@object-ui/plugin-report 6.2.3 → 7.1.0

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.
Files changed (33) hide show
  1. package/CHANGELOG.md +114 -0
  2. package/dist/DatasetReportRenderer.d.ts +95 -0
  3. package/dist/{packages/plugin-report/src/LiveReportExporter.d.ts → LiveReportExporter.d.ts} +1 -1
  4. package/dist/{packages/plugin-report/src/ReportExportEngine.d.ts → ReportExportEngine.d.ts} +1 -1
  5. package/dist/ReportRenderer.d.ts +45 -0
  6. package/dist/{packages/plugin-report/src/ReportViewer.d.ts → ReportViewer.d.ts} +1 -1
  7. package/dist/{packages/plugin-report/src/formatValue.d.ts → formatValue.d.ts} +1 -1
  8. package/dist/index.d.ts +13 -2
  9. package/dist/index.js +586 -3685
  10. package/dist/index.umd.cjs +18 -18
  11. package/dist/mergeFilters.d.ts +10 -0
  12. package/package.json +15 -15
  13. package/dist/packages/plugin-report/src/ChartConfig.d.ts +0 -8
  14. package/dist/packages/plugin-report/src/ColumnsEditor.d.ts +0 -16
  15. package/dist/packages/plugin-report/src/FieldPickerDialog.d.ts +0 -36
  16. package/dist/packages/plugin-report/src/GroupingsBuilder.d.ts +0 -8
  17. package/dist/packages/plugin-report/src/JoinedBlocksEditor.d.ts +0 -31
  18. package/dist/packages/plugin-report/src/JoinedReportRenderer.d.ts +0 -47
  19. package/dist/packages/plugin-report/src/MatrixRenderer.d.ts +0 -51
  20. package/dist/packages/plugin-report/src/MatrixRenderer.stories.d.ts +0 -24
  21. package/dist/packages/plugin-report/src/ReportBuilder.d.ts +0 -10
  22. package/dist/packages/plugin-report/src/ReportConfigPanel.d.ts +0 -24
  23. package/dist/packages/plugin-report/src/ReportRenderer.d.ts +0 -44
  24. package/dist/packages/plugin-report/src/ScheduleConfig.d.ts +0 -7
  25. package/dist/packages/plugin-report/src/SpecReportGrid.d.ts +0 -49
  26. package/dist/packages/plugin-report/src/SpecReportGrid.stories.d.ts +0 -31
  27. package/dist/packages/plugin-report/src/buildChartData.d.ts +0 -38
  28. package/dist/packages/plugin-report/src/drill.d.ts +0 -63
  29. package/dist/packages/plugin-report/src/editorTypes.d.ts +0 -20
  30. package/dist/packages/plugin-report/src/hooks/useReportData.d.ts +0 -131
  31. package/dist/packages/plugin-report/src/index.d.ts +0 -26
  32. package/dist/packages/plugin-report/src/specFilterAdapter.d.ts +0 -38
  33. /package/dist/{packages/plugin-report/src/LegacyReportRenderer.d.ts → LegacyReportRenderer.d.ts} +0 -0
package/dist/index.js CHANGED
@@ -1,58 +1,56 @@
1
- import { ComponentRegistry as e } from "@object-ui/core";
2
- import * as t from "react";
3
- import n, { useCallback as r, useEffect as i, useMemo as a, useRef as o, useState as s } from "react";
4
- import { isJoinedSpecReport as c, isSpecReport as l } from "@object-ui/types";
5
- import { SchemaRenderer as u, SchemaRendererContext as d } from "@object-ui/react";
6
- import { Badge as f, Button as p, Card as m, CardContent as h, CardDescription as g, CardHeader as _, CardTitle as v, Checkbox as y, ConfigPanelRenderer as b, Dialog as x, DialogContent as S, DialogDescription as C, DialogFooter as w, DialogHeader as T, DialogTitle as E, DialogTrigger as D, Input as O, Label as k, Skeleton as A, Tabs as j, TabsContent as M, TabsList as ee, TabsTrigger as N, cn as P, useConfigDraft as F } from "@object-ui/components";
7
- import { Fragment as I, jsx as L, jsxs as R } from "react/jsx-runtime";
8
- import { useTranslation as z } from "react-i18next";
9
- import { ObjectGrid as B } from "@object-ui/plugin-grid";
10
- import { useSafeFieldLabel as V } from "@object-ui/i18n";
11
- import { AlertTriangle as H, ArrowDown as U, ArrowUp as te, Calendar as ne, ChevronDown as re, ChevronRight as ie, Clock as ae, Download as oe, Filter as se, Layers as ce, Mail as le, Plus as W, Printer as ue, RefreshCw as de, Save as fe, Search as pe, Settings as me, Trash2 as G } from "lucide-react";
12
- import { getCellRenderer as he, resolveCellRendererType as ge } from "@object-ui/fields";
1
+ import { ComponentRegistry as e, buildDatasetDrillFilter as t, buildDatasetFieldHelpers as n, formatDimensionValue as r, formatMeasure as i } from "@object-ui/core";
2
+ import * as a from "react";
3
+ import o from "react";
4
+ import { isSpecReport as s, specReportToPresentation as c } from "@object-ui/types";
5
+ import { SchemaRenderer as l, SchemaRendererContext as u } from "@object-ui/react";
6
+ import { Badge as d, Button as f, Card as p, CardContent as m, CardDescription as h, CardHeader as g, CardTitle as _, Skeleton as v } from "@object-ui/components";
7
+ import { jsx as y, jsxs as b } from "react/jsx-runtime";
8
+ import { AlertTriangle as x, Download as S, Loader2 as C, Printer as w, RefreshCw as T, Table2 as E } from "lucide-react";
9
+ import { getCellRenderer as D, resolveCellRendererType as O } from "@object-ui/fields";
10
+ import { useSafeFieldLabel as k, useSafeTranslate as A } from "@object-ui/i18n";
13
11
  //#region src/LegacyReportRenderer.tsx
14
- var _e = ({ schema: t }) => {
12
+ var j = ({ schema: t }) => {
15
13
  let { title: n, description: r, data: i, columns: a } = t;
16
14
  t.chart?.type;
17
15
  let o = !!t.chart;
18
- return /* @__PURE__ */ R(m, {
16
+ return /* @__PURE__ */ b(p, {
19
17
  className: `h-full flex flex-col ${t.className || ""}`,
20
- children: [/* @__PURE__ */ R(_, { children: [n && /* @__PURE__ */ L(v, { children: n }), r && /* @__PURE__ */ L(g, { children: r })] }), /* @__PURE__ */ R(h, {
18
+ children: [/* @__PURE__ */ b(g, { children: [n && /* @__PURE__ */ y(_, { children: n }), r && /* @__PURE__ */ y(h, { children: r })] }), /* @__PURE__ */ b(m, {
21
19
  className: "flex-1 overflow-auto space-y-4",
22
20
  children: [o && (() => {
23
21
  let n = t.chart?.type, r = n ? e.get(n) : null;
24
- return r ||= e.get("chart"), r ? /* @__PURE__ */ L("div", {
22
+ return r ||= e.get("chart"), r ? /* @__PURE__ */ y("div", {
25
23
  className: "min-h-[300px] border rounded-lg p-4 bg-background/50",
26
- children: /* @__PURE__ */ L(r, { schema: {
24
+ children: /* @__PURE__ */ y(r, { schema: {
27
25
  ...t.chart,
28
26
  data: t.chart.data || i
29
27
  } })
30
- }) : /* @__PURE__ */ R("div", {
28
+ }) : /* @__PURE__ */ b("div", {
31
29
  className: "min-h-[100px] border rounded-md p-4 bg-muted/20 text-muted-foreground flex items-center justify-center",
32
30
  children: ["Unknown component type: ", n || "chart"]
33
31
  });
34
- })(), i && i.length > 0 && /* @__PURE__ */ L("div", {
32
+ })(), i && i.length > 0 && /* @__PURE__ */ y("div", {
35
33
  className: "border rounded-lg",
36
34
  children: (() => {
37
35
  let t = e.get("grid") || e.get("table");
38
- return t ? /* @__PURE__ */ L(t, { schema: {
36
+ return t ? /* @__PURE__ */ y(t, { schema: {
39
37
  type: "grid",
40
38
  rowData: i,
41
39
  columnDefs: a,
42
40
  domLayout: "autoHeight"
43
- } }) : /* @__PURE__ */ L("div", {
41
+ } }) : /* @__PURE__ */ y("div", {
44
42
  className: "overflow-x-auto",
45
- children: /* @__PURE__ */ R("table", {
43
+ children: /* @__PURE__ */ b("table", {
46
44
  className: "w-full text-sm text-left",
47
- children: [/* @__PURE__ */ L("thead", {
45
+ children: [/* @__PURE__ */ y("thead", {
48
46
  className: "text-xs uppercase bg-muted",
49
- children: /* @__PURE__ */ L("tr", { children: a?.map((e) => /* @__PURE__ */ L("th", {
47
+ children: /* @__PURE__ */ y("tr", { children: a?.map((e) => /* @__PURE__ */ y("th", {
50
48
  className: "px-6 py-3",
51
49
  children: e.headerName || e.label || e.field
52
50
  }, e.field)) })
53
- }), /* @__PURE__ */ L("tbody", { children: i.map((e, t) => /* @__PURE__ */ L("tr", {
51
+ }), /* @__PURE__ */ y("tbody", { children: i.map((e, t) => /* @__PURE__ */ y("tr", {
54
52
  className: "bg-background border-b",
55
- children: a?.map((t) => /* @__PURE__ */ L("td", {
53
+ children: a?.map((t) => /* @__PURE__ */ y("td", {
56
54
  className: "px-6 py-4",
57
55
  children: e[t.field]
58
56
  }, t.field))
@@ -65,1142 +63,30 @@ var _e = ({ schema: t }) => {
65
63
  });
66
64
  };
67
65
  //#endregion
68
- //#region src/hooks/useReportData.ts
69
- function K(e) {
70
- return e.aggregate ? `${e.field}__${e.aggregate}` : e.field;
71
- }
72
- function ve(e, t) {
73
- if (e == null) return null;
74
- let n = e instanceof Date ? e : new Date(String(e));
75
- if (Number.isNaN(n.getTime())) return null;
76
- let r = n.getUTCFullYear(), i = n.getUTCMonth(), a = n.getUTCDate();
77
- switch (t) {
78
- case "year": return String(r);
79
- case "quarter": return `${r}-Q${Math.floor(i / 3) + 1}`;
80
- case "month": return `${r}-${String(i + 1).padStart(2, "0")}`;
81
- case "week": {
82
- let e = new Date(Date.UTC(r, i, a)), t = e.getUTCDay() || 7;
83
- e.setUTCDate(e.getUTCDate() + 4 - t);
84
- let n = new Date(Date.UTC(e.getUTCFullYear(), 0, 1)), o = Math.ceil(((e.getTime() - n.getTime()) / 864e5 + 1) / 7);
85
- return `${e.getUTCFullYear()}-W${String(o).padStart(2, "0")}`;
86
- }
87
- case "day": return `${r}-${String(i + 1).padStart(2, "0")}-${String(a).padStart(2, "0")}`;
88
- default: return String(e);
89
- }
90
- }
91
- function q(e, t) {
92
- let n = e[t.field];
93
- return t.dateGranularity ? ve(n, t.dateGranularity) ?? "(empty)" : n == null || n === "" ? "(empty)" : String(n);
94
- }
95
- function J(e, t) {
96
- let n = {};
97
- for (let r of t) {
98
- if (!r.aggregate) {
99
- let t = e.find((e) => e[r.field] != null);
100
- n[K(r)] = t ? t[r.field] : null;
101
- continue;
102
- }
103
- let t = e.map((e) => e[r.field]);
104
- switch (r.aggregate) {
105
- case "count":
106
- n[K(r)] = t.length;
107
- break;
108
- case "unique": {
109
- let e = /* @__PURE__ */ new Set();
110
- for (let n of t) n != null && e.add(n);
111
- n[K(r)] = e.size;
112
- break;
113
- }
114
- case "sum": {
115
- let e = 0;
116
- for (let n of t) e += Number(n) || 0;
117
- n[K(r)] = e;
118
- break;
119
- }
120
- case "avg": {
121
- let e = 0, i = 0;
122
- for (let n of t) {
123
- if (n == null || n === "") continue;
124
- let t = Number(n);
125
- Number.isNaN(t) || (e += t, i += 1);
126
- }
127
- n[K(r)] = i === 0 ? null : e / i;
128
- break;
129
- }
130
- case "min": {
131
- let e = null;
132
- for (let n of t) {
133
- if (n == null) continue;
134
- let t = Number(n);
135
- Number.isNaN(t) || (e === null || t < e) && (e = t);
136
- }
137
- n[K(r)] = e;
138
- break;
139
- }
140
- case "max": {
141
- let e = null;
142
- for (let n of t) {
143
- if (n == null) continue;
144
- let t = Number(n);
145
- Number.isNaN(t) || (e === null || t > e) && (e = t);
146
- }
147
- n[K(r)] = e;
148
- break;
149
- }
150
- default: n[K(r)] = null;
151
- }
152
- }
153
- return n;
154
- }
155
- function ye(e, t, n, r = {}, i = []) {
156
- if (t.length === 0) return [];
157
- let [a, ...o] = t, s = /* @__PURE__ */ new Map();
158
- for (let t of e) {
159
- let e = q(t, a), n = s.get(e);
160
- n || (n = [], s.set(e, n)), n.push(t);
161
- }
162
- let c = [];
163
- for (let [e, t] of s) {
164
- let s = {
165
- ...r,
166
- [a.field]: e
167
- }, l = [...i, e], u = J(t, n), d = o.length > 0 ? ye(t, o, n, s, l) : void 0;
168
- c.push({
169
- groupKey: s,
170
- groupPath: l,
171
- values: u,
172
- count: t.length,
173
- children: d
174
- });
175
- }
176
- let l = a.sort === "desc" ? -1 : 1;
177
- return c.sort((e, t) => {
178
- let n = String(e.groupPath[e.groupPath.length - 1]), r = String(t.groupPath[t.groupPath.length - 1]);
179
- return n.localeCompare(r) * l;
180
- }), typeof a.limit == "number" && a.limit > 0 ? c.slice(0, a.limit) : c;
181
- }
182
- function be(e, t, n, r) {
183
- let i = xe(e, n), a = xe(e, r), o = {}, s = {}, c = {};
184
- for (let c of i) {
185
- o[c.id] = {};
186
- let i = Se(e, c.key, n);
187
- s[c.id] = J(i, t);
188
- for (let e of a) {
189
- let n = Se(i, e.key, r);
190
- n.length !== 0 && (o[c.id][e.id] = J(n, t));
191
- }
192
- }
193
- for (let n of a) {
194
- let i = Se(e, n.key, r);
195
- c[n.id] = J(i, t);
196
- }
197
- return {
198
- rowHeaders: i,
199
- colHeaders: a,
200
- cells: o,
201
- rowTotals: s,
202
- colTotals: c,
203
- grandTotal: J(e, t),
204
- columns: t,
205
- downGroupings: n,
206
- acrossGroupings: r
207
- };
208
- }
209
- function xe(e, t) {
210
- if (t.length === 0) return [{
211
- key: {},
212
- path: [],
213
- id: ""
214
- }];
215
- let n = /* @__PURE__ */ new Map();
216
- for (let r of e) {
217
- let e = [], i = {};
218
- for (let n of t) {
219
- let t = q(r, n);
220
- e.push(t), i[n.field] = t;
221
- }
222
- let a = e.join("");
223
- n.has(a) || n.set(a, {
224
- key: i,
225
- path: e,
226
- id: a
227
- });
228
- }
229
- let r = Array.from(n.values());
230
- r.sort((e, n) => {
231
- for (let r = 0; r < t.length; r++) {
232
- let i = t[r].sort === "desc" ? -1 : 1, a = e.path[r].localeCompare(n.path[r]) * i;
233
- if (a !== 0) return a;
234
- }
235
- return 0;
236
- });
237
- let i = t[0].limit;
238
- if (typeof i == "number" && i > 0) {
239
- let e = /* @__PURE__ */ new Set();
240
- for (let t of r) e.size >= i && !e.has(t.path[0]) || e.add(t.path[0]);
241
- return r.filter((t) => e.has(t.path[0]));
242
- }
243
- return r;
244
- }
245
- function Se(e, t, n) {
246
- let r = Object.entries(t);
247
- if (r.length === 0) return e;
248
- let i = /* @__PURE__ */ new Map();
249
- for (let e of n) i.set(e.field, e);
250
- return e.filter((e) => {
251
- for (let [t, n] of r) {
252
- let r = i.get(t);
253
- if ((r ? q(e, r) : e[t] == null ? "(null)" : String(e[t])) !== String(n)) return !1;
254
- }
255
- return !0;
256
- });
257
- }
258
- function Y(e, t) {
259
- let n = {};
260
- for (let r of t) {
261
- if (!r.aggregate) continue;
262
- let t = K(r), i = 0, a = 0, o = null, s = null;
263
- for (let n of e) {
264
- let e = n[t];
265
- typeof e == "number" && (i += e, a += 1, (o == null || e < o) && (o = e), (s == null || e > s) && (s = e));
266
- }
267
- r.aggregate === "min" ? n[t] = o : r.aggregate === "max" ? n[t] = s : r.aggregate === "avg" ? n[t] = a === 0 ? null : i / a : n[t] = i;
268
- }
269
- return n;
270
- }
271
- function Ce(e, t, n, r) {
272
- let i = we(e, n), a = we(e, r), o = {}, s = {}, c = {};
273
- for (let n of i) {
274
- o[n.id] = {};
275
- let r = e.filter((e) => Te(e, n.key));
276
- s[n.id] = Y(r, t);
277
- for (let e of a) {
278
- let i = r.filter((t) => Te(t, e.key));
279
- if (i.length === 0) continue;
280
- let a = {};
281
- for (let e of t) {
282
- if (!e.aggregate) continue;
283
- let t = K(e);
284
- a[t] = i[0][t];
285
- }
286
- o[n.id][e.id] = a;
287
- }
288
- }
289
- for (let n of a) {
290
- let r = e.filter((e) => Te(e, n.key));
291
- c[n.id] = Y(r, t);
292
- }
293
- return {
294
- rowHeaders: i,
295
- colHeaders: a,
296
- cells: o,
297
- rowTotals: s,
298
- colTotals: c,
299
- grandTotal: Y(e, t),
300
- columns: t,
301
- downGroupings: n,
302
- acrossGroupings: r
303
- };
304
- }
305
- function we(e, t) {
306
- if (t.length === 0) return [{
307
- key: {},
308
- path: [],
309
- id: ""
310
- }];
311
- let n = /* @__PURE__ */ new Map();
312
- for (let r of e) {
313
- let e = [], i = {};
314
- for (let n of t) {
315
- let t = r[n.field], a = t == null ? "(null)" : String(t);
316
- e.push(a), i[n.field] = a;
317
- }
318
- let a = e.join("");
319
- n.has(a) || n.set(a, {
320
- key: i,
321
- path: e,
322
- id: a
323
- });
324
- }
325
- let r = Array.from(n.values());
326
- return r.sort((e, n) => {
327
- for (let r = 0; r < t.length; r++) {
328
- let i = t[r].sort === "desc" ? -1 : 1, a = e.path[r].localeCompare(n.path[r]) * i;
329
- if (a !== 0) return a;
330
- }
331
- return 0;
332
- }), r;
333
- }
334
- function Te(e, t) {
335
- for (let [n, r] of Object.entries(t)) if ((e[n] == null ? "(null)" : String(e[n])) !== String(r)) return !1;
336
- return !0;
337
- }
338
- function X(e, t) {
339
- let n = e && Object.keys(e).length > 0, r = t && Object.keys(t).length > 0;
340
- if (n && r) return { $and: [e, t] };
341
- if (n) return e;
342
- if (r) return t;
343
- }
344
- function Ee(e) {
345
- let t = /* @__PURE__ */ new Set();
346
- for (let n of e.groupingsDown ?? []) t.add(n.field);
347
- for (let n of e.groupingsAcross ?? []) t.add(n.field);
348
- for (let n of e.columns ?? []) t.add(n.field);
349
- for (let n of e.sort ?? []) t.add(n.field);
350
- return Array.from(t);
351
- }
352
- function De(e, t, n) {
353
- let r = [...e.groupingsDown ?? [], ...e.groupingsAcross ?? []], i = (e.columns ?? []).filter((e) => !!e.aggregate);
354
- if (r.length === 0 && i.length === 0) return null;
355
- let a = r.map((e) => e.dateGranularity ? {
356
- field: e.field,
357
- dateGranularity: e.dateGranularity
358
- } : e.field), o = i.map((e) => ({
359
- function: e.aggregate === "unique" ? "count_distinct" : e.aggregate,
360
- field: e.field,
361
- alias: K(e)
362
- })), s = X(e.filter, t), c = {
363
- object: e.objectName,
364
- limit: n
365
- };
366
- return a.length > 0 && (c.groupBy = a), o.length > 0 && (c.aggregations = o), s && (c.where = s), c;
367
- }
368
- function Oe(e, t, n) {
369
- for (let [r, i] of Object.entries(t)) {
370
- let t = n.find((e) => e.field === r);
371
- if ((t ? q(e, t) : String(e[r] ?? "(empty)")) !== String(i)) return !1;
372
- }
373
- return !0;
374
- }
375
- var Z = [];
376
- function ke(e, t = {}) {
377
- let { dataSource: n, runtimeFilter: c, maxRows: l = 5e3, enabled: u = !0, rows: d, preferServerAggregation: f = !0 } = t, [p, m] = s(d ?? Z), [h, g] = s(!1), [_, v] = s(() => d ? !1 : !!(e && u && n)), [y, b] = s(null), x = o(0), S = r(async () => {
378
- if (!e || !u) return;
379
- if (d) {
380
- m(d), g(!1);
381
- return;
382
- }
383
- if (!n) {
384
- m(Z);
385
- return;
386
- }
387
- let t = ++x.current;
388
- v(!0), b(null);
389
- try {
390
- let r = f ? De(e, c, l) : null;
391
- if (r && typeof n.aggregate == "function") try {
392
- let i = Ae(await n.aggregate(e.objectName, r));
393
- if (t !== x.current) return;
394
- m(i), g(!0);
395
- return;
396
- } catch (e) {
397
- typeof console < "u" && console.warn && console.warn("[useReportData] dataSource.aggregate() failed, falling back to find():", e);
398
- }
399
- if (typeof n.find != "function") {
400
- m(Z), g(!1);
401
- return;
402
- }
403
- let i = X(e.filter, c), a = Ee(e), o = { $top: l };
404
- i && (o.$filter = i), a.length > 0 && (o.$select = a), e.sort && e.sort.length > 0 && (o.$orderBy = e.sort.map((e) => `${e.field} ${e.direction ?? "asc"}`).join(","));
405
- let s = Ae(await n.find(e.objectName, o));
406
- if (t !== x.current) return;
407
- m(s), g(!1);
408
- } catch (e) {
409
- if (t !== x.current) return;
410
- b(e instanceof Error ? e : Error(String(e))), m(Z), g(!1);
411
- } finally {
412
- t === x.current && v(!1);
413
- }
414
- }, [
415
- e,
416
- u,
417
- d,
418
- n,
419
- c,
420
- l,
421
- f
422
- ]);
423
- i(() => {
424
- S();
425
- }, [S]);
426
- let { rows: C, totals: w, pivot: T } = a(() => {
427
- if (!e) return {
428
- rows: [],
429
- totals: {},
430
- pivot: null
431
- };
432
- let t = e.groupingsDown ?? [], n = e.groupingsAcross ?? [], r = e.columns ?? [], i = n.length > 0;
433
- if (h) {
434
- let e = [...t, ...n], a = p.map((t) => {
435
- let n = {}, r = [];
436
- for (let i of e) {
437
- let e = t[i.field];
438
- n[i.field] = e, r.push(e == null ? "(null)" : String(e));
439
- }
440
- let i = { ...t };
441
- for (let t of e) delete i[t.field];
442
- return {
443
- groupKey: n,
444
- groupPath: r,
445
- values: i,
446
- count: 1
447
- };
448
- }), o = Y(p, r), s = i ? Ce(p, r, t, n) : null;
449
- return {
450
- rows: i && s ? s.rowHeaders.map((e) => ({
451
- groupKey: e.key,
452
- groupPath: e.path,
453
- values: s.rowTotals[e.id] ?? {},
454
- count: 1
455
- })) : a,
456
- totals: o,
457
- pivot: s
458
- };
459
- }
460
- let a = i ? t : [...t, ...n];
461
- return {
462
- rows: a.length > 0 ? ye(p, a, r) : p.map((e) => ({
463
- groupKey: {},
464
- groupPath: [],
465
- values: r.length > 0 ? J([e], r) : { ...e },
466
- count: 1
467
- })),
468
- totals: J(p, r),
469
- pivot: i ? be(p, r, t, n) : null
470
- };
471
- }, [
472
- e,
473
- p,
474
- h
475
- ]);
476
- return {
477
- rows: C,
478
- rawRows: p,
479
- totals: w,
480
- pivot: T,
481
- serverAggregated: h,
482
- loading: _,
483
- error: y,
484
- refetch: S,
485
- drillDown: r((t) => {
486
- if (!e) return [];
487
- let n = [...e.groupingsDown ?? [], ...e.groupingsAcross ?? []];
488
- return p.filter((e) => Oe(e, t, n));
489
- }, [e, p])
490
- };
491
- }
492
- function Ae(e) {
493
- if (Array.isArray(e)) return e;
494
- if (e && typeof e == "object") {
495
- let t = e;
496
- if (Array.isArray(t.data)) return t.data;
497
- if (Array.isArray(t.records)) return t.records;
498
- if (Array.isArray(t.results)) return t.results;
499
- if (Array.isArray(t.value)) return t.value;
500
- }
501
- return Z;
502
- }
503
- //#endregion
504
- //#region src/buildChartData.ts
505
- function je(e) {
506
- return e.aggregate ? `${e.field}__${e.aggregate}` : e.field;
507
- }
508
- function Me(e) {
509
- let t = [], n = (e) => {
510
- e.children && e.children.length > 0 ? e.children.forEach(n) : t.push(e);
511
- };
512
- return e.forEach(n), t;
513
- }
514
- function Ne({ report: e, rows: t, labels: n }) {
515
- let r = e.chart;
516
- if (!r || !r.type) return { schema: null };
517
- let i = e.groupingsDown ?? [], a = r.xAxis || (i.length > 0 ? i[0]?.field : void 0);
518
- if (!a) return {
519
- schema: null,
520
- diagnostic: "chart.xAxis missing and no groupingsDown[0] to default to."
521
- };
522
- let o = e.columns ?? [], s = r.yAxis, c = "count", l = "Count", u = !0;
523
- if (s) {
524
- let e = o.find((e) => e.field === s && e.aggregate);
525
- e ? (c = je(e), l = n?.resolveColumnLabel?.(e) ?? (typeof e.label == "string" ? e.label : `${e.aggregate}(${e.field})`), u = !1) : (c = "count", l = n?.resolveCountLabel?.(s) ?? `Count of ${s}`);
526
- }
527
- let d = Me(t), f = /* @__PURE__ */ new Map();
528
- for (let e of d) {
529
- let t = e.groupKey[a];
530
- if (t === void 0) continue;
531
- let n = String(t ?? ""), r = u ? e.count : Number(e.values[c] ?? 0), i = f.get(n);
532
- i ? i.measure += Number.isFinite(r) ? r : 0 : f.set(n, {
533
- x: t,
534
- measure: Number.isFinite(r) ? r : 0
535
- });
536
- }
537
- let p = Array.from(f.values()).map((e) => {
538
- let t = n?.resolveAxisValue?.(a, e.x) ?? e.x ?? "(null)";
539
- return {
540
- [a]: t,
541
- [c]: e.measure
542
- };
543
- });
544
- return (r.type === "pie" || r.type === "donut" || r.type === "funnel") && (p = [...p].sort((e, t) => Number(t[c] ?? 0) - Number(e[c] ?? 0))), { schema: {
545
- type: "chart",
546
- chartType: r.type,
547
- data: p,
548
- xAxisKey: a,
549
- series: [{
550
- dataKey: c,
551
- label: l
552
- }],
553
- title: r.title,
554
- showLegend: r.showLegend ?? !0,
555
- showDataLabels: r.showDataLabels ?? !1,
556
- className: "w-full h-[320px]"
557
- } };
558
- }
559
- //#endregion
560
- //#region src/drill.ts
561
- function Pe(e, t, n = {}) {
562
- let r = X(X(e.filter, n.runtimeFilter), Object.keys(t).length > 0 ? t : void 0);
563
- return {
564
- type: "drill",
565
- name: `drill-${e.name}`,
566
- objectName: e.objectName,
567
- ...r ? { filter: r } : {},
568
- view: n.view ?? "list",
569
- ...n.recordId === void 0 ? {} : { recordId: n.recordId },
570
- openIn: n.openIn ?? "current"
571
- };
572
- }
573
- function Fe(e) {
574
- return !!e && e.type === "drill";
575
- }
576
- function Ie(e) {
577
- return async (t) => {
578
- if (!Fe(t)) return {
579
- success: !1,
580
- error: "drill handler invoked with non-drill action"
581
- };
582
- try {
583
- return await e.navigate({
584
- objectName: t.objectName,
585
- filter: t.filter,
586
- view: t.view,
587
- recordId: t.recordId,
588
- openIn: t.openIn
589
- }), { success: !0 };
590
- } catch (e) {
591
- return {
592
- success: !1,
593
- error: e instanceof Error ? e.message : String(e)
594
- };
595
- }
596
- };
597
- }
598
- function Le(e, t) {
599
- return e.registerHandler("drill", Ie(t)), () => e.unregisterHandler("drill");
600
- }
601
- //#endregion
602
- //#region src/SpecReportGrid.tsx
603
- function Re(e) {
604
- return e ? e === "unique" ? "count_distinct" : e : null;
605
- }
606
- function ze(e) {
607
- if (!(!e || e.length === 0)) return { fields: e.map((e) => ({
608
- field: e.field,
609
- order: e.sort ?? "asc",
610
- collapsed: !1
611
- })) };
612
- }
613
- function Be(e) {
614
- return (e.columns ?? []).map((e) => {
615
- let t = { field: e.field };
616
- return e.label && (t.label = typeof e.label == "string" ? e.label : String(e.label)), e.format && (t.format = e.format), e.width && (t.width = e.width), t;
617
- });
618
- }
619
- var Ve = {
620
- padding: "12px 16px",
621
- border: "1px dashed rgb(203 213 225)",
622
- borderRadius: 8,
623
- color: "rgb(100 116 139)",
624
- fontSize: 14
625
- }, He = ({ report: e, dataSource: n, rows: r, runtimeFilter: i, onDrillDown: a, actionRunner: o, drillView: s, drillOpenIn: c, className: l }) => {
626
- let d = e.type ?? "tabular", { t: f } = z(), { fieldLabel: p, translateOptions: m } = V(), [h, g] = t.useState(null);
627
- t.useEffect(() => {
628
- let t = n;
629
- if (!t || typeof t.getObjectSchema != "function" || !e.objectName) return;
630
- let r = !1;
631
- return t.getObjectSchema(e.objectName).then((e) => {
632
- r || g(e ?? null);
633
- }).catch(() => {}), () => {
634
- r = !0;
635
- };
636
- }, [n, e.objectName]);
637
- let _ = t.useCallback((t) => {
638
- if (t.label) return String(t.label);
639
- let n = h?.fields?.[t.field]?.label ?? t.field, r = p(e.objectName, t.field, n);
640
- return t.aggregate ? `${r} · ${f(`report.aggregate.${t.aggregate}`, t.aggregate)}` : r;
641
- }, [
642
- h,
643
- e.objectName,
644
- p,
645
- f
646
- ]), v = t.useCallback((t, n) => {
647
- if (n == null) return;
648
- let r = h?.fields?.[t];
649
- if (!r || !(r.type === "select" || r.type === "status") || !Array.isArray(r.options) || r.options.length === 0) return;
650
- let i = m(e.objectName, t, r.options), a = String(n);
651
- for (let e of i) if (e && e.value !== void 0 && e.value !== null && String(e.value) === a) return e.label == null ? a : String(e.label);
652
- }, [
653
- h,
654
- e.objectName,
655
- m
656
- ]), { rawRows: y, rows: b, totals: x, serverAggregated: S, loading: C, error: w, drillDown: T } = ke(e, {
657
- dataSource: n,
658
- rows: r,
659
- runtimeFilter: i
660
- });
661
- if (d === "matrix" || d === "joined") return /* @__PURE__ */ R("div", {
662
- className: l,
663
- style: Ve,
664
- children: [
665
- "Report type ",
666
- /* @__PURE__ */ L("code", { children: d }),
667
- " is not yet supported by SpecReportGrid. It will be rendered by a dedicated component in M2 (matrix) / M3 (joined)."
668
- ]
669
- });
670
- let E = t.useMemo(() => {
671
- if (S) {
672
- let t = (e.groupingsDown ?? []).map((e) => ({
673
- field: e.field,
674
- label: e.field.replace(/_/g, " ").replace(/\b\w/g, (e) => e.toUpperCase())
675
- })), n = (e.columns ?? []).filter((e) => e.aggregate).map((e) => ({
676
- field: K(e),
677
- label: `${(typeof e.label == "string" ? e.label : null) ?? e.field} (${e.aggregate})`,
678
- ...e.format ? { format: e.format } : {}
679
- }));
680
- return {
681
- type: "object-grid",
682
- objectName: e.objectName,
683
- columns: [...t, ...n]
684
- };
685
- }
686
- let t = d === "summary" ? ze(e.groupingsDown) : void 0, n = (e.columns ?? []).map((e) => {
687
- let t = Re(e.aggregate);
688
- return t ? {
689
- field: e.field,
690
- type: t
691
- } : null;
692
- }).filter((e) => e !== null);
693
- return {
694
- type: "object-grid",
695
- objectName: e.objectName,
696
- columns: Be(e),
697
- grouping: t,
698
- aggregations: n.length > 0 ? n : void 0
699
- };
700
- }, [
701
- e,
702
- d,
703
- S
704
- ]), D = y, O = t.useCallback((t) => {
705
- let n = e.groupingsDown ?? [], r = {};
706
- for (let e of n) r[e.field] = t[e.field];
707
- if (o) {
708
- let t = Pe(e, r, {
709
- runtimeFilter: i,
710
- view: s,
711
- openIn: c
712
- });
713
- o.execute(t);
714
- }
715
- a && a(r, T(r));
716
- }, [
717
- o,
718
- T,
719
- c,
720
- s,
721
- a,
722
- e,
723
- i
724
- ]), k = !!a || !!o, A = (e.columns ?? []).filter((e) => e.aggregate), j = A.length > 0 && x && Object.keys(x).length > 0, M = t.useMemo(() => d !== "summary" || !e.chart || !e.chart.type ? null : Ne({
725
- report: e,
726
- rows: b,
727
- labels: {
728
- resolveColumnLabel: _,
729
- resolveCountLabel: (t) => {
730
- let n = h?.fields?.[t]?.label ?? t;
731
- return `${p(e.objectName, t, n)} · ${f("report.aggregate.count", "Count")}`;
732
- },
733
- resolveAxisValue: v
734
- }
735
- }).schema, [
736
- e,
737
- b,
738
- d,
739
- _,
740
- v,
741
- h,
742
- p,
743
- f
744
- ]);
745
- return /* @__PURE__ */ R("div", {
746
- className: l,
747
- "data-testid": "spec-report-grid",
748
- "aria-busy": C || void 0,
749
- children: [
750
- w ? /* @__PURE__ */ L("div", {
751
- role: "alert",
752
- style: {
753
- ...Ve,
754
- color: "rgb(190 18 60)"
755
- },
756
- children: w.message
757
- }) : null,
758
- j ? /* @__PURE__ */ R("div", {
759
- "data-testid": "spec-report-totals",
760
- className: "mb-3 flex flex-wrap items-baseline gap-x-6 gap-y-1 rounded-md border bg-muted/40 px-3 py-2 text-sm",
761
- children: [/* @__PURE__ */ L("span", {
762
- className: "text-xs font-medium uppercase tracking-wide text-muted-foreground",
763
- children: f("report.totals", "Totals")
764
- }), A.map((e) => {
765
- let t = K(e), n = x[t], r = _(e), i = typeof n == "number" ? n.toLocaleString(void 0, { maximumFractionDigits: 2 }) : String(n ?? "—");
766
- return /* @__PURE__ */ R("span", {
767
- "data-testid": `spec-report-total-${t}`,
768
- className: "inline-flex items-baseline gap-1.5",
769
- children: [/* @__PURE__ */ R("span", {
770
- className: "text-muted-foreground",
771
- children: [r, ":"]
772
- }), /* @__PURE__ */ L("span", {
773
- className: "font-mono font-medium tabular-nums",
774
- children: i
775
- })]
776
- }, t);
777
- })]
778
- }) : null,
779
- M ? /* @__PURE__ */ L("div", {
780
- className: "mb-4",
781
- "data-testid": "spec-report-chart",
782
- children: /* @__PURE__ */ L(u, { schema: M })
783
- }) : null,
784
- /* @__PURE__ */ L(B, {
785
- schema: E,
786
- data: D,
787
- dataSource: n,
788
- onRowClick: k ? O : void 0
789
- })
790
- ]
791
- });
792
- };
793
- He.displayName = "SpecReportGrid";
794
- //#endregion
795
- //#region src/MatrixRenderer.tsx
796
- var Ue = "—";
797
- function We(e) {
798
- return e == null ? Ue : typeof e == "number" ? e.toLocaleString() : String(e);
799
- }
800
- function Ge(e, t, n) {
801
- if (e == null || e === "" || e === "(null)") return n;
802
- let r = t?.options;
803
- if (r) {
804
- let t = r.get(e);
805
- if (t !== void 0 && t !== "") return t;
806
- }
807
- return e;
808
- }
809
- function Ke({ header: e, groupings: t, metaByField: n, fallback: r, emptyLabel: i }) {
810
- return e.path.length === 0 ? /* @__PURE__ */ L(I, { children: r }) : /* @__PURE__ */ L(I, { children: e.path.map((e, r) => {
811
- let a = t[r]?.field;
812
- return Ge(e, a ? n.get(a) : void 0, i);
813
- }).join(" / ") });
814
- }
815
- var qe = ({ report: e, dataSource: n, rows: r, runtimeFilter: i, onCellClick: a, actionRunner: o, drillView: s, drillOpenIn: c, className: l, emptyCellText: u = Ue }) => {
816
- let { pivot: d, loading: f, error: p } = ke(e, {
817
- dataSource: n,
818
- rows: r,
819
- runtimeFilter: i
820
- }), m = e.columns ?? [], h = m.length > 1, { fieldLabel: g, translateOptions: _ } = V(), { t: v } = z(), y = v("report.emptyLabel", "(Empty)"), b = v("report.allLabel", "(All)"), [x, S] = t.useState(null);
821
- t.useEffect(() => {
822
- let t = n;
823
- if (!t || typeof t.getObjectSchema != "function" || !e.objectName) return;
824
- let r = !1;
825
- return t.getObjectSchema(e.objectName).then((e) => {
826
- r || S(e ?? null);
827
- }).catch(() => {}), () => {
828
- r = !0;
829
- };
830
- }, [n, e.objectName]);
831
- let C = e.groupingsDown ?? [], w = e.groupingsAcross ?? [], T = t.useMemo(() => {
832
- let t = /* @__PURE__ */ new Map(), n = x?.fields ?? {}, r = [...C, ...w];
833
- for (let i of r) {
834
- let r = n[i.field], a = r?.label ?? i.field, o = g(e.objectName, i.field, a), s = r?.type === "select" || r?.type === "status", c;
835
- if (s && Array.isArray(r?.options) && r.options.length > 0) {
836
- let t = _(e.objectName, i.field, r.options);
837
- c = /* @__PURE__ */ new Map();
838
- for (let e of t) e && e.value !== void 0 && e.value !== null && c.set(String(e.value), e.label == null ? String(e.value) : String(e.label));
839
- }
840
- t.set(i.field, {
841
- fieldLabel: o,
842
- options: c
843
- });
844
- }
845
- return t;
846
- }, [
847
- x,
848
- C,
849
- w,
850
- e.objectName,
851
- g,
852
- _
853
- ]), E = t.useMemo(() => {
854
- let t = /* @__PURE__ */ new Map(), n = x?.fields ?? {};
855
- for (let r of m) {
856
- let i = K(r);
857
- if (r.label) {
858
- t.set(i, String(r.label));
859
- continue;
860
- }
861
- let a = n[r.field]?.label ?? r.field, o = g(e.objectName, r.field, a);
862
- if (r.aggregate) {
863
- let e = v(`report.aggregate.${r.aggregate}`, r.aggregate);
864
- t.set(i, `${o} · ${e}`);
865
- } else t.set(i, o);
866
- }
867
- return t;
868
- }, [
869
- m,
870
- x,
871
- e.objectName,
872
- g,
873
- v
874
- ]), D = t.useCallback((t, n, r) => {
875
- let l = {
876
- ...t.key,
877
- ...n.key
878
- };
879
- if (o) {
880
- let t = Pe(e, l, {
881
- runtimeFilter: i,
882
- view: s,
883
- openIn: c
884
- });
885
- o.execute(t);
886
- }
887
- a && a({
888
- rowKey: t.key,
889
- colKey: n.key,
890
- combinedKey: l,
891
- values: r
892
- });
893
- }, [
894
- o,
895
- c,
896
- s,
897
- a,
898
- e,
899
- i
900
- ]);
901
- if (p) return /* @__PURE__ */ L("div", {
902
- className: P("rounded-md border border-destructive/30 bg-destructive/5 px-4 py-3 text-sm text-destructive", l),
903
- role: "alert",
904
- "data-testid": "matrix-error",
905
- children: v("report.failedToLoad", "Failed to load matrix: {{message}}", { message: p.message })
906
- });
907
- if (!d) return /* @__PURE__ */ L("div", {
908
- className: P("rounded-md border border-dashed border-border bg-muted/30 px-4 py-6 text-center text-sm text-muted-foreground", l),
909
- "aria-busy": f || void 0,
910
- "data-testid": "matrix-empty",
911
- children: f ? v("report.loading", "Loading…") : v("report.needsAcross", "Matrix report requires at least one `groupingsAcross` field.")
912
- });
913
- let O = !!a || !!o, k = C.map((e) => T.get(e.field)?.fieldLabel ?? e.field).join(" / ") || v("report.rowsLabel", "Row"), A = w.map((e) => T.get(e.field)?.fieldLabel ?? e.field).join(" / ") || v("report.columnsLabel", "Column"), j = m.length > 0 ? K(m[0]) : null, M = 0;
914
- if (j) for (let e of d.rowHeaders) for (let t of d.colHeaders) {
915
- let n = d.cells[e.id]?.[t.id]?.[j];
916
- typeof n == "number" && n > M && (M = n);
917
- }
918
- let ee = (e) => {
919
- if (!j || M <= 0 || !e) return 0;
920
- let t = e[j];
921
- return typeof t != "number" || t <= 0 ? 0 : Math.min(1, t / M);
922
- };
923
- return /* @__PURE__ */ L("div", {
924
- className: P("overflow-auto rounded-lg border border-border bg-card shadow-sm", l),
925
- "data-testid": "matrix-renderer",
926
- "aria-busy": f || void 0,
927
- children: /* @__PURE__ */ R("table", {
928
- role: "table",
929
- className: "w-full border-separate border-spacing-0 text-sm",
930
- children: [
931
- /* @__PURE__ */ L("thead", { children: /* @__PURE__ */ R("tr", { children: [
932
- /* @__PURE__ */ R("th", {
933
- scope: "col",
934
- className: P("sticky left-0 top-0 z-30 border-b border-r border-border bg-muted/60", "px-3 py-2 text-left text-xs font-semibold uppercase tracking-wide text-muted-foreground"),
935
- "aria-label": `${k} \u2192 ${A}`,
936
- children: [
937
- /* @__PURE__ */ L("span", {
938
- className: "text-muted-foreground/70",
939
- children: k
940
- }),
941
- /* @__PURE__ */ L("span", {
942
- className: "mx-1 text-muted-foreground/40",
943
- children: "\\"
944
- }),
945
- /* @__PURE__ */ L("span", {
946
- className: "text-foreground/80",
947
- children: A
948
- })
949
- ]
950
- }),
951
- d.colHeaders.map((e) => /* @__PURE__ */ L("th", {
952
- scope: "col",
953
- className: "sticky top-0 z-20 whitespace-nowrap border-b border-border bg-muted/60 px-3 py-2 text-right text-xs font-semibold text-foreground",
954
- children: /* @__PURE__ */ L(Ke, {
955
- header: e,
956
- groupings: w,
957
- metaByField: T,
958
- fallback: b,
959
- emptyLabel: y
960
- })
961
- }, `col-${e.id}`)),
962
- /* @__PURE__ */ L("th", {
963
- scope: "col",
964
- className: "sticky top-0 z-20 whitespace-nowrap border-b border-l border-border bg-muted px-3 py-2 text-right text-xs font-semibold uppercase tracking-wide text-foreground",
965
- children: v("report.rowTotal", "Row Total")
966
- })
967
- ] }) }),
968
- /* @__PURE__ */ L("tbody", { children: d.rowHeaders.map((e, t) => /* @__PURE__ */ R("tr", {
969
- className: "group",
970
- children: [
971
- /* @__PURE__ */ L("th", {
972
- scope: "row",
973
- className: P("sticky left-0 z-10 whitespace-nowrap border-b border-r border-border bg-card px-3 py-2 text-left text-sm font-medium text-foreground", "group-hover:bg-muted/50", t === 0 && "border-t-0"),
974
- children: /* @__PURE__ */ L(Ke, {
975
- header: e,
976
- groupings: C,
977
- metaByField: T,
978
- fallback: b,
979
- emptyLabel: y
980
- })
981
- }),
982
- d.colHeaders.map((t) => {
983
- let n = d.cells[e.id]?.[t.id], r = !n, i = ee(n);
984
- return /* @__PURE__ */ L("td", {
985
- className: P("border-b border-border px-3 py-2 text-right tabular-nums transition-colors", r ? "text-muted-foreground/40" : "text-foreground", O && !r && "cursor-pointer hover:outline hover:outline-2 hover:-outline-offset-2 hover:outline-primary/50", "group-hover:bg-muted/30"),
986
- style: i > 0 ? { backgroundColor: `rgba(59, 130, 246, ${.06 + i * .28})` } : void 0,
987
- onClick: O && !r ? () => D(e, t, n) : void 0,
988
- "data-row": e.id,
989
- "data-col": t.id,
990
- children: r ? u : Je(m, n, h, E)
991
- }, `cell-${e.id}-${t.id}`);
992
- }),
993
- /* @__PURE__ */ L("td", {
994
- className: P("border-b border-l border-border bg-muted/40 px-3 py-2 text-right text-sm font-semibold tabular-nums text-foreground", "group-hover:bg-muted/60"),
995
- children: Je(m, d.rowTotals[e.id] ?? {}, h, E)
996
- })
997
- ]
998
- }, `row-${e.id}`)) }),
999
- /* @__PURE__ */ L("tfoot", { children: /* @__PURE__ */ R("tr", { children: [
1000
- /* @__PURE__ */ L("th", {
1001
- scope: "row",
1002
- className: "sticky left-0 z-10 whitespace-nowrap border-t-2 border-r border-border bg-muted px-3 py-2 text-left text-xs font-semibold uppercase tracking-wide text-foreground",
1003
- children: v("report.columnTotal", "Column Total")
1004
- }),
1005
- d.colHeaders.map((e) => /* @__PURE__ */ L("td", {
1006
- className: "border-t-2 border-border bg-muted/40 px-3 py-2 text-right text-sm font-semibold tabular-nums text-foreground",
1007
- children: Je(m, d.colTotals[e.id] ?? {}, h, E)
1008
- }, `coltotal-${e.id}`)),
1009
- /* @__PURE__ */ L("td", {
1010
- className: "border-l border-t-2 border-border bg-primary/10 px-3 py-2 text-right text-sm font-bold tabular-nums text-foreground",
1011
- children: Je(m, d.grandTotal, h, E)
1012
- })
1013
- ] }) })
1014
- ]
1015
- })
1016
- });
1017
- };
1018
- function Je(e, t, n, r) {
1019
- return e.length ? n ? /* @__PURE__ */ L("div", {
1020
- className: "flex flex-col gap-0.5",
1021
- children: e.map((e) => {
1022
- let n = K(e);
1023
- return /* @__PURE__ */ R("div", {
1024
- className: "flex items-baseline justify-between gap-2",
1025
- children: [/* @__PURE__ */ L("span", {
1026
- className: "text-xs text-muted-foreground",
1027
- children: r?.get(n) ?? e.label ?? n
1028
- }), /* @__PURE__ */ L("span", {
1029
- className: "tabular-nums",
1030
- children: We(t[n])
1031
- })]
1032
- }, n);
1033
- })
1034
- }) : We(t[K(e[0])]) : Ue;
1035
- }
1036
- //#endregion
1037
- //#region src/JoinedReportRenderer.tsx
1038
- function Ye(e, t) {
1039
- return e ? typeof e == "string" ? e : typeof e == "object" && typeof e.default == "string" ? e.default : t : t;
1040
- }
1041
- function Xe(e, t) {
1042
- if (!t || Object.keys(t).length === 0) return e;
1043
- let n = X(t, e.filter);
1044
- return {
1045
- ...e,
1046
- filter: n
1047
- };
1048
- }
1049
- var Ze = ({ report: e, dataSource: t, runtimeFilter: n, actionRunner: r, drillView: i, drillOpenIn: a, className: o, renderBlock: s }) => {
1050
- if (!c(e)) return /* @__PURE__ */ R("div", {
1051
- className: o,
1052
- "data-testid": "joined-report-invalid",
1053
- style: {
1054
- color: "var(--color-destructive, #b91c1c)",
1055
- fontSize: 13,
1056
- padding: 12
1057
- },
1058
- children: [
1059
- "JoinedReportRenderer requires a report with ",
1060
- /* @__PURE__ */ L("code", { children: "type: 'joined'" }),
1061
- " and a ",
1062
- /* @__PURE__ */ L("code", { children: "blocks" }),
1063
- " array."
1064
- ]
1065
- });
1066
- let l = e.blocks ?? [], u = e.filter, d = e.objectName;
1067
- return /* @__PURE__ */ L("div", {
1068
- className: o,
1069
- "data-testid": "joined-report",
1070
- "data-report-name": e.name,
1071
- style: {
1072
- display: "flex",
1073
- flexDirection: "column",
1074
- gap: 24
1075
- },
1076
- children: l.map((e, o) => {
1077
- let c = e.objectName ?? d ?? "", l = Xe({
1078
- ...e,
1079
- objectName: c,
1080
- type: e.type ?? "tabular",
1081
- columns: e.columns ?? []
1082
- }, u), f = Ye(e.label, e.name), p = e.description ? Ye(e.description, "") : "", m = e.name ?? `block-${o}`, h = /* @__PURE__ */ R("section", {
1083
- "data-testid": "joined-report-block",
1084
- "data-block-id": m,
1085
- style: {
1086
- display: "flex",
1087
- flexDirection: "column",
1088
- gap: 8,
1089
- border: "1px solid var(--color-border, #e4e4e7)",
1090
- borderRadius: 8,
1091
- padding: 16,
1092
- background: "var(--color-card, #ffffff)"
1093
- },
1094
- children: [/* @__PURE__ */ R("header", {
1095
- style: {
1096
- display: "flex",
1097
- flexDirection: "column",
1098
- gap: 2
1099
- },
1100
- children: [/* @__PURE__ */ L("h3", {
1101
- style: {
1102
- margin: 0,
1103
- fontSize: 16,
1104
- fontWeight: 600
1105
- },
1106
- children: f
1107
- }), p ? /* @__PURE__ */ L("p", {
1108
- style: {
1109
- margin: 0,
1110
- fontSize: 13,
1111
- color: "var(--color-muted-foreground, #71717a)"
1112
- },
1113
- children: p
1114
- }) : null]
1115
- }), /* @__PURE__ */ L($e, {
1116
- schema: l,
1117
- dataSource: t,
1118
- runtimeFilter: n,
1119
- actionRunner: r,
1120
- drillView: i,
1121
- drillOpenIn: a
1122
- })]
1123
- }, m);
1124
- return s ? s(e, o, h) : h;
1125
- })
1126
- });
1127
- }, Qe = {
1128
- border: "1px dashed var(--color-border, #d4d4d8)",
1129
- borderRadius: 8,
1130
- padding: 16,
1131
- color: "var(--color-muted-foreground, #71717a)",
1132
- background: "var(--color-muted, #f4f4f5)",
1133
- fontSize: 13
1134
- }, $e = (e) => {
1135
- let { dataSource: n, rows: r, runtimeFilter: i, actionRunner: a, drillView: o, drillOpenIn: s, className: u } = e, f = t.useContext(d), p = n ?? f?.dataSource, m = e.schema;
1136
- if (m && typeof m == "object" && m.type === "spec-report" && m.report && typeof m.report == "object" && (m = m.report), l(m)) {
1137
- let e = m.type ?? "tabular";
1138
- return e === "matrix" ? /* @__PURE__ */ L(qe, {
1139
- report: m,
1140
- dataSource: p,
1141
- rows: r,
1142
- runtimeFilter: i,
1143
- actionRunner: a,
1144
- drillView: o,
1145
- drillOpenIn: s,
1146
- className: u
1147
- }) : e === "joined" ? c(m) ? /* @__PURE__ */ L(Ze, {
1148
- report: m,
1149
- dataSource: p,
1150
- runtimeFilter: i,
1151
- actionRunner: a,
1152
- drillView: o,
1153
- drillOpenIn: s,
1154
- className: u
1155
- }) : /* @__PURE__ */ R("div", {
1156
- className: u,
1157
- style: Qe,
1158
- "data-testid": "report-joined-placeholder",
1159
- children: [
1160
- "Joined report (",
1161
- /* @__PURE__ */ L("code", { children: m.name }),
1162
- ") is missing a ",
1163
- /* @__PURE__ */ L("code", { children: "blocks" }),
1164
- " array."
1165
- ]
1166
- }) : /* @__PURE__ */ L(He, {
1167
- report: m,
1168
- dataSource: p,
1169
- rows: r,
1170
- runtimeFilter: i,
1171
- actionRunner: a,
1172
- drillView: o,
1173
- drillOpenIn: s,
1174
- className: u
1175
- });
1176
- }
1177
- return /* @__PURE__ */ L(_e, { schema: m });
1178
- };
1179
- //#endregion
1180
66
  //#region src/ReportExportEngine.ts
1181
- function et(e, t, n) {
67
+ function M(e, t, n) {
1182
68
  let r = e.fields || [], i = r.map((e) => e.label || e.name), a = t.map((e) => r.map((t) => {
1183
69
  let n = e[t.name];
1184
- return n = ot(n), typeof n == "string" && (n.includes(",") || n.includes("\"") || n.includes("\n")) ? `"${n.replace(/"/g, "\"\"")}"` : n ?? "";
70
+ return n = R(n), typeof n == "string" && (n.includes(",") || n.includes("\"") || n.includes("\n")) ? `"${n.replace(/"/g, "\"\"")}"` : n ?? "";
1185
71
  }));
1186
- lt([...n?.includeHeaders === !1 ? [] : [i.join(",")], ...a.map((e) => e.join(","))].join("\n"), n?.filename || `${e.title || "report"}.csv`, "text/csv");
72
+ V([...n?.includeHeaders === !1 ? [] : [i.join(",")], ...a.map((e) => e.join(","))].join("\n"), n?.filename || `${e.title || "report"}.csv`, "text/csv");
1187
73
  }
1188
- function tt(e, t, n) {
74
+ function ee(e, t, n) {
1189
75
  let r = {
1190
76
  title: e.title,
1191
77
  description: e.description,
1192
78
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1193
79
  data: t
1194
80
  };
1195
- lt(JSON.stringify(r, null, 2), n?.filename || `${e.title || "report"}.json`, "application/json");
81
+ V(JSON.stringify(r, null, 2), n?.filename || `${e.title || "report"}.json`, "application/json");
1196
82
  }
1197
- function nt(e, t, n) {
1198
- let r = e.fields || [], i = ct(n?.orientation), a = st(n?.pageSize);
1199
- lt(`<!DOCTYPE html>
83
+ function N(e, t, n) {
84
+ let r = e.fields || [], i = B(n?.orientation), a = z(n?.pageSize);
85
+ V(`<!DOCTYPE html>
1200
86
  <html>
1201
87
  <head>
1202
88
  <meta charset="utf-8">
1203
- <title>${Q(e.title || "Report")}</title>
89
+ <title>${L(e.title || "Report")}</title>
1204
90
  <style>
1205
91
  @page { size: ${a} ${i}; margin: 20mm; }
1206
92
  body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #333; }
@@ -1214,20 +100,20 @@ function nt(e, t, n) {
1214
100
  </style>
1215
101
  </head>
1216
102
  <body>
1217
- <h1>${Q(e.title || "Report")}</h1>
1218
- ${e.description ? `<p class="description">${Q(e.description)}</p>` : ""}
103
+ <h1>${L(e.title || "Report")}</h1>
104
+ ${e.description ? `<p class="description">${L(e.description)}</p>` : ""}
1219
105
  <p class="meta">Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}</p>
1220
106
  <table>
1221
- <thead><tr>${r.map((e) => `<th>${Q(e.label || e.name)}</th>`).join("")}</tr></thead>
1222
- <tbody>${t.map((e) => `<tr>${r.map((t) => `<td>${Q(String(e[t.name] ?? ""))}</td>`).join("")}</tr>`).join("")}</tbody>
107
+ <thead><tr>${r.map((e) => `<th>${L(e.label || e.name)}</th>`).join("")}</tr></thead>
108
+ <tbody>${t.map((e) => `<tr>${r.map((t) => `<td>${L(String(e[t.name] ?? ""))}</td>`).join("")}</tr>`).join("")}</tbody>
1223
109
  </table>
1224
110
  </body>
1225
111
  </html>`, n?.filename || `${e.title || "report"}.html`, "text/html");
1226
112
  }
1227
- function rt(e, t, n) {
1228
- let r = e.fields || [], i = ct(n?.orientation), a = st(n?.pageSize), o = window.open("", "_blank");
113
+ function P(e, t, n) {
114
+ let r = e.fields || [], i = B(n?.orientation), a = z(n?.pageSize), o = window.open("", "_blank");
1229
115
  if (!o) {
1230
- nt(e, t, {
116
+ N(e, t, {
1231
117
  ...n,
1232
118
  format: "html",
1233
119
  filename: n?.filename?.replace(/\.pdf$/, ".html") || `${e.title || "report"}.html`
@@ -1238,7 +124,7 @@ function rt(e, t, n) {
1238
124
  <html>
1239
125
  <head>
1240
126
  <meta charset="utf-8">
1241
- <title>${Q(e.title || "Report")}</title>
127
+ <title>${L(e.title || "Report")}</title>
1242
128
  <style>
1243
129
  @page { size: ${a} ${i}; margin: 20mm; }
1244
130
  @media print { .no-print { display: none; } }
@@ -1253,56 +139,56 @@ function rt(e, t, n) {
1253
139
  </style>
1254
140
  </head>
1255
141
  <body>
1256
- <h1>${Q(e.title || "Report")}</h1>
1257
- ${e.description ? `<p class="description">${Q(e.description)}</p>` : ""}
142
+ <h1>${L(e.title || "Report")}</h1>
143
+ ${e.description ? `<p class="description">${L(e.description)}</p>` : ""}
1258
144
  <p class="meta">Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}</p>
1259
145
  <table>
1260
- <thead><tr>${r.map((e) => `<th>${Q(e.label || e.name)}</th>`).join("")}</tr></thead>
1261
- <tbody>${t.map((e) => `<tr>${r.map((t) => `<td>${Q(String(e[t.name] ?? ""))}</td>`).join("")}</tr>`).join("")}</tbody>
146
+ <thead><tr>${r.map((e) => `<th>${L(e.label || e.name)}</th>`).join("")}</tr></thead>
147
+ <tbody>${t.map((e) => `<tr>${r.map((t) => `<td>${L(String(e[t.name] ?? ""))}</td>`).join("")}</tr>`).join("")}</tbody>
1262
148
  </table>
1263
149
  </body>
1264
150
  </html>`), o.document.close(), o.onload = () => {
1265
151
  o.print();
1266
152
  };
1267
153
  }
1268
- function it(e, t, n) {
154
+ function F(e, t, n) {
1269
155
  let r = e.fields || [], i = r.map((e) => e.label || e.name), a = t.map((e) => r.map((t) => {
1270
156
  let n = e[t.name];
1271
- return n = ot(n), typeof n == "string" && (n.includes(",") || n.includes("\"") || n.includes("\n") || n.includes(" ")) ? `"${n.replace(/"/g, "\"\"")}"` : n ?? "";
157
+ return n = R(n), typeof n == "string" && (n.includes(",") || n.includes("\"") || n.includes("\n") || n.includes(" ")) ? `"${n.replace(/"/g, "\"\"")}"` : n ?? "";
1272
158
  }));
1273
- lt("" + [...n?.includeHeaders === !1 ? [] : [i.join(" ")], ...a.map((e) => e.join(" "))].join("\n"), n?.filename || `${e.title || "report"}.tsv`, "text/tab-separated-values");
159
+ V("" + [...n?.includeHeaders === !1 ? [] : [i.join(" ")], ...a.map((e) => e.join(" "))].join("\n"), n?.filename || `${e.title || "report"}.tsv`, "text/tab-separated-values");
1274
160
  }
1275
- function at(e, t, n, r) {
161
+ function I(e, t, n, r) {
1276
162
  switch (e) {
1277
163
  case "csv":
1278
- et(t, n, r);
164
+ M(t, n, r);
1279
165
  break;
1280
166
  case "json":
1281
- tt(t, n, r);
167
+ ee(t, n, r);
1282
168
  break;
1283
169
  case "html":
1284
- nt(t, n, r);
170
+ N(t, n, r);
1285
171
  break;
1286
172
  case "pdf":
1287
- rt(t, n, r);
173
+ P(t, n, r);
1288
174
  break;
1289
175
  case "excel":
1290
- it(t, n, r);
176
+ F(t, n, r);
1291
177
  break;
1292
178
  default: console.warn(`Unsupported export format: ${e}`);
1293
179
  }
1294
180
  }
1295
- function Q(e) {
181
+ function L(e) {
1296
182
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
1297
183
  }
1298
- function ot(e) {
184
+ function R(e) {
1299
185
  if (typeof e == "string" && e.length > 0) {
1300
186
  let t = e.charAt(0);
1301
187
  if (t === "=" || t === "+" || t === "-" || t === "@" || t === "|") return `\t${e}`;
1302
188
  }
1303
189
  return e;
1304
190
  }
1305
- function st(e) {
191
+ function z(e) {
1306
192
  return [
1307
193
  "A4",
1308
194
  "A3",
@@ -1310,19 +196,19 @@ function st(e) {
1310
196
  "Legal"
1311
197
  ].includes(e || "") ? e : "A4";
1312
198
  }
1313
- function ct(e) {
199
+ function B(e) {
1314
200
  return e === "landscape" ? "landscape" : "portrait";
1315
201
  }
1316
- function lt(e, t, n) {
202
+ function V(e, t, n) {
1317
203
  let r = new Blob([e], { type: `${n};charset=utf-8` }), i = URL.createObjectURL(r), a = document.createElement("a");
1318
204
  a.href = i, a.download = t, document.body.appendChild(a), a.click(), document.body.removeChild(a), URL.revokeObjectURL(i);
1319
205
  }
1320
206
  //#endregion
1321
207
  //#region src/formatValue.ts
1322
- function ut(e, t) {
208
+ function H(e, t) {
1323
209
  if (e == null || e === "") return "";
1324
210
  let n = t?.type, r = t?.format;
1325
- if (n === "date" || r === "date" || dt(e)) return ft(e);
211
+ if (n === "date" || r === "date" || te(e)) return ne(e);
1326
212
  if (n === "number" || typeof e == "number") {
1327
213
  let t = typeof e == "number" ? e : Number(e);
1328
214
  return isNaN(t) ? String(e) : r === "currency" || r === "currency_cny" ? `¥${t.toLocaleString("en-US", {
@@ -1338,10 +224,10 @@ function ut(e, t) {
1338
224
  }
1339
225
  return String(e);
1340
226
  }
1341
- function dt(e) {
227
+ function te(e) {
1342
228
  return typeof e == "string" ? /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2})?/.test(e) : !1;
1343
229
  }
1344
- function ft(e) {
230
+ function ne(e) {
1345
231
  try {
1346
232
  let t = new Date(e);
1347
233
  return isNaN(t.getTime()) ? String(e) : `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, "0")}-${String(t.getDate()).padStart(2, "0")}`;
@@ -1351,7 +237,7 @@ function ft(e) {
1351
237
  }
1352
238
  //#endregion
1353
239
  //#region src/ReportViewer.tsx
1354
- function pt(e, t) {
240
+ function re(e, t) {
1355
241
  if (!t || t.length === 0 || !e || e.length === 0) return null;
1356
242
  let n = t[0], r = n.field, i = /* @__PURE__ */ new Map();
1357
243
  for (let t of e) {
@@ -1367,30 +253,30 @@ function pt(e, t) {
1367
253
  let o = n.sort === "desc" ? -1 : 1;
1368
254
  return a.sort((e, t) => e.key.localeCompare(t.key) * o), a;
1369
255
  }
1370
- var mt = ({ schema: t, onRefresh: r }) => {
1371
- let { report: i, data: a, showToolbar: o = !0, allowExport: s = !0, allowPrint: c = !0, loading: l = !1 } = t, d = (e) => {
1372
- if (!i) {
256
+ var U = ({ schema: t, onRefresh: n }) => {
257
+ let { report: r, data: i, showToolbar: a = !0, allowExport: s = !0, allowPrint: c = !0, loading: u = !1 } = t, x = (e) => {
258
+ if (!r) {
1373
259
  console.warn("ReportViewer: Cannot export, no report defined");
1374
260
  return;
1375
261
  }
1376
- at(e, i, a || [], i.exportConfigs?.[e]);
1377
- }, y = () => {
262
+ I(e, r, i || [], r.exportConfigs?.[e]);
263
+ }, C = () => {
1378
264
  window.print();
1379
- }, b = () => {
1380
- r?.();
1381
- }, x = (e, t) => {
1382
- if (!a) return 0;
1383
- let n = a.map((t) => Number(t[e]) || 0);
265
+ }, E = () => {
266
+ n?.();
267
+ }, k = (e, t) => {
268
+ if (!i) return 0;
269
+ let n = i.map((t) => Number(t[e]) || 0);
1384
270
  switch (t) {
1385
- case "count": return a.length;
271
+ case "count": return i.length;
1386
272
  case "sum": return n.reduce((e, t) => e + t, 0);
1387
273
  case "avg": return n.length > 0 ? (n.reduce((e, t) => e + t, 0) / n.length).toFixed(2) : 0;
1388
274
  case "min": return n.length > 0 ? Math.min(...n) : 0;
1389
275
  case "max": return n.length > 0 ? Math.max(...n) : 0;
1390
276
  default: return "";
1391
277
  }
1392
- }, S = (e, t) => {
1393
- let n = i?.conditionalFormatting;
278
+ }, A = (e, t) => {
279
+ let n = r?.conditionalFormatting;
1394
280
  if (!(!n || !Array.isArray(n))) for (let r of n) {
1395
281
  if (r.field !== e) continue;
1396
282
  let n = String(t ?? ""), i = String(r.value ?? ""), a = !1;
@@ -1416,160 +302,160 @@ var mt = ({ schema: t, onRefresh: r }) => {
1416
302
  return r.backgroundColor && (e.backgroundColor = r.backgroundColor), r.textColor && (e.color = r.textColor), e;
1417
303
  }
1418
304
  }
1419
- }, C = (e, t) => {
305
+ }, j = (e, t) => {
1420
306
  if (e == null || e === "") return "";
1421
- if (t.renderAs === "badge" && (!t.type || t.type === "string" || t.type === "text")) return /* @__PURE__ */ L(f, {
307
+ if (t.renderAs === "badge" && (!t.type || t.type === "string" || t.type === "text")) return /* @__PURE__ */ y(d, {
1422
308
  className: t.colorMap?.[String(e)] || "",
1423
309
  children: String(e)
1424
310
  });
1425
- if (t.aggregation) return ut(e, t);
311
+ if (t.aggregation) return H(e, t);
1426
312
  if (t.type) {
1427
313
  let n = { ...t };
1428
314
  return t.colorMap && !n.options && (n.options = Object.entries(t.colorMap).map(([e, t]) => ({
1429
315
  value: e,
1430
316
  label: e,
1431
317
  color: t
1432
- }))), /* @__PURE__ */ L(he(ge(n)), {
318
+ }))), /* @__PURE__ */ y(D(O(n)), {
1433
319
  value: e,
1434
320
  field: n
1435
321
  });
1436
322
  }
1437
- return ut(e, t);
323
+ return H(e, t);
1438
324
  };
1439
- return i ? /* @__PURE__ */ R("div", {
325
+ return r ? /* @__PURE__ */ b("div", {
1440
326
  className: "space-y-4",
1441
- children: [o && /* @__PURE__ */ R("div", {
327
+ children: [a && /* @__PURE__ */ b("div", {
1442
328
  className: "flex items-center justify-between gap-2 p-4 bg-card rounded-lg border",
1443
- children: [/* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("h2", {
329
+ children: [/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("h2", {
1444
330
  className: "text-lg font-semibold",
1445
- children: i.title
1446
- }), i.description && /* @__PURE__ */ L("p", {
331
+ children: r.title
332
+ }), r.description && /* @__PURE__ */ y("p", {
1447
333
  className: "text-sm text-muted-foreground",
1448
- children: i.description
1449
- })] }), /* @__PURE__ */ R("div", {
334
+ children: r.description
335
+ })] }), /* @__PURE__ */ b("div", {
1450
336
  className: "flex items-center gap-2",
1451
337
  children: [
1452
- i.refreshInterval && /* @__PURE__ */ R(p, {
338
+ r.refreshInterval && /* @__PURE__ */ b(f, {
1453
339
  variant: "outline",
1454
340
  size: "sm",
1455
- onClick: b,
1456
- children: [/* @__PURE__ */ L(de, { className: "h-4 w-4 mr-2" }), "Refresh"]
341
+ onClick: E,
342
+ children: [/* @__PURE__ */ y(T, { className: "h-4 w-4 mr-2" }), "Refresh"]
1457
343
  }),
1458
- c && /* @__PURE__ */ R(p, {
344
+ c && /* @__PURE__ */ b(f, {
1459
345
  variant: "outline",
1460
346
  size: "sm",
1461
- onClick: y,
1462
- children: [/* @__PURE__ */ L(ue, { className: "h-4 w-4 mr-2" }), "Print"]
347
+ onClick: C,
348
+ children: [/* @__PURE__ */ y(w, { className: "h-4 w-4 mr-2" }), "Print"]
1463
349
  }),
1464
- s && i.showExportButtons && /* @__PURE__ */ R("div", {
350
+ s && r.showExportButtons && /* @__PURE__ */ b("div", {
1465
351
  className: "flex items-center gap-1",
1466
352
  children: [
1467
- /* @__PURE__ */ R(p, {
353
+ /* @__PURE__ */ b(f, {
1468
354
  variant: "outline",
1469
355
  size: "sm",
1470
- onClick: () => d("pdf"),
1471
- children: [/* @__PURE__ */ L(oe, { className: "h-4 w-4 mr-2" }), "PDF"]
356
+ onClick: () => x("pdf"),
357
+ children: [/* @__PURE__ */ y(S, { className: "h-4 w-4 mr-2" }), "PDF"]
1472
358
  }),
1473
- /* @__PURE__ */ R(p, {
359
+ /* @__PURE__ */ b(f, {
1474
360
  variant: "outline",
1475
361
  size: "sm",
1476
- onClick: () => d("excel"),
1477
- children: [/* @__PURE__ */ L(oe, { className: "h-4 w-4 mr-2" }), "Excel"]
362
+ onClick: () => x("excel"),
363
+ children: [/* @__PURE__ */ y(S, { className: "h-4 w-4 mr-2" }), "Excel"]
1478
364
  }),
1479
- /* @__PURE__ */ R(p, {
365
+ /* @__PURE__ */ b(f, {
1480
366
  variant: "outline",
1481
367
  size: "sm",
1482
- onClick: () => d("csv"),
1483
- children: [/* @__PURE__ */ L(oe, { className: "h-4 w-4 mr-2" }), "CSV"]
368
+ onClick: () => x("csv"),
369
+ children: [/* @__PURE__ */ y(S, { className: "h-4 w-4 mr-2" }), "CSV"]
1484
370
  })
1485
371
  ]
1486
372
  })
1487
373
  ]
1488
374
  })]
1489
- }), /* @__PURE__ */ R(m, { children: [/* @__PURE__ */ R(_, { children: [!o && i.title && /* @__PURE__ */ L(v, { children: i.title }), !o && i.description && /* @__PURE__ */ L(g, { children: i.description })] }), /* @__PURE__ */ R(h, {
375
+ }), /* @__PURE__ */ b(p, { children: [/* @__PURE__ */ b(g, { children: [!a && r.title && /* @__PURE__ */ y(_, { children: r.title }), !a && r.description && /* @__PURE__ */ y(h, { children: r.description })] }), /* @__PURE__ */ b(m, {
1490
376
  className: "space-y-6",
1491
377
  children: [
1492
- l && /* @__PURE__ */ R("div", {
378
+ u && /* @__PURE__ */ b("div", {
1493
379
  className: "space-y-6",
1494
- children: [/* @__PURE__ */ L("div", {
380
+ children: [/* @__PURE__ */ y("div", {
1495
381
  className: "grid grid-cols-1 md:grid-cols-3 gap-4",
1496
382
  children: [
1497
383
  1,
1498
384
  2,
1499
385
  3
1500
- ].map((e) => /* @__PURE__ */ L(m, { children: /* @__PURE__ */ R(h, {
386
+ ].map((e) => /* @__PURE__ */ y(p, { children: /* @__PURE__ */ b(m, {
1501
387
  className: "p-4 space-y-2",
1502
- children: [/* @__PURE__ */ L(A, { className: "h-4 w-20" }), /* @__PURE__ */ L(A, { className: "h-8 w-28" })]
388
+ children: [/* @__PURE__ */ y(v, { className: "h-4 w-20" }), /* @__PURE__ */ y(v, { className: "h-8 w-28" })]
1503
389
  }) }, e))
1504
- }), /* @__PURE__ */ R("div", {
390
+ }), /* @__PURE__ */ b("div", {
1505
391
  className: "space-y-2",
1506
- children: [/* @__PURE__ */ L(A, { className: "h-10 w-full" }), [
392
+ children: [/* @__PURE__ */ y(v, { className: "h-10 w-full" }), [
1507
393
  1,
1508
394
  2,
1509
395
  3,
1510
396
  4,
1511
397
  5
1512
- ].map((e) => /* @__PURE__ */ L(A, { className: "h-8 w-full" }, e))]
398
+ ].map((e) => /* @__PURE__ */ y(v, { className: "h-8 w-full" }, e))]
1513
399
  })]
1514
400
  }),
1515
- !l && i.sections?.map((t, r) => t.visible === !1 ? null : /* @__PURE__ */ R("div", {
401
+ !u && r.sections?.map((t, n) => t.visible === !1 ? null : /* @__PURE__ */ b("div", {
1516
402
  className: "space-y-2",
1517
403
  children: [
1518
- t.title && t.type !== "header" && /* @__PURE__ */ L("h3", {
404
+ t.title && t.type !== "header" && /* @__PURE__ */ y("h3", {
1519
405
  className: "text-lg font-semibold border-b pb-2",
1520
406
  children: t.title
1521
407
  }),
1522
- t.type === "header" && t.title && /* @__PURE__ */ L("div", {
408
+ t.type === "header" && t.title && /* @__PURE__ */ y("div", {
1523
409
  className: "text-2xl font-bold py-4",
1524
410
  children: t.title
1525
411
  }),
1526
- t.type === "summary" && /* @__PURE__ */ L("div", {
412
+ t.type === "summary" && /* @__PURE__ */ y("div", {
1527
413
  className: "grid grid-cols-1 md:grid-cols-3 gap-4",
1528
- children: i.fields?.filter((e) => e.showInSummary).map((e, t) => /* @__PURE__ */ L(m, { children: /* @__PURE__ */ R(h, {
414
+ children: r.fields?.filter((e) => e.showInSummary).map((e, t) => /* @__PURE__ */ y(p, { children: /* @__PURE__ */ b(m, {
1529
415
  className: "p-4",
1530
- children: [/* @__PURE__ */ L("div", {
416
+ children: [/* @__PURE__ */ y("div", {
1531
417
  className: "text-sm text-muted-foreground",
1532
418
  children: e.label || e.name
1533
- }), /* @__PURE__ */ L("div", {
419
+ }), /* @__PURE__ */ y("div", {
1534
420
  className: "text-2xl font-bold",
1535
- children: ut(x(e.name, e.aggregation), e)
421
+ children: H(k(e.name, e.aggregation), e)
1536
422
  })]
1537
423
  }) }, t))
1538
424
  }),
1539
- t.type === "chart" && t.chart && /* @__PURE__ */ L("div", {
425
+ t.type === "chart" && t.chart && /* @__PURE__ */ y("div", {
1540
426
  className: "min-h-[300px]",
1541
427
  children: (() => {
1542
428
  let n = t.chart.type, r = !!t.chart.chartType;
1543
429
  !n && r && (n = "chart"), n && e.get(n) || (n = "chart");
1544
- let i = n === "chart" ? {
430
+ let a = n === "chart" ? {
1545
431
  xAxisKey: t.chart.xAxisKey || t.chart.xAxisField || "name",
1546
432
  series: t.chart.series || (t.chart.yAxisFields ? t.chart.yAxisFields.map((e) => ({ dataKey: e })) : []),
1547
433
  chartType: t.chart.chartType || "bar"
1548
434
  } : {};
1549
- return /* @__PURE__ */ L(u, { schema: {
435
+ return /* @__PURE__ */ y(l, { schema: {
1550
436
  ...t.chart,
1551
437
  type: n,
1552
- ...i,
1553
- data: a || t.chart.data,
438
+ ...a,
439
+ data: i || t.chart.data,
1554
440
  className: t.chart.className || "w-full h-[350px]"
1555
441
  } });
1556
442
  })()
1557
443
  }),
1558
- t.type === "table" && /* @__PURE__ */ L("div", {
444
+ t.type === "table" && /* @__PURE__ */ y("div", {
1559
445
  className: "border rounded-lg overflow-x-auto",
1560
- children: /* @__PURE__ */ R("table", {
446
+ children: /* @__PURE__ */ b("table", {
1561
447
  className: "w-full text-sm min-w-[600px]",
1562
- children: [/* @__PURE__ */ L("thead", {
448
+ children: [/* @__PURE__ */ y("thead", {
1563
449
  className: "bg-muted",
1564
- children: /* @__PURE__ */ L("tr", { children: t.columns?.map((e, t) => /* @__PURE__ */ L("th", {
450
+ children: /* @__PURE__ */ y("tr", { children: t.columns?.map((e, t) => /* @__PURE__ */ y("th", {
1565
451
  className: `px-4 py-2 font-medium ${e.type === "number" ? "text-right" : "text-left"}`,
1566
452
  children: e.label || e.name
1567
453
  }, t)) })
1568
- }), /* @__PURE__ */ L("tbody", { children: (() => {
1569
- let e = pt(a || [], i.groupBy || []);
1570
- return e ? e.map((e) => /* @__PURE__ */ R(n.Fragment, { children: [/* @__PURE__ */ L("tr", {
454
+ }), /* @__PURE__ */ y("tbody", { children: (() => {
455
+ let e = re(i || [], r.groupBy || []);
456
+ return e ? e.map((e) => /* @__PURE__ */ b(o.Fragment, { children: [/* @__PURE__ */ y("tr", {
1571
457
  className: "bg-muted/60",
1572
- children: /* @__PURE__ */ R("td", {
458
+ children: /* @__PURE__ */ b("td", {
1573
459
  colSpan: t.columns?.length || 1,
1574
460
  className: "px-4 py-2 font-semibold text-sm",
1575
461
  children: [
@@ -1579,2477 +465,501 @@ var mt = ({ schema: t, onRefresh: r }) => {
1579
465
  ")"
1580
466
  ]
1581
467
  })
1582
- }), e.rows.map((e, n) => /* @__PURE__ */ L("tr", {
468
+ }), e.rows.map((e, n) => /* @__PURE__ */ y("tr", {
1583
469
  className: "border-t hover:bg-muted/50 even:bg-muted/20",
1584
- children: t.columns?.map((t, n) => /* @__PURE__ */ L("td", {
470
+ children: t.columns?.map((t, n) => /* @__PURE__ */ y("td", {
1585
471
  className: `px-4 py-2 ${t.type === "number" ? "text-right tabular-nums" : ""}`,
1586
- style: S(t.name, e[t.name]),
1587
- children: C(e[t.name], t)
472
+ style: A(t.name, e[t.name]),
473
+ children: j(e[t.name], t)
1588
474
  }, n))
1589
- }, n))] }, e.key)) : a?.map((e, n) => /* @__PURE__ */ L("tr", {
475
+ }, n))] }, e.key)) : i?.map((e, n) => /* @__PURE__ */ y("tr", {
1590
476
  className: "border-t hover:bg-muted/50 even:bg-muted/20",
1591
- children: t.columns?.map((t, n) => /* @__PURE__ */ L("td", {
477
+ children: t.columns?.map((t, n) => /* @__PURE__ */ y("td", {
1592
478
  className: `px-4 py-2 ${t.type === "number" ? "text-right tabular-nums" : ""}`,
1593
- style: S(t.name, e[t.name]),
1594
- children: C(e[t.name], t)
479
+ style: A(t.name, e[t.name]),
480
+ children: j(e[t.name], t)
1595
481
  }, n))
1596
482
  }, n));
1597
483
  })() })]
1598
484
  })
1599
485
  }),
1600
- t.type === "text" && t.text && /* @__PURE__ */ L("div", {
486
+ t.type === "text" && t.text && /* @__PURE__ */ y("div", {
1601
487
  className: "prose max-w-none",
1602
- children: /* @__PURE__ */ L("p", { children: t.text })
488
+ children: /* @__PURE__ */ y("p", { children: t.text })
1603
489
  }),
1604
- t.type === "page-break" && /* @__PURE__ */ L("div", { className: "border-t-2 border-dashed my-8 print:page-break-after-always" }),
1605
- t.content && /* @__PURE__ */ L(u, { schema: t.content })
490
+ t.type === "page-break" && /* @__PURE__ */ y("div", { className: "border-t-2 border-dashed my-8 print:page-break-after-always" }),
491
+ t.content && /* @__PURE__ */ y(l, { schema: t.content })
1606
492
  ]
1607
- }, r)),
1608
- !i.sections && a && a.length > 0 && /* @__PURE__ */ L("div", {
493
+ }, n)),
494
+ !r.sections && i && i.length > 0 && /* @__PURE__ */ y("div", {
1609
495
  className: "border rounded-lg overflow-x-auto",
1610
- children: /* @__PURE__ */ R("table", {
496
+ children: /* @__PURE__ */ b("table", {
1611
497
  className: "w-full text-sm min-w-[600px]",
1612
- children: [/* @__PURE__ */ L("thead", {
498
+ children: [/* @__PURE__ */ y("thead", {
1613
499
  className: "bg-muted",
1614
- children: /* @__PURE__ */ L("tr", { children: i.fields?.map((e, t) => /* @__PURE__ */ L("th", {
500
+ children: /* @__PURE__ */ y("tr", { children: r.fields?.map((e, t) => /* @__PURE__ */ y("th", {
1615
501
  className: `px-4 py-2 font-medium ${e.type === "number" ? "text-right" : "text-left"}`,
1616
502
  children: e.label || e.name
1617
503
  }, t)) })
1618
- }), /* @__PURE__ */ L("tbody", { children: a.map((e, t) => /* @__PURE__ */ L("tr", {
504
+ }), /* @__PURE__ */ y("tbody", { children: i.map((e, t) => /* @__PURE__ */ y("tr", {
1619
505
  className: "border-t hover:bg-muted/50 even:bg-muted/20",
1620
- children: i.fields?.map((t, n) => /* @__PURE__ */ L("td", {
506
+ children: r.fields?.map((t, n) => /* @__PURE__ */ y("td", {
1621
507
  className: `px-4 py-2 ${t.type === "number" ? "text-right tabular-nums" : ""}`,
1622
- style: S(t.name, e[t.name]),
1623
- children: C(e[t.name], t)
508
+ style: A(t.name, e[t.name]),
509
+ children: j(e[t.name], t)
1624
510
  }, n))
1625
511
  }, t)) })]
1626
512
  })
1627
513
  })
1628
514
  ]
1629
515
  })] })]
1630
- }) : /* @__PURE__ */ L(m, { children: /* @__PURE__ */ L(h, {
516
+ }) : /* @__PURE__ */ y(p, { children: /* @__PURE__ */ y(m, {
1631
517
  className: "p-8 text-center text-muted-foreground",
1632
518
  children: "No report to display"
1633
519
  }) });
1634
- }, ht = ({ schedule: e, onChange: t }) => {
1635
- let [n, r] = s(e || {
1636
- enabled: !1,
1637
- frequency: "weekly",
1638
- time: "09:00",
1639
- timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
1640
- recipients: [],
1641
- formats: ["pdf"]
1642
- }), i = (e) => {
1643
- let i = {
1644
- ...n,
1645
- ...e
1646
- };
1647
- r(i), t?.(i);
1648
- };
1649
- return /* @__PURE__ */ R(m, { children: [/* @__PURE__ */ L(_, { children: /* @__PURE__ */ R(v, {
1650
- className: "flex items-center gap-2",
1651
- children: [/* @__PURE__ */ L(ne, { className: "h-5 w-5" }), "Schedule Configuration"]
1652
- }) }), /* @__PURE__ */ R(h, {
1653
- className: "space-y-4",
1654
- children: [/* @__PURE__ */ R("div", {
1655
- className: "flex items-center gap-2",
1656
- children: [/* @__PURE__ */ L("input", {
1657
- type: "checkbox",
1658
- id: "schedule-enabled",
1659
- checked: n.enabled || !1,
1660
- onChange: (e) => i({ enabled: e.target.checked }),
1661
- className: "rounded"
1662
- }), /* @__PURE__ */ L(k, {
1663
- htmlFor: "schedule-enabled",
1664
- children: "Enable Scheduled Report"
1665
- })]
1666
- }), n.enabled && /* @__PURE__ */ R(I, { children: [
1667
- /* @__PURE__ */ R("div", {
1668
- className: "space-y-2",
1669
- children: [/* @__PURE__ */ L(k, { children: "Frequency" }), /* @__PURE__ */ L("select", {
1670
- className: "w-full border rounded-md p-2 bg-background",
1671
- value: n.frequency || "weekly",
1672
- onChange: (e) => i({ frequency: e.target.value }),
1673
- children: [
1674
- {
1675
- value: "once",
1676
- label: "Once"
1677
- },
1678
- {
1679
- value: "daily",
1680
- label: "Daily"
1681
- },
1682
- {
1683
- value: "weekly",
1684
- label: "Weekly"
1685
- },
1686
- {
1687
- value: "monthly",
1688
- label: "Monthly"
1689
- },
1690
- {
1691
- value: "quarterly",
1692
- label: "Quarterly"
1693
- },
1694
- {
1695
- value: "yearly",
1696
- label: "Yearly"
1697
- }
1698
- ].map((e) => /* @__PURE__ */ L("option", {
1699
- value: e.value,
1700
- children: e.label
1701
- }, e.value))
1702
- })]
1703
- }),
1704
- n.frequency === "weekly" && /* @__PURE__ */ R("div", {
1705
- className: "space-y-2",
1706
- children: [/* @__PURE__ */ L(k, { children: "Day of Week" }), /* @__PURE__ */ L("select", {
1707
- className: "w-full border rounded-md p-2 bg-background",
1708
- value: n.dayOfWeek ?? 1,
1709
- onChange: (e) => i({ dayOfWeek: Number(e.target.value) }),
1710
- children: [
1711
- {
1712
- value: 0,
1713
- label: "Sunday"
1714
- },
1715
- {
1716
- value: 1,
1717
- label: "Monday"
1718
- },
1719
- {
1720
- value: 2,
1721
- label: "Tuesday"
1722
- },
1723
- {
1724
- value: 3,
1725
- label: "Wednesday"
1726
- },
1727
- {
1728
- value: 4,
1729
- label: "Thursday"
1730
- },
1731
- {
1732
- value: 5,
1733
- label: "Friday"
1734
- },
1735
- {
1736
- value: 6,
1737
- label: "Saturday"
1738
- }
1739
- ].map((e) => /* @__PURE__ */ L("option", {
1740
- value: e.value,
1741
- children: e.label
1742
- }, e.value))
1743
- })]
1744
- }),
1745
- n.frequency === "monthly" && /* @__PURE__ */ R("div", {
1746
- className: "space-y-2",
1747
- children: [/* @__PURE__ */ L(k, { children: "Day of Month" }), /* @__PURE__ */ L(O, {
1748
- type: "number",
1749
- min: 1,
1750
- max: 31,
1751
- value: n.dayOfMonth ?? 1,
1752
- onChange: (e) => i({ dayOfMonth: Number(e.target.value) })
1753
- })]
1754
- }),
1755
- /* @__PURE__ */ R("div", {
1756
- className: "space-y-2",
1757
- children: [/* @__PURE__ */ R(k, {
1758
- className: "flex items-center gap-2",
1759
- children: [/* @__PURE__ */ L(ae, { className: "h-4 w-4" }), "Time"]
1760
- }), /* @__PURE__ */ L(O, {
1761
- type: "time",
1762
- value: n.time || "09:00",
1763
- onChange: (e) => i({ time: e.target.value })
1764
- })]
1765
- }),
1766
- /* @__PURE__ */ R("div", {
1767
- className: "space-y-2",
1768
- children: [/* @__PURE__ */ L(k, { children: "Timezone" }), /* @__PURE__ */ L(O, {
1769
- value: n.timezone || "",
1770
- onChange: (e) => i({ timezone: e.target.value }),
1771
- placeholder: "e.g. America/New_York"
1772
- })]
1773
- }),
1774
- /* @__PURE__ */ R("div", {
1775
- className: "space-y-2",
1776
- children: [/* @__PURE__ */ L(k, { children: "Export Formats" }), /* @__PURE__ */ L("div", {
1777
- className: "flex flex-wrap gap-2",
1778
- children: [
1779
- {
1780
- value: "pdf",
1781
- label: "PDF"
1782
- },
1783
- {
1784
- value: "excel",
1785
- label: "Excel"
1786
- },
1787
- {
1788
- value: "csv",
1789
- label: "CSV"
1790
- },
1791
- {
1792
- value: "html",
1793
- label: "HTML"
1794
- }
1795
- ].map((e) => /* @__PURE__ */ R("label", {
1796
- className: "flex items-center gap-1.5 px-3 py-1.5 border rounded-md cursor-pointer hover:bg-muted/50",
1797
- children: [/* @__PURE__ */ L("input", {
1798
- type: "checkbox",
1799
- checked: n.formats?.includes(e.value) || !1,
1800
- onChange: (t) => {
1801
- let r = n.formats || [];
1802
- i({ formats: t.target.checked ? [...r, e.value] : r.filter((t) => t !== e.value) });
1803
- },
1804
- className: "rounded"
1805
- }), /* @__PURE__ */ L("span", {
1806
- className: "text-sm",
1807
- children: e.label
1808
- })]
1809
- }, e.value))
1810
- })]
1811
- }),
1812
- /* @__PURE__ */ R("div", {
1813
- className: "space-y-2",
1814
- children: [/* @__PURE__ */ R(k, {
1815
- className: "flex items-center gap-2",
1816
- children: [/* @__PURE__ */ L(le, { className: "h-4 w-4" }), "Email Recipients"]
1817
- }), /* @__PURE__ */ L(O, {
1818
- placeholder: "email1@example.com, email2@example.com",
1819
- value: n.recipients?.join(", ") || "",
1820
- onChange: (e) => i({ recipients: e.target.value.split(",").map((e) => e.trim()).filter(Boolean) })
1821
- })]
1822
- }),
1823
- /* @__PURE__ */ R("div", {
1824
- className: "space-y-2",
1825
- children: [/* @__PURE__ */ L(k, { children: "Email Subject" }), /* @__PURE__ */ L(O, {
1826
- value: n.subject || "",
1827
- onChange: (e) => i({ subject: e.target.value }),
1828
- placeholder: "Scheduled Report: {report_title}"
1829
- })]
1830
- })
1831
- ] })]
1832
- })] });
1833
- }, gt = ({ schema: e }) => {
1834
- let { report: t, dataSources: n = [], availableFields: r = [], showPreview: i = !0, onSave: a, onCancel: o } = e, [c, l] = s(t || {
1835
- type: "report",
1836
- title: "New Report",
1837
- fields: [],
1838
- filters: [],
1839
- groupBy: [],
1840
- sections: [],
1841
- showExportButtons: !0,
1842
- showPrintButton: !0
1843
- }), [u, d] = s(c.fields || []), [f, y] = s(c.filters || []), [b, x] = s(c.groupBy || []), [S, C] = s(c.sections || []), w = () => {
1844
- if (r.length > 0 && u.length < r.length) {
1845
- let e = r.find((e) => !u.some((t) => t.name === e.name));
1846
- if (e) {
1847
- let t = [...u, e];
1848
- d(t), l({
1849
- ...c,
1850
- fields: t
1851
- });
1852
- }
520
+ };
521
+ //#endregion
522
+ //#region src/mergeFilters.ts
523
+ function W(e, t) {
524
+ let n = e && Object.keys(e).length > 0, r = t && Object.keys(t).length > 0;
525
+ if (n && r) return { $and: [e, t] };
526
+ if (n) return e;
527
+ if (r) return t;
528
+ }
529
+ //#endregion
530
+ //#region src/DatasetReportRenderer.tsx
531
+ function G(e) {
532
+ if (!e || typeof e != "object") return !1;
533
+ let t = e;
534
+ return typeof t.dataset == "string" && t.dataset.length > 0 ? !0 : t.type === "joined" && Array.isArray(t.blocks) && t.blocks.some((e) => typeof e?.dataset == "string");
535
+ }
536
+ function K(e, t) {
537
+ return e ? typeof e == "string" ? e : typeof e == "object" && typeof e.default == "string" ? e.default : t : t;
538
+ }
539
+ function q(e) {
540
+ return Array.isArray(e) ? e.filter((e) => typeof e == "string" && !!e) : [];
541
+ }
542
+ function J(e, t, n, r, i, o) {
543
+ let [s, c] = a.useState({
544
+ status: "idle",
545
+ rows: []
546
+ }), l = JSON.stringify(r ?? null), u = JSON.stringify(o ?? null), d = `${e}|${t.join(",")}|${n.join(",")}|${l}|${u}`;
547
+ return a.useEffect(() => {
548
+ let a = i;
549
+ if (!a || typeof a.queryDataset != "function") {
550
+ c({
551
+ status: "error",
552
+ rows: [],
553
+ error: "This data source does not support dataset queries."
554
+ });
555
+ return;
1853
556
  }
1854
- }, T = (e) => {
1855
- let t = u.filter((t, n) => n !== e);
1856
- d(t), l({
1857
- ...c,
1858
- fields: t
1859
- });
1860
- }, E = (e, t) => {
1861
- let n = [...u];
1862
- n[e] = t, d(n), l({
1863
- ...c,
1864
- fields: n
557
+ if (!e || n.length === 0) {
558
+ c({
559
+ status: "idle",
560
+ rows: []
561
+ });
562
+ return;
563
+ }
564
+ let s = !1;
565
+ return c({
566
+ status: "loading",
567
+ rows: []
568
+ }), a.queryDataset(e, {
569
+ dimensions: t,
570
+ measures: n,
571
+ ...r && Object.keys(r).length > 0 ? { runtimeFilter: r } : {},
572
+ ...o ? { totals: { groupings: o } } : {}
573
+ }).then((e) => {
574
+ s || c({
575
+ status: "ok",
576
+ rows: Array.isArray(e?.rows) ? e.rows : [],
577
+ fields: Array.isArray(e?.fields) ? e.fields : [],
578
+ object: e?.object,
579
+ dimensionFields: e?.dimensionFields,
580
+ drillRawRows: Array.isArray(e?.drillRawRows) ? e.drillRawRows : void 0,
581
+ totals: Array.isArray(e?.totals) ? e.totals : void 0
582
+ });
583
+ }).catch((e) => {
584
+ s || c({
585
+ status: "error",
586
+ rows: [],
587
+ error: String(e?.message ?? e)
588
+ });
589
+ }), () => {
590
+ s = !0;
591
+ };
592
+ }, [d]), s;
593
+ }
594
+ function Y({ dataset: e }) {
595
+ return /* @__PURE__ */ b("div", {
596
+ className: "flex items-center justify-center rounded-md border border-dashed bg-muted/20 p-4 text-xs text-muted-foreground",
597
+ children: [
598
+ "This report binds the “",
599
+ e,
600
+ "” dataset — choose at least one measure (values) to render."
601
+ ]
602
+ });
603
+ }
604
+ function X({ status: e, error: t }) {
605
+ return e === "error" ? /* @__PURE__ */ b("div", {
606
+ role: "alert",
607
+ className: "flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive",
608
+ children: [/* @__PURE__ */ y(x, { className: "h-3.5 w-3.5 mt-0.5 shrink-0" }), /* @__PURE__ */ y("span", {
609
+ className: "break-words",
610
+ children: t
611
+ })]
612
+ }) : /* @__PURE__ */ b("div", {
613
+ className: "flex items-center gap-2 p-4 text-xs text-muted-foreground",
614
+ children: [/* @__PURE__ */ y(C, { className: "h-4 w-4 animate-spin" }), " Running report…"]
615
+ });
616
+ }
617
+ function Z() {
618
+ return /* @__PURE__ */ b("div", {
619
+ className: "flex flex-col items-center justify-center gap-2 rounded-md border border-dashed bg-muted/20 p-6 text-xs text-muted-foreground",
620
+ children: [/* @__PURE__ */ y(E, { className: "h-6 w-6" }), " The dataset returned no rows for this report’s scope."]
621
+ });
622
+ }
623
+ var ie = "cursor-pointer hover:bg-accent/40";
624
+ function ae({ dataset: e, rows: a, values: o, runtimeFilter: s, dataSource: c, onDrill: l }) {
625
+ let u = J(e, a, o, s, c), { fieldLabel: d } = k();
626
+ if (o.length === 0) return /* @__PURE__ */ y(Y, { dataset: e });
627
+ if (u.status === "loading" || u.status === "idle") return /* @__PURE__ */ y(X, { status: u.status });
628
+ if (u.status === "error") return /* @__PURE__ */ y(X, {
629
+ status: "error",
630
+ error: u.error
631
+ });
632
+ if (u.rows.length === 0) return /* @__PURE__ */ y(Z, {});
633
+ let f = !!l && a.length > 0, p = u.dimensionFields ? a.filter((e) => e in u.dimensionFields) : [], m = (n, r) => {
634
+ let i = {};
635
+ for (let e of a) i[e] = n[e];
636
+ let o = u.object && u.dimensionFields && p.length > 0 ? t(u.drillRawRows?.[r], p, u.dimensionFields, s) : void 0;
637
+ l({
638
+ dataset: e,
639
+ groupKey: i,
640
+ runtimeFilter: s,
641
+ object: u.object,
642
+ objectFilter: o
1865
643
  });
1866
- }, D = () => {
1867
- let e = {
1868
- field: r[0]?.name || "",
1869
- operator: "equals",
1870
- value: ""
1871
- }, t = [...f, e];
1872
- y(t), l({
1873
- ...c,
1874
- filters: t
1875
- });
1876
- }, A = (e) => {
1877
- let t = f.filter((t, n) => n !== e);
1878
- y(t), l({
1879
- ...c,
1880
- filters: t
1881
- });
1882
- }, P = (e, t) => {
1883
- let n = [...f];
1884
- n[e] = t, y(n), l({
1885
- ...c,
1886
- filters: n
1887
- });
1888
- }, F = () => {
1889
- let e = {
1890
- field: r[0]?.name || "",
1891
- sort: "asc"
1892
- }, t = [...b, e];
1893
- x(t), l({
1894
- ...c,
1895
- groupBy: t
1896
- });
1897
- }, z = (e) => {
1898
- let t = b.filter((t, n) => n !== e);
1899
- x(t), l({
1900
- ...c,
1901
- groupBy: t
1902
- });
1903
- }, B = (e, t) => {
1904
- let n = [...b];
1905
- n[e] = t, x(n), l({
1906
- ...c,
1907
- groupBy: n
1908
- });
1909
- }, V = (e) => {
1910
- let t = {
1911
- type: e,
1912
- title: `New ${e} Section`
1913
- }, n = [...S, t];
1914
- C(n), l({
1915
- ...c,
1916
- sections: n
1917
- });
1918
- }, H = (e) => {
1919
- let t = S.filter((t, n) => n !== e);
1920
- C(t), l({
1921
- ...c,
1922
- sections: t
1923
- });
1924
- }, U = (e, t) => {
1925
- let n = [...S];
1926
- n[e] = t, C(n), l({
1927
- ...c,
1928
- sections: n
1929
- });
1930
- };
1931
- return /* @__PURE__ */ R("div", {
1932
- className: "space-y-4",
1933
- children: [/* @__PURE__ */ R(m, { children: [/* @__PURE__ */ R(_, { children: [/* @__PURE__ */ L(v, { children: "Report Builder" }), /* @__PURE__ */ L(g, { children: "Configure your report settings, fields, filters, and sections" })] }), /* @__PURE__ */ R(h, { children: [/* @__PURE__ */ R(j, {
1934
- defaultValue: "basic",
1935
- className: "w-full",
1936
- children: [
1937
- /* @__PURE__ */ R(ee, {
1938
- className: "grid w-full grid-cols-6",
1939
- children: [
1940
- /* @__PURE__ */ R(N, {
1941
- value: "basic",
1942
- children: [/* @__PURE__ */ L(me, { className: "h-4 w-4 mr-2" }), "Basic"]
1943
- }),
1944
- /* @__PURE__ */ R(N, {
1945
- value: "fields",
1946
- children: [/* @__PURE__ */ L(ce, { className: "h-4 w-4 mr-2" }), "Fields"]
1947
- }),
1948
- /* @__PURE__ */ R(N, {
1949
- value: "filters",
1950
- children: [/* @__PURE__ */ L(se, { className: "h-4 w-4 mr-2" }), "Filters"]
1951
- }),
1952
- /* @__PURE__ */ R(N, {
1953
- value: "grouping",
1954
- children: [/* @__PURE__ */ L(ce, { className: "h-4 w-4 mr-2" }), "Group By"]
1955
- }),
1956
- /* @__PURE__ */ R(N, {
1957
- value: "sections",
1958
- children: [/* @__PURE__ */ L(ce, { className: "h-4 w-4 mr-2" }), "Sections"]
1959
- }),
1960
- /* @__PURE__ */ R(N, {
1961
- value: "schedule",
1962
- children: [/* @__PURE__ */ L(ne, { className: "h-4 w-4 mr-2" }), "Schedule"]
1963
- })
1964
- ]
1965
- }),
1966
- /* @__PURE__ */ L(M, {
1967
- value: "basic",
1968
- className: "space-y-4 mt-4",
1969
- children: /* @__PURE__ */ R("div", {
1970
- className: "space-y-4",
1971
- children: [
1972
- /* @__PURE__ */ R("div", {
1973
- className: "space-y-2",
1974
- children: [/* @__PURE__ */ L(k, {
1975
- htmlFor: "report-title",
1976
- children: "Report Title"
1977
- }), /* @__PURE__ */ L(O, {
1978
- id: "report-title",
1979
- value: c.title || "",
1980
- onChange: (e) => l({
1981
- ...c,
1982
- title: e.target.value
1983
- }),
1984
- placeholder: "Enter report title"
1985
- })]
1986
- }),
1987
- /* @__PURE__ */ R("div", {
1988
- className: "space-y-2",
1989
- children: [/* @__PURE__ */ L(k, {
1990
- htmlFor: "report-description",
1991
- children: "Description"
1992
- }), /* @__PURE__ */ L(O, {
1993
- id: "report-description",
1994
- value: c.description || "",
1995
- onChange: (e) => l({
1996
- ...c,
1997
- description: e.target.value
1998
- }),
1999
- placeholder: "Enter report description"
2000
- })]
2001
- }),
2002
- n.length > 0 && /* @__PURE__ */ R("div", {
2003
- className: "space-y-2",
2004
- children: [/* @__PURE__ */ L(k, { children: "Data Source" }), /* @__PURE__ */ R("select", {
2005
- className: "w-full border rounded-md p-2",
2006
- children: [/* @__PURE__ */ L("option", {
2007
- value: "",
2008
- children: "Select a data source"
2009
- }), n.map((e, t) => /* @__PURE__ */ R("option", {
2010
- value: t,
2011
- children: ["Data Source ", t + 1]
2012
- }, t))]
2013
- })]
2014
- }),
2015
- /* @__PURE__ */ R("div", {
2016
- className: "space-y-2",
2017
- children: [/* @__PURE__ */ L(k, { children: "Export Options" }), /* @__PURE__ */ R("div", {
2018
- className: "flex items-center gap-4",
2019
- children: [/* @__PURE__ */ R("label", {
2020
- className: "flex items-center gap-2",
2021
- children: [/* @__PURE__ */ L("input", {
2022
- type: "checkbox",
2023
- checked: c.showExportButtons || !1,
2024
- onChange: (e) => l({
2025
- ...c,
2026
- showExportButtons: e.target.checked
2027
- })
2028
- }), /* @__PURE__ */ L("span", {
2029
- className: "text-sm",
2030
- children: "Show Export Buttons"
2031
- })]
2032
- }), /* @__PURE__ */ R("label", {
2033
- className: "flex items-center gap-2",
2034
- children: [/* @__PURE__ */ L("input", {
2035
- type: "checkbox",
2036
- checked: c.showPrintButton || !1,
2037
- onChange: (e) => l({
2038
- ...c,
2039
- showPrintButton: e.target.checked
2040
- })
2041
- }), /* @__PURE__ */ L("span", {
2042
- className: "text-sm",
2043
- children: "Show Print Button"
2044
- })]
2045
- })]
2046
- })]
2047
- }),
2048
- /* @__PURE__ */ R("div", {
2049
- className: "space-y-2",
2050
- children: [/* @__PURE__ */ L(k, {
2051
- htmlFor: "export-format",
2052
- children: "Default Export Format"
2053
- }), /* @__PURE__ */ R("select", {
2054
- id: "export-format",
2055
- className: "w-full border rounded-md p-2",
2056
- value: c.defaultExportFormat || "pdf",
2057
- onChange: (e) => l({
2058
- ...c,
2059
- defaultExportFormat: e.target.value
2060
- }),
2061
- children: [
2062
- /* @__PURE__ */ L("option", {
2063
- value: "pdf",
2064
- children: "PDF"
2065
- }),
2066
- /* @__PURE__ */ L("option", {
2067
- value: "excel",
2068
- children: "Excel"
2069
- }),
2070
- /* @__PURE__ */ L("option", {
2071
- value: "csv",
2072
- children: "CSV"
2073
- }),
2074
- /* @__PURE__ */ L("option", {
2075
- value: "json",
2076
- children: "JSON"
2077
- }),
2078
- /* @__PURE__ */ L("option", {
2079
- value: "html",
2080
- children: "HTML"
2081
- })
2082
- ]
2083
- })]
2084
- })
2085
- ]
2086
- })
2087
- }),
2088
- /* @__PURE__ */ R(M, {
2089
- value: "fields",
2090
- className: "space-y-4 mt-4",
2091
- children: [/* @__PURE__ */ R("div", {
2092
- className: "flex items-center justify-between",
2093
- children: [/* @__PURE__ */ L(k, { children: "Report Fields" }), /* @__PURE__ */ R(p, {
2094
- size: "sm",
2095
- variant: "outline",
2096
- onClick: w,
2097
- disabled: u.length >= r.length,
2098
- children: [/* @__PURE__ */ L(W, { className: "h-4 w-4 mr-2" }), "Add Field"]
2099
- })]
2100
- }), /* @__PURE__ */ R("div", {
2101
- className: "space-y-2",
2102
- children: [u.map((e, t) => /* @__PURE__ */ L("div", {
2103
- className: "flex items-center gap-2 p-3 border rounded-lg",
2104
- children: /* @__PURE__ */ R("div", {
2105
- className: "flex-1 grid grid-cols-4 gap-2",
2106
- children: [
2107
- /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L(k, {
2108
- className: "text-xs",
2109
- children: "Field Name"
2110
- }), /* @__PURE__ */ L("div", {
2111
- className: "text-sm font-medium",
2112
- children: e.name
2113
- })] }),
2114
- /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L(k, {
2115
- className: "text-xs",
2116
- children: "Label"
2117
- }), /* @__PURE__ */ L(O, {
2118
- className: "h-8 text-sm",
2119
- value: e.label || e.name,
2120
- onChange: (n) => E(t, {
2121
- ...e,
2122
- label: n.target.value
2123
- })
2124
- })] }),
2125
- /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L(k, {
2126
- className: "text-xs",
2127
- children: "Aggregation"
2128
- }), /* @__PURE__ */ R("select", {
2129
- className: "w-full border rounded-md h-8 text-sm px-2",
2130
- value: e.aggregation || "",
2131
- onChange: (n) => E(t, {
2132
- ...e,
2133
- aggregation: n.target.value
2134
- }),
2135
- children: [
2136
- /* @__PURE__ */ L("option", {
2137
- value: "",
2138
- children: "None"
2139
- }),
2140
- /* @__PURE__ */ L("option", {
2141
- value: "sum",
2142
- children: "Sum"
2143
- }),
2144
- /* @__PURE__ */ L("option", {
2145
- value: "count",
2146
- children: "Count"
2147
- }),
2148
- /* @__PURE__ */ L("option", {
2149
- value: "avg",
2150
- children: "Average"
2151
- }),
2152
- /* @__PURE__ */ L("option", {
2153
- value: "min",
2154
- children: "Min"
2155
- }),
2156
- /* @__PURE__ */ L("option", {
2157
- value: "max",
2158
- children: "Max"
2159
- })
2160
- ]
2161
- })] }),
2162
- /* @__PURE__ */ L("div", {
2163
- className: "flex items-end justify-end",
2164
- children: /* @__PURE__ */ L(p, {
2165
- size: "sm",
2166
- variant: "ghost",
2167
- className: "text-red-500 hover:text-red-700 hover:bg-red-50",
2168
- onClick: () => T(t),
2169
- children: /* @__PURE__ */ L(G, { className: "h-4 w-4" })
2170
- })
2171
- })
2172
- ]
2173
- })
2174
- }, t)), u.length === 0 && /* @__PURE__ */ L("div", {
2175
- className: "text-center py-8 text-muted-foreground border-2 border-dashed rounded-lg",
2176
- children: "No fields selected. Click \"Add Field\" to begin."
2177
- })]
2178
- })]
2179
- }),
2180
- /* @__PURE__ */ R(M, {
2181
- value: "filters",
2182
- className: "space-y-4 mt-4",
2183
- children: [/* @__PURE__ */ R("div", {
2184
- className: "flex items-center justify-between",
2185
- children: [/* @__PURE__ */ L(k, { children: "Report Filters" }), /* @__PURE__ */ R(p, {
2186
- size: "sm",
2187
- variant: "outline",
2188
- onClick: D,
2189
- children: [/* @__PURE__ */ L(W, { className: "h-4 w-4 mr-2" }), "Add Filter"]
2190
- })]
2191
- }), /* @__PURE__ */ R("div", {
2192
- className: "space-y-2",
2193
- children: [f.map((e, t) => /* @__PURE__ */ R("div", {
2194
- className: "flex items-center gap-2 p-3 border rounded-lg",
2195
- children: [/* @__PURE__ */ R("div", {
2196
- className: "flex-1 grid grid-cols-3 gap-2",
2197
- children: [
2198
- /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L(k, {
2199
- className: "text-xs",
2200
- children: "Field"
2201
- }), /* @__PURE__ */ L("select", {
2202
- className: "w-full border rounded-md h-8 text-sm px-2",
2203
- value: e.field,
2204
- onChange: (n) => P(t, {
2205
- ...e,
2206
- field: n.target.value
2207
- }),
2208
- children: r.map((e, t) => /* @__PURE__ */ L("option", {
2209
- value: e.name,
2210
- children: e.label || e.name
2211
- }, t))
2212
- })] }),
2213
- /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L(k, {
2214
- className: "text-xs",
2215
- children: "Operator"
2216
- }), /* @__PURE__ */ R("select", {
2217
- className: "w-full border rounded-md h-8 text-sm px-2",
2218
- value: e.operator,
2219
- onChange: (n) => P(t, {
2220
- ...e,
2221
- operator: n.target.value
2222
- }),
2223
- children: [
2224
- /* @__PURE__ */ L("option", {
2225
- value: "equals",
2226
- children: "Equals"
2227
- }),
2228
- /* @__PURE__ */ L("option", {
2229
- value: "contains",
2230
- children: "Contains"
2231
- }),
2232
- /* @__PURE__ */ L("option", {
2233
- value: "gt",
2234
- children: "Greater Than"
2235
- }),
2236
- /* @__PURE__ */ L("option", {
2237
- value: "lt",
2238
- children: "Less Than"
2239
- }),
2240
- /* @__PURE__ */ L("option", {
2241
- value: "between",
2242
- children: "Between"
2243
- })
2244
- ]
2245
- })] }),
2246
- /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L(k, {
2247
- className: "text-xs",
2248
- children: "Value"
2249
- }), /* @__PURE__ */ L(O, {
2250
- className: "h-8 text-sm",
2251
- value: String(e.value),
2252
- onChange: (n) => P(t, {
2253
- ...e,
2254
- value: n.target.value
2255
- })
2256
- })] })
2257
- ]
2258
- }), /* @__PURE__ */ L(p, {
2259
- size: "sm",
2260
- variant: "ghost",
2261
- className: "text-red-500 hover:text-red-700 hover:bg-red-50 self-end",
2262
- onClick: () => A(t),
2263
- children: /* @__PURE__ */ L(G, { className: "h-4 w-4" })
2264
- })]
2265
- }, t)), f.length === 0 && /* @__PURE__ */ L("div", {
2266
- className: "text-center py-8 text-muted-foreground border-2 border-dashed rounded-lg",
2267
- children: "No filters defined."
2268
- })]
2269
- })]
2270
- }),
2271
- /* @__PURE__ */ R(M, {
2272
- value: "grouping",
2273
- className: "space-y-4 mt-4",
2274
- children: [/* @__PURE__ */ R("div", {
2275
- className: "flex items-center justify-between",
2276
- children: [/* @__PURE__ */ L(k, { children: "Grouping Rules" }), /* @__PURE__ */ R(p, {
2277
- size: "sm",
2278
- variant: "outline",
2279
- onClick: F,
2280
- children: [/* @__PURE__ */ L(W, { className: "h-4 w-4 mr-2" }), "Add Group"]
2281
- })]
2282
- }), /* @__PURE__ */ R("div", {
2283
- className: "space-y-2",
2284
- children: [b.map((e, t) => /* @__PURE__ */ R("div", {
2285
- className: "flex items-center gap-2 p-3 border rounded-lg",
2286
- children: [/* @__PURE__ */ R("div", {
2287
- className: "flex-1 grid grid-cols-2 gap-2",
2288
- children: [/* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L(k, {
2289
- className: "text-xs",
2290
- children: "Field"
2291
- }), /* @__PURE__ */ L("select", {
2292
- className: "w-full border rounded-md h-8 text-sm px-2",
2293
- value: e.field,
2294
- onChange: (n) => B(t, {
2295
- ...e,
2296
- field: n.target.value
2297
- }),
2298
- children: r.map((e, t) => /* @__PURE__ */ L("option", {
2299
- value: e.name,
2300
- children: e.label || e.name
2301
- }, t))
2302
- })] }), /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L(k, {
2303
- className: "text-xs",
2304
- children: "Sort Order"
2305
- }), /* @__PURE__ */ R("select", {
2306
- className: "w-full border rounded-md h-8 text-sm px-2",
2307
- value: e.sort || "asc",
2308
- onChange: (n) => B(t, {
2309
- ...e,
2310
- sort: n.target.value
2311
- }),
2312
- children: [/* @__PURE__ */ L("option", {
2313
- value: "asc",
2314
- children: "Ascending"
2315
- }), /* @__PURE__ */ L("option", {
2316
- value: "desc",
2317
- children: "Descending"
2318
- })]
2319
- })] })]
2320
- }), /* @__PURE__ */ L(p, {
2321
- size: "sm",
2322
- variant: "ghost",
2323
- className: "text-red-500 hover:text-red-700 hover:bg-red-50 self-end",
2324
- onClick: () => z(t),
2325
- children: /* @__PURE__ */ L(G, { className: "h-4 w-4" })
2326
- })]
2327
- }, t)), b.length === 0 && /* @__PURE__ */ L("div", {
2328
- className: "text-center py-8 text-muted-foreground border-2 border-dashed rounded-lg",
2329
- children: "No grouping rules applied."
2330
- })]
2331
- })]
2332
- }),
2333
- /* @__PURE__ */ R(M, {
2334
- value: "sections",
2335
- className: "space-y-4 mt-4",
2336
- children: [/* @__PURE__ */ R("div", {
2337
- className: "flex items-center justify-between",
2338
- children: [/* @__PURE__ */ L(k, { children: "Report Sections" }), /* @__PURE__ */ R("div", {
2339
- className: "flex gap-2",
2340
- children: [
2341
- /* @__PURE__ */ R(p, {
2342
- size: "sm",
2343
- variant: "outline",
2344
- onClick: () => V("header"),
2345
- children: [/* @__PURE__ */ L(W, { className: "h-4 w-4 mr-2" }), "Header"]
2346
- }),
2347
- /* @__PURE__ */ R(p, {
2348
- size: "sm",
2349
- variant: "outline",
2350
- onClick: () => V("chart"),
2351
- children: [/* @__PURE__ */ L(W, { className: "h-4 w-4 mr-2" }), "Chart"]
2352
- }),
2353
- /* @__PURE__ */ R(p, {
2354
- size: "sm",
2355
- variant: "outline",
2356
- onClick: () => V("table"),
2357
- children: [/* @__PURE__ */ L(W, { className: "h-4 w-4 mr-2" }), "Table"]
2358
- })
2359
- ]
2360
- })]
2361
- }), /* @__PURE__ */ R("div", {
2362
- className: "space-y-2",
2363
- children: [S.map((e, t) => /* @__PURE__ */ R("div", {
2364
- className: "p-3 border rounded-lg space-y-2",
2365
- children: [/* @__PURE__ */ R("div", {
2366
- className: "flex items-center justify-between",
2367
- children: [/* @__PURE__ */ R("div", {
2368
- className: "font-medium flex items-center gap-2",
2369
- children: [/* @__PURE__ */ L("div", {
2370
- className: "text-xs bg-muted px-2 py-0.5 rounded uppercase",
2371
- children: e.type
2372
- }), e.title]
2373
- }), /* @__PURE__ */ L(p, {
2374
- size: "sm",
2375
- variant: "ghost",
2376
- className: "text-red-500 hover:text-red-700 hover:bg-red-50",
2377
- onClick: () => H(t),
2378
- children: /* @__PURE__ */ L(G, { className: "h-4 w-4" })
2379
- })]
2380
- }), /* @__PURE__ */ R("div", {
2381
- className: "grid grid-cols-2 gap-2",
2382
- children: [
2383
- /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L(k, {
2384
- className: "text-xs",
2385
- children: "Title"
2386
- }), /* @__PURE__ */ L(O, {
2387
- className: "h-8 text-sm",
2388
- value: e.title || "",
2389
- onChange: (n) => U(t, {
2390
- ...e,
2391
- title: n.target.value
2392
- })
2393
- })] }),
2394
- e.type === "text" && /* @__PURE__ */ R("div", {
2395
- className: "col-span-2",
2396
- children: [/* @__PURE__ */ L(k, {
2397
- className: "text-xs",
2398
- children: "Content"
2399
- }), /* @__PURE__ */ L(O, {
2400
- className: "h-8 text-sm",
2401
- value: e.text || "",
2402
- onChange: (n) => U(t, {
2403
- ...e,
2404
- text: n.target.value
2405
- })
2406
- })]
2407
- }),
2408
- e.type === "chart" && /* @__PURE__ */ R("div", {
2409
- className: "col-span-2 grid grid-cols-2 gap-2 mt-2 p-2 bg-muted/20 rounded",
2410
- children: [
2411
- /* @__PURE__ */ L("div", {
2412
- className: "col-span-2",
2413
- children: /* @__PURE__ */ L(k, {
2414
- className: "text-xs font-semibold",
2415
- children: "Chart Configuration"
2416
- })
2417
- }),
2418
- /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L(k, {
2419
- className: "text-xs",
2420
- children: "Chart Type"
2421
- }), /* @__PURE__ */ R("select", {
2422
- className: "flex h-8 w-full rounded-md border border-input bg-background px-3 py-1 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
2423
- value: e.chart?.chartType || "bar",
2424
- onChange: (n) => U(t, {
2425
- ...e,
2426
- chart: {
2427
- ...e.chart,
2428
- type: "chart",
2429
- chartType: n.target.value
2430
- }
2431
- }),
2432
- children: [
2433
- /* @__PURE__ */ L("option", {
2434
- value: "bar",
2435
- children: "Bar"
2436
- }),
2437
- /* @__PURE__ */ L("option", {
2438
- value: "line",
2439
- children: "Line"
2440
- }),
2441
- /* @__PURE__ */ L("option", {
2442
- value: "area",
2443
- children: "Area"
2444
- }),
2445
- /* @__PURE__ */ L("option", {
2446
- value: "pie",
2447
- children: "Pie"
2448
- })
2449
- ]
2450
- })] }),
2451
- /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L(k, {
2452
- className: "text-xs",
2453
- children: "X-Axis Field"
2454
- }), /* @__PURE__ */ R("select", {
2455
- className: "flex h-8 w-full rounded-md border border-input bg-background px-3 py-1 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
2456
- value: e.chart?.xAxisField || "",
2457
- onChange: (n) => U(t, {
2458
- ...e,
2459
- chart: {
2460
- ...e.chart,
2461
- type: "chart",
2462
- xAxisField: n.target.value
2463
- }
2464
- }),
2465
- children: [
2466
- /* @__PURE__ */ L("option", {
2467
- value: "",
2468
- children: "Select Field..."
2469
- }),
2470
- r.map((e) => /* @__PURE__ */ L("option", {
2471
- value: e.name,
2472
- children: e.label || e.name
2473
- }, e.name)),
2474
- r.length === 0 && /* @__PURE__ */ R(I, { children: [/* @__PURE__ */ L("option", {
2475
- value: "name",
2476
- children: "Name"
2477
- }), /* @__PURE__ */ L("option", {
2478
- value: "month",
2479
- children: "Month"
2480
- })] })
2481
- ]
2482
- })] }),
2483
- /* @__PURE__ */ R("div", {
2484
- className: "col-span-2",
2485
- children: [/* @__PURE__ */ L(k, {
2486
- className: "text-xs",
2487
- children: "Y-Axis Fields (comma separated)"
2488
- }), /* @__PURE__ */ L(O, {
2489
- className: "h-8 text-sm",
2490
- placeholder: "e.g. value, count",
2491
- value: e.chart?.yAxisFields?.join(", ") || "",
2492
- onChange: (n) => U(t, {
2493
- ...e,
2494
- chart: {
2495
- ...e.chart,
2496
- type: "chart",
2497
- yAxisFields: n.target.value.split(",").map((e) => e.trim()).filter(Boolean)
2498
- }
2499
- })
2500
- })]
2501
- })
2502
- ]
2503
- })
2504
- ]
2505
- })]
2506
- }, t)), S.length === 0 && /* @__PURE__ */ L("div", {
2507
- className: "text-center py-8 text-muted-foreground border-2 border-dashed rounded-lg",
2508
- children: "No customized sections. The default report layout will be used."
2509
- })]
2510
- })]
2511
- }),
2512
- /* @__PURE__ */ L(M, {
2513
- value: "schedule",
2514
- className: "space-y-4 mt-4",
2515
- children: /* @__PURE__ */ L(ht, {
2516
- schedule: c.schedule,
2517
- onChange: (e) => l({
2518
- ...c,
2519
- schedule: e
2520
- })
2521
- })
2522
- })
2523
- ]
2524
- }), /* @__PURE__ */ R("div", {
2525
- className: "flex items-center justify-end gap-2 mt-6 pt-4 border-t",
2526
- children: [/* @__PURE__ */ L(p, {
2527
- variant: "outline",
2528
- onClick: () => {
2529
- o && console.log("Report cancelled:", o);
2530
- },
2531
- children: "Cancel"
2532
- }), /* @__PURE__ */ R(p, {
2533
- onClick: () => {
2534
- console.log("Saving report:", c), a && alert("Report saved! (Handler: " + a + ")");
2535
- },
2536
- children: [/* @__PURE__ */ L(fe, { className: "h-4 w-4 mr-2" }), "Save Report"]
2537
- })]
2538
- })] })] }), i && /* @__PURE__ */ R(m, {
2539
- className: "mt-8 border-2 border-blue-100",
2540
- children: [/* @__PURE__ */ L(_, {
2541
- className: "bg-blue-50/50",
2542
- children: /* @__PURE__ */ L(v, {
2543
- className: "text-blue-900 text-sm uppercase tracking-wide",
2544
- children: "Live Preview"
2545
- })
2546
- }), /* @__PURE__ */ L(h, {
2547
- className: "pt-6",
2548
- children: /* @__PURE__ */ L(mt, { schema: {
2549
- type: "report-viewer",
2550
- report: {
2551
- ...c,
2552
- fields: u,
2553
- filters: f,
2554
- groupBy: b,
2555
- sections: S
2556
- },
2557
- data: [
2558
- {
2559
- id: 1,
2560
- name: "Sample Item A",
2561
- value: 100,
2562
- status: "New"
2563
- },
2564
- {
2565
- id: 2,
2566
- name: "Sample Item B",
2567
- value: 250,
2568
- status: "Active"
2569
- },
2570
- {
2571
- id: 3,
2572
- name: "Sample Item C",
2573
- value: 75,
2574
- status: "Closed"
2575
- }
2576
- ]
2577
- } })
2578
- })]
2579
- })]
644
+ }, { measureField: h, headerLabel: g } = n(u.fields, u.object, d), _ = [...a, ...o];
645
+ return /* @__PURE__ */ y("div", {
646
+ className: "overflow-auto max-h-[70vh] rounded-md border",
647
+ children: /* @__PURE__ */ b("table", {
648
+ className: "w-full text-xs",
649
+ children: [/* @__PURE__ */ y("thead", {
650
+ className: "bg-muted/40",
651
+ children: /* @__PURE__ */ y("tr", { children: _.map((e) => /* @__PURE__ */ y("th", {
652
+ className: "px-2 py-1.5 text-left font-medium whitespace-nowrap",
653
+ children: g(e)
654
+ }, e)) })
655
+ }), /* @__PURE__ */ y("tbody", { children: u.rows.map((e, t) => /* @__PURE__ */ y("tr", {
656
+ className: `border-t${f ? ` ${ie}` : ""}`,
657
+ "data-testid": f ? "dataset-drill-row" : void 0,
658
+ onClick: f ? () => m(e, t) : void 0,
659
+ children: _.map((t) => /* @__PURE__ */ y("td", {
660
+ className: "px-2 py-1 tabular-nums whitespace-nowrap",
661
+ children: o.includes(t) ? i(e[t], h(t)?.format, h(t)?.currency) : r(e[t])
662
+ }, t))
663
+ }, t)) })]
664
+ })
2580
665
  });
2581
- }, _t = [
2582
- "tabular",
2583
- "summary",
2584
- "matrix"
2585
- ];
2586
- function vt(e) {
2587
- let t = e.length + 1, n = new Set(e.map((e) => e.name).filter(Boolean)), r = `block_${t}`;
2588
- for (; n.has(r);) t += 1, r = `block_${t}`;
2589
- return {
2590
- name: r,
2591
- type: "tabular",
2592
- columns: []
2593
- };
2594
- }
2595
- function yt(e) {
2596
- return typeof e.label == "string" ? e.label : e.label && typeof e.label == "object" ? e.label.default ?? "" : "";
2597
666
  }
2598
- function bt(e) {
2599
- return typeof e.description == "string" ? e.description : e.description && typeof e.description == "object" ? e.description.default ?? "" : "";
667
+ function oe(e) {
668
+ switch (e) {
669
+ case "line": return "line";
670
+ case "area": return "area";
671
+ case "pie": return "pie";
672
+ case "donut": return "donut";
673
+ case "radar": return "radar";
674
+ case "scatter": return "scatter";
675
+ default: return "bar";
676
+ }
2600
677
  }
2601
- function xt({ block: e, index: n, total: r, availableFields: i, t: a, duplicateName: o, onChange: s, onRemove: c, onMove: l }) {
2602
- let [u, d] = t.useState(n === 0), f = e.type ?? "tabular", m = f === "summary", h = f === "matrix", g = m || h, _ = !e.name || !e.name.trim(), v = _ || o, y = (t) => s({
2603
- ...e,
2604
- ...t
2605
- });
2606
- return /* @__PURE__ */ R("div", {
2607
- className: "border rounded-md bg-card text-card-foreground",
2608
- "data-testid": `joined-block-${n}`,
2609
- children: [
2610
- /* @__PURE__ */ R("div", {
2611
- className: "flex items-center gap-1 p-1.5 border-b bg-muted/30",
2612
- children: [
2613
- /* @__PURE__ */ L(p, {
2614
- type: "button",
2615
- size: "sm",
2616
- variant: "ghost",
2617
- className: "h-6 w-6 p-0 shrink-0",
2618
- onClick: () => d((e) => !e),
2619
- "aria-label": u ? "Collapse block" : "Expand block",
2620
- "aria-expanded": u,
2621
- "data-testid": `joined-block-toggle-${n}`,
2622
- children: L(u ? re : ie, { className: "h-3.5 w-3.5" })
2623
- }),
2624
- /* @__PURE__ */ L("input", {
2625
- type: "text",
2626
- className: `h-6 text-xs border rounded px-1.5 bg-background flex-1 min-w-0 ${v ? "border-destructive" : ""}`,
2627
- value: e.name ?? "",
2628
- onChange: (e) => y({ name: e.target.value }),
2629
- placeholder: a("report.editor.blockNamePlaceholder"),
2630
- "aria-label": a("report.editor.blockName"),
2631
- "aria-invalid": v,
2632
- "data-testid": `joined-block-name-${n}`
2633
- }),
2634
- /* @__PURE__ */ L("select", {
2635
- className: "h-6 text-xs border rounded px-1 bg-background shrink-0",
2636
- value: f,
2637
- onChange: (e) => y({ type: e.target.value }),
2638
- "aria-label": a("report.editor.type"),
2639
- "data-testid": `joined-block-type-${n}`,
2640
- children: _t.map((e) => /* @__PURE__ */ L("option", {
2641
- value: e,
2642
- children: a(`report.editor.type${e.charAt(0).toUpperCase()}${e.slice(1)}`)
2643
- }, e))
2644
- }),
2645
- /* @__PURE__ */ R("div", {
2646
- className: "flex flex-col gap-0.5 shrink-0",
2647
- children: [/* @__PURE__ */ L("button", {
2648
- type: "button",
2649
- className: "text-muted-foreground hover:text-foreground disabled:opacity-30",
2650
- disabled: n === 0,
2651
- onClick: () => l(-1),
2652
- "aria-label": "Move block up",
2653
- children: /* @__PURE__ */ L(te, { className: "h-2.5 w-2.5" })
2654
- }), /* @__PURE__ */ L("button", {
2655
- type: "button",
2656
- className: "text-muted-foreground hover:text-foreground disabled:opacity-30",
2657
- disabled: n === r - 1,
2658
- onClick: () => l(1),
2659
- "aria-label": "Move block down",
2660
- children: /* @__PURE__ */ L(U, { className: "h-2.5 w-2.5" })
2661
- })]
2662
- }),
2663
- /* @__PURE__ */ L(p, {
2664
- type: "button",
2665
- size: "sm",
2666
- variant: "ghost",
2667
- className: "h-6 w-6 p-0 shrink-0 text-destructive hover:text-destructive",
2668
- onClick: c,
2669
- "aria-label": a("report.editor.removeBlock"),
2670
- "data-testid": `joined-block-remove-${n}`,
2671
- children: /* @__PURE__ */ L(G, { className: "h-3 w-3" })
2672
- })
2673
- ]
2674
- }),
2675
- v && /* @__PURE__ */ R("div", {
2676
- className: "flex items-center gap-1 px-2 py-1 text-[10px] text-destructive bg-destructive/5 border-b",
2677
- children: [/* @__PURE__ */ L(H, { className: "h-3 w-3" }), a(_ ? "report.editor.validationBlockNameRequired" : "report.editor.validationBlockNameDuplicate")]
2678
- }),
2679
- u && /* @__PURE__ */ R("div", {
2680
- className: "p-2 space-y-2 text-xs",
2681
- children: [
2682
- /* @__PURE__ */ R("div", {
2683
- className: "grid grid-cols-2 gap-2",
2684
- children: [/* @__PURE__ */ R("label", {
2685
- className: "flex flex-col gap-0.5",
2686
- children: [/* @__PURE__ */ L("span", {
2687
- className: "text-[10px] text-muted-foreground",
2688
- children: a("report.editor.blockLabel")
2689
- }), /* @__PURE__ */ L("input", {
2690
- type: "text",
2691
- className: "h-6 text-xs border rounded px-1.5 bg-background",
2692
- value: yt(e),
2693
- onChange: (e) => y({ label: e.target.value || void 0 }),
2694
- placeholder: a("report.editor.blockLabelPlaceholder"),
2695
- "data-testid": `joined-block-label-${n}`
2696
- })]
2697
- }), /* @__PURE__ */ R("label", {
2698
- className: "flex flex-col gap-0.5",
2699
- children: [/* @__PURE__ */ L("span", {
2700
- className: "text-[10px] text-muted-foreground",
2701
- children: a("report.editor.objectName")
2702
- }), /* @__PURE__ */ L("input", {
2703
- type: "text",
2704
- className: "h-6 text-xs border rounded px-1.5 bg-background",
2705
- value: e.objectName ?? "",
2706
- onChange: (e) => y({ objectName: e.target.value || void 0 }),
2707
- placeholder: a("report.editor.objectNamePlaceholder"),
2708
- "data-testid": `joined-block-object-${n}`
2709
- })]
2710
- })]
2711
- }),
2712
- /* @__PURE__ */ R("label", {
2713
- className: "flex flex-col gap-0.5",
2714
- children: [/* @__PURE__ */ L("span", {
2715
- className: "text-[10px] text-muted-foreground",
2716
- children: a("report.editor.blockDescription")
2717
- }), /* @__PURE__ */ L("textarea", {
2718
- className: "text-xs border rounded px-1.5 py-1 bg-background resize-y min-h-[2rem]",
2719
- rows: 2,
2720
- value: bt(e),
2721
- onChange: (e) => y({ description: e.target.value || void 0 }),
2722
- placeholder: a("report.editor.blockDescriptionPlaceholder"),
2723
- "data-testid": `joined-block-description-${n}`
2724
- })]
2725
- }),
2726
- /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("div", {
2727
- className: "text-[10px] text-muted-foreground mb-0.5",
2728
- children: a("report.editor.columns")
2729
- }), /* @__PURE__ */ L(Bt, {
2730
- availableFields: i,
2731
- value: e.columns,
2732
- onChange: (e) => y({ columns: e }),
2733
- t: a
2734
- })] }),
2735
- (m || h) && /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("div", {
2736
- className: "text-[10px] text-muted-foreground mb-0.5",
2737
- children: a("report.editor.rows")
2738
- }), /* @__PURE__ */ L(Vt, {
2739
- availableFields: i,
2740
- value: e.groupingsDown,
2741
- onChange: (e) => y({ groupingsDown: e }),
2742
- t: a
2743
- })] }),
2744
- h && /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("div", {
2745
- className: "text-[10px] text-muted-foreground mb-0.5",
2746
- children: a("report.editor.columnsAxis")
2747
- }), /* @__PURE__ */ L(Vt, {
2748
- availableFields: i,
2749
- value: e.groupingsAcross,
2750
- onChange: (e) => y({ groupingsAcross: e }),
2751
- t: a
2752
- })] }),
2753
- /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("div", {
2754
- className: "text-[10px] text-muted-foreground mb-0.5",
2755
- children: a("report.editor.filters")
2756
- }), /* @__PURE__ */ L(Nt, {
2757
- availableFields: i,
2758
- value: e.filter,
2759
- onChange: (e) => y({ filter: e }),
2760
- t: a
2761
- })] }),
2762
- g && /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("div", {
2763
- className: "text-[10px] text-muted-foreground mb-0.5",
2764
- children: a("report.editor.chart")
2765
- }), /* @__PURE__ */ L(Ht, {
2766
- availableFields: i,
2767
- columns: zt(e.columns),
2768
- value: e.chart,
2769
- onChange: (e) => y({ chart: e }),
2770
- t: a
2771
- })] })
2772
- ]
2773
- })
2774
- ]
678
+ function se(t) {
679
+ let [, n] = a.useReducer((e) => e + 1, 0);
680
+ return a.useEffect(() => {
681
+ if (e.get(t)) return;
682
+ let r = typeof e.subscribe == "function" ? e.subscribe(() => {
683
+ e.get(t) && n();
684
+ }) : void 0, i = e.loadLazy?.(t);
685
+ return i && typeof i.then == "function" && i.then(() => n()).catch(() => {}), r;
686
+ }, [t]), e.get(t);
687
+ }
688
+ function ce({ dataset: e, chart: t, runtimeFilter: n, dataSource: r }) {
689
+ let i = typeof t.xAxis == "string" ? t.xAxis : "", a = typeof t.yAxis == "string" ? t.yAxis : "", o = J(e, i ? [i] : [], a ? [a] : [], n, r), s = se("chart");
690
+ if (!i || !a) return null;
691
+ if (o.status === "loading" || o.status === "idle") return /* @__PURE__ */ b("div", {
692
+ className: "flex items-center gap-2 p-4 text-xs text-muted-foreground",
693
+ children: [/* @__PURE__ */ y(C, { className: "h-4 w-4 animate-spin" }), " Loading chart…"]
2775
694
  });
2776
- }
2777
- function St(e) {
2778
- return Array.isArray(e) ? e.map((e) => {
2779
- let t = e ?? {};
2780
- return {
2781
- name: t.name ?? "",
2782
- type: t.type ?? "tabular",
2783
- columns: Array.isArray(t.columns) ? t.columns : [],
2784
- ...t
2785
- };
2786
- }) : [];
2787
- }
2788
- function Ct({ value: e, onChange: t, availableFields: n, getFieldsForObject: r, containerObjectName: i, t: a }) {
2789
- let o = St(e), s = (e) => r ? r(e.objectName ?? i) ?? n : n, c = {};
2790
- for (let e of o) e.name && (c[e.name] = (c[e.name] ?? 0) + 1);
2791
- let l = (e, n) => {
2792
- t(o.map((t, r) => r === e ? n : t));
2793
- }, u = (e) => {
2794
- t(o.filter((t, n) => n !== e));
2795
- }, d = (e, n) => {
2796
- let r = e + n;
2797
- if (r < 0 || r >= o.length) return;
2798
- let i = [...o];
2799
- [i[e], i[r]] = [i[r], i[e]], t(i);
2800
- };
2801
- return /* @__PURE__ */ R("div", {
2802
- className: "space-y-2",
2803
- "data-testid": "joined-blocks-editor",
2804
- children: [
2805
- o.length === 0 && /* @__PURE__ */ L("div", {
2806
- className: "text-[10px] text-muted-foreground italic px-1",
2807
- children: a("report.editor.validationJoinedNeedsBlocks")
2808
- }),
2809
- o.map((e, t) => /* @__PURE__ */ L(xt, {
2810
- block: e,
2811
- index: t,
2812
- total: o.length,
2813
- availableFields: s(e),
2814
- t: a,
2815
- duplicateName: !!e.name && (c[e.name] ?? 0) > 1,
2816
- onChange: (e) => l(t, e),
2817
- onRemove: () => u(t),
2818
- onMove: (e) => d(t, e)
2819
- }, t)),
2820
- /* @__PURE__ */ R(p, {
2821
- type: "button",
2822
- size: "sm",
2823
- variant: "outline",
2824
- className: "h-7 text-xs w-full",
2825
- onClick: () => {
2826
- t([...o, vt(o)]);
2827
- },
2828
- "data-testid": "joined-block-add",
2829
- children: [/* @__PURE__ */ L(W, { className: "h-3 w-3 mr-1" }), a("report.editor.addBlock")]
2830
- })
2831
- ]
695
+ if (o.status === "error" || o.rows.length === 0 || !s) return null;
696
+ let c = typeof t.title == "string" ? t.title : void 0;
697
+ return /* @__PURE__ */ b("div", {
698
+ className: "rounded-md border bg-card p-3",
699
+ "data-testid": "dataset-report-chart",
700
+ children: [c ? /* @__PURE__ */ y("h3", {
701
+ className: "mb-2 text-sm font-semibold",
702
+ children: c
703
+ }) : null, /* @__PURE__ */ y(s, { schema: {
704
+ chartType: oe(t.type),
705
+ data: o.rows,
706
+ xAxisKey: i,
707
+ series: [{ dataKey: a }],
708
+ height: typeof t.height == "number" ? t.height : 280,
709
+ isAnimationActive: !1
710
+ } })]
2832
711
  });
2833
712
  }
2834
- function wt(e, t) {
2835
- let n = [];
2836
- if (!Array.isArray(e) || e.length === 0) return n.push(t("report.editor.validationJoinedNeedsBlocks")), n;
2837
- let r = /* @__PURE__ */ new Map(), i = !1, a = !1, o = !1;
2838
- for (let t of e) {
2839
- let e = t ?? {};
2840
- if (!e.name || !String(e.name).trim()) i = !0;
2841
- else {
2842
- let t = (r.get(e.name) ?? 0) + 1;
2843
- r.set(e.name, t), t === 2 && (a = !0);
2844
- }
2845
- (!Array.isArray(e.columns) || e.columns.length === 0) && (o = !0);
2846
- }
2847
- return i && n.push(t("report.editor.validationBlockNameRequired")), a && n.push(t("report.editor.validationBlockNameDuplicate")), o && n.push(t("report.editor.validationBlockNeedsColumns")), n;
2848
- }
2849
- //#endregion
2850
- //#region src/specFilterAdapter.tsx
2851
- var Tt = {
2852
- $eq: "equals",
2853
- $ne: "notEquals",
2854
- $gt: "greaterThan",
2855
- $gte: "greaterOrEqual",
2856
- $lt: "lessThan",
2857
- $lte: "lessOrEqual",
2858
- $in: "in",
2859
- $nin: "notIn",
2860
- $contains: "contains",
2861
- $notContains: "notContains",
2862
- $exists: "isNotEmpty"
2863
- }, Et = {
2864
- equals: "$eq",
2865
- notEquals: "$ne",
2866
- greaterThan: "$gt",
2867
- greaterOrEqual: "$gte",
2868
- lessThan: "$lt",
2869
- lessOrEqual: "$lte",
2870
- in: "$in",
2871
- notIn: "$nin",
2872
- contains: "$contains",
2873
- notContains: "$notContains"
2874
- }, Dt = () => ({
2875
- id: "root",
2876
- logic: "and",
2877
- conditions: []
2878
- });
2879
- function Ot(e) {
2880
- return !!e && typeof e == "object" && !Array.isArray(e);
2881
- }
2882
- function $() {
2883
- return Math.random().toString(36).slice(2, 10);
713
+ function Q(e, t) {
714
+ return e.map((e) => String(t[e] ?? "∅")).join("");
2884
715
  }
2885
- function kt(e, t) {
2886
- if (typeof t != "object" || !t || Array.isArray(t)) return [{
2887
- id: $(),
2888
- field: e,
2889
- operator: Array.isArray(t) ? "in" : "equals",
2890
- value: t
2891
- }];
2892
- let n = [];
2893
- for (let [r, i] of Object.entries(t)) {
2894
- if (r === "$exists") {
2895
- n.push({
2896
- id: $(),
2897
- field: e,
2898
- operator: i === !1 ? "isEmpty" : "isNotEmpty",
2899
- value: ""
2900
- });
2901
- continue;
2902
- }
2903
- if (r === "$null") {
2904
- n.push({
2905
- id: $(),
2906
- field: e,
2907
- operator: i === !1 ? "isNotEmpty" : "isEmpty",
2908
- value: ""
2909
- });
2910
- continue;
2911
- }
2912
- let t = Tt[r];
2913
- if (!t || Ot(i) && "$field" in i) return null;
2914
- n.push({
2915
- id: $(),
2916
- field: e,
2917
- operator: t,
2918
- value: i
2919
- });
2920
- }
2921
- return n.length > 0 ? n : null;
716
+ function le(e, t) {
717
+ return e.map((e) => r(t[e])).join(" / ");
2922
718
  }
2923
- function At(e) {
2924
- if (e == null) return {
2925
- group: Dt(),
2926
- complex: !1
2927
- };
2928
- if (!Ot(e)) return {
2929
- group: Dt(),
2930
- complex: !0
2931
- };
2932
- let t = Object.keys(e);
2933
- if (t.length === 1 && (t[0] === "$and" || t[0] === "$or")) {
2934
- let n = t[0] === "$or" ? "or" : "and", r = e[t[0]];
2935
- if (!Array.isArray(r)) return {
2936
- group: Dt(),
2937
- complex: !0
2938
- };
2939
- let i = [], a = !1;
2940
- for (let e of r) {
2941
- if (!Ot(e)) {
2942
- a = !0;
2943
- continue;
2944
- }
2945
- if (Object.keys(e).some((e) => e === "$and" || e === "$or" || e === "$not")) {
2946
- a = !0;
2947
- continue;
719
+ function ue({ dataset: e, rows: o, columnsAcross: s, values: c, runtimeFilter: l, dataSource: u, onDrill: d }) {
720
+ let f = J(e, [...o, ...s], c, l, u, [
721
+ o,
722
+ s,
723
+ []
724
+ ]), p = A(), { fieldLabel: m } = k(), h = a.useMemo(() => {
725
+ if (f.status !== "ok") return null;
726
+ let e = [], t = [], n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Map();
727
+ return f.rows.forEach((a, c) => {
728
+ let l = Q(o, a), u = Q(s, a);
729
+ if (!n.has(l)) {
730
+ n.add(l);
731
+ let t = {};
732
+ for (let e of o) t[e] = a[e];
733
+ e.push({
734
+ id: l,
735
+ label: le(o, a),
736
+ key: t
737
+ });
2948
738
  }
2949
- for (let [t, n] of Object.entries(e)) {
2950
- let e = kt(t, n);
2951
- e ? i.push(...e) : a = !0;
739
+ if (!r.has(u)) {
740
+ r.add(u);
741
+ let e = {};
742
+ for (let t of s) e[t] = a[t];
743
+ t.push({
744
+ id: u,
745
+ label: le(s, a),
746
+ key: e
747
+ });
2952
748
  }
2953
- }
2954
- return {
2955
- group: {
2956
- id: "root",
2957
- logic: n,
2958
- conditions: i
2959
- },
2960
- complex: a
749
+ i.set(`${l} ${u}`, {
750
+ row: a,
751
+ index: c
752
+ });
753
+ }), {
754
+ rowHeaders: e,
755
+ colHeaders: t,
756
+ cells: i
2961
757
  };
2962
- }
2963
- if (t.includes("$not") || t.includes("$and") || t.includes("$or")) return {
2964
- group: Dt(),
2965
- complex: !0
2966
- };
2967
- let n = [], r = !1;
2968
- for (let [t, i] of Object.entries(e)) {
2969
- let e = kt(t, i);
2970
- e ? n.push(...e) : r = !0;
2971
- }
2972
- return {
2973
- group: {
2974
- id: "root",
2975
- logic: "and",
2976
- conditions: n
2977
- },
2978
- complex: r
2979
- };
2980
- }
2981
- function jt(e) {
2982
- if (!e || !Array.isArray(e.conditions) || e.conditions.length === 0) return;
2983
- let t = e.conditions.filter((e) => e.field).map((e) => Mt(e));
2984
- if (t.length !== 0) return t.length === 1 ? t[0] : { [e.logic === "or" ? "$or" : "$and"]: t };
2985
- }
2986
- function Mt(e) {
2987
- let { field: t, operator: n, value: r } = e;
2988
- if (n === "isEmpty") return { [t]: { $exists: !1 } };
2989
- if (n === "isNotEmpty") return { [t]: { $exists: !0 } };
2990
- if (n === "equals") return { [t]: r };
2991
- let i = Et[n];
2992
- return i ? { [t]: { [i]: r } } : { [t]: r };
2993
- }
2994
- function Nt({ availableFields: e, value: n, onChange: r, t: i }) {
2995
- let a = t.useMemo(() => JSON.stringify(n ?? null), [n]), o = t.useMemo(() => At(n), [a]), [s, c] = t.useState(o.group), l = t.useRef(a);
2996
- t.useEffect(() => {
2997
- l.current !== a && (c(o.group), l.current = a);
2998
- }, [a, o.group]);
2999
- let u = (e) => {
3000
- c(e);
3001
- let t = jt(e);
3002
- l.current = JSON.stringify(t ?? null), r(t);
3003
- };
3004
- if (o.complex) return /* @__PURE__ */ R("div", {
3005
- className: "flex items-start gap-2 p-2 rounded border border-amber-300 bg-amber-50 text-amber-900 text-[11px]",
3006
- children: [/* @__PURE__ */ L(H, { className: "h-3.5 w-3.5 mt-0.5 shrink-0" }), /* @__PURE__ */ L("span", { children: i("report.editor.filtersComplex") })]
758
+ }, [
759
+ f,
760
+ o,
761
+ s
762
+ ]);
763
+ if (c.length === 0) return /* @__PURE__ */ y(Y, { dataset: e });
764
+ if (f.status === "loading" || f.status === "idle") return /* @__PURE__ */ y(X, { status: f.status });
765
+ if (f.status === "error") return /* @__PURE__ */ y(X, {
766
+ status: "error",
767
+ error: f.error
3007
768
  });
3008
- let d = () => {
3009
- u({
3010
- ...s,
3011
- conditions: [...s.conditions, {
3012
- id: $(),
3013
- field: e[0]?.value ?? "",
3014
- operator: "equals",
3015
- value: ""
3016
- }]
3017
- });
3018
- }, f = (e) => {
3019
- u({
3020
- ...s,
3021
- conditions: s.conditions.filter((t) => t.id !== e)
3022
- });
3023
- }, m = (e, t) => {
3024
- u({
3025
- ...s,
3026
- conditions: s.conditions.map((n) => n.id === e ? {
769
+ if (!h || h.rowHeaders.length === 0) return /* @__PURE__ */ y(Z, {});
770
+ let { measureField: g, headerLabel: _ } = n(f.fields, f.object, m), v = p("report.total", "Total"), x = !!d, S = f.dimensionFields ? [...o, ...s].filter((e) => e in f.dimensionFields) : [], C = (n, r, i) => {
771
+ let a = f.object && f.dimensionFields && S.length > 0 ? t(f.drillRawRows?.[i], S, f.dimensionFields, l) : void 0;
772
+ d({
773
+ dataset: e,
774
+ groupKey: {
3027
775
  ...n,
3028
- ...t
3029
- } : n)
776
+ ...r
777
+ },
778
+ runtimeFilter: l,
779
+ object: f.object,
780
+ objectFilter: a
3030
781
  });
3031
- }, h = [
3032
- {
3033
- value: "equals",
3034
- label: "="
3035
- },
3036
- {
3037
- value: "notEquals",
3038
- label: "≠"
3039
- },
3040
- {
3041
- value: "greaterThan",
3042
- label: ">"
3043
- },
3044
- {
3045
- value: "greaterOrEqual",
3046
- label: "≥"
3047
- },
3048
- {
3049
- value: "lessThan",
3050
- label: "<"
3051
- },
3052
- {
3053
- value: "lessOrEqual",
3054
- label: "≤"
3055
- },
3056
- {
3057
- value: "contains",
3058
- label: i("report.editor.opContains", "contains")
3059
- },
3060
- {
3061
- value: "in",
3062
- label: "in"
3063
- },
3064
- {
3065
- value: "notIn",
3066
- label: "not in"
3067
- },
3068
- {
3069
- value: "isEmpty",
3070
- label: i("report.editor.opIsEmpty", "is empty")
3071
- },
3072
- {
3073
- value: "isNotEmpty",
3074
- label: i("report.editor.opIsNotEmpty", "is not empty")
3075
- }
3076
- ];
3077
- return /* @__PURE__ */ R("div", {
3078
- className: "space-y-1.5 py-1",
3079
- "data-testid": "spec-filter-adapter",
3080
- children: [
3081
- s.conditions.length > 1 && /* @__PURE__ */ R("div", {
3082
- className: "flex items-center gap-2 text-[10px] text-muted-foreground",
3083
- children: [/* @__PURE__ */ L("span", { children: i("report.editor.combineLogic", "Combine with") }), /* @__PURE__ */ R("select", {
3084
- className: "h-5 text-[10px] border rounded px-1 bg-background",
3085
- value: s.logic,
3086
- onChange: (e) => u({
3087
- ...s,
3088
- logic: e.target.value
3089
- }),
3090
- "data-testid": "filter-logic-select",
3091
- children: [/* @__PURE__ */ L("option", {
3092
- value: "and",
3093
- children: "AND"
3094
- }), /* @__PURE__ */ L("option", {
3095
- value: "or",
3096
- children: "OR"
3097
- })]
3098
- })]
3099
- }),
3100
- s.conditions.map((t) => /* @__PURE__ */ R("div", {
3101
- className: "flex items-center gap-1 text-[10px] p-1 border rounded bg-muted/20",
782
+ }, w = h.colHeaders.flatMap((e) => c.map((t) => ({
783
+ col: e,
784
+ measure: t,
785
+ header: c.length === 1 ? e.label : `${e.label} · ${_(t)}`
786
+ }))), T = (e) => f.totals?.find((t) => Array.isArray(t.dimensions) && t.dimensions.join(",") === e.join(","))?.rows, E = /* @__PURE__ */ new Map();
787
+ for (let e of T(o) ?? []) E.set(Q(o, e), e);
788
+ let D = /* @__PURE__ */ new Map();
789
+ for (let e of T(s) ?? []) D.set(Q(s, e), e);
790
+ let O = T([])?.[0], j = E.size > 0, M = D.size > 0;
791
+ return /* @__PURE__ */ y("div", {
792
+ className: "overflow-auto max-h-[70vh] rounded-md border",
793
+ "data-testid": "dataset-matrix",
794
+ children: /* @__PURE__ */ b("table", {
795
+ className: "w-full text-xs",
796
+ children: [/* @__PURE__ */ y("thead", {
797
+ className: "bg-muted/40",
798
+ children: /* @__PURE__ */ b("tr", { children: [
799
+ o.map((e) => /* @__PURE__ */ y("th", {
800
+ className: "px-2 py-1.5 text-left font-medium whitespace-nowrap",
801
+ children: _(e)
802
+ }, e)),
803
+ w.map((e) => /* @__PURE__ */ y("th", {
804
+ className: "px-2 py-1.5 text-right font-medium whitespace-nowrap",
805
+ children: e.header
806
+ }, `${e.col.id}-${e.measure}`)),
807
+ j && c.map((e) => /* @__PURE__ */ y("th", {
808
+ className: "px-2 py-1.5 text-right font-medium whitespace-nowrap",
809
+ "data-testid": "matrix-total-col-header",
810
+ children: c.length === 1 ? v : `${v} · ${_(e)}`
811
+ }, `total-${e}`))
812
+ ] })
813
+ }), /* @__PURE__ */ b("tbody", { children: [h.rowHeaders.map((e) => /* @__PURE__ */ b("tr", {
814
+ className: "border-t",
3102
815
  children: [
3103
- /* @__PURE__ */ L("select", {
3104
- className: "h-5 text-[10px] border rounded px-1 bg-background flex-1 min-w-0",
3105
- value: t.field,
3106
- onChange: (e) => m(t.id, { field: e.target.value }),
3107
- "data-testid": `filter-field-${t.id}`,
3108
- children: e.map((e) => /* @__PURE__ */ L("option", {
3109
- value: e.value,
3110
- children: e.label
3111
- }, e.value))
3112
- }),
3113
- /* @__PURE__ */ L("select", {
3114
- className: "h-5 text-[10px] border rounded px-1 bg-background w-20 shrink-0",
3115
- value: t.operator,
3116
- onChange: (e) => m(t.id, { operator: e.target.value }),
3117
- "data-testid": `filter-op-${t.id}`,
3118
- children: h.map((e) => /* @__PURE__ */ L("option", {
3119
- value: e.value,
3120
- children: e.label
3121
- }, e.value))
3122
- }),
3123
- t.operator !== "isEmpty" && t.operator !== "isNotEmpty" && /* @__PURE__ */ L("input", {
3124
- className: "h-5 text-[10px] border rounded px-1 bg-background w-24 shrink-0",
3125
- value: Array.isArray(t.value) ? t.value.join(",") : (t.value ?? "").toString(),
3126
- placeholder: "value",
3127
- onChange: (e) => {
3128
- let n = e.target.value, r = t.operator === "in" || t.operator === "notIn" ? n.split(",").map((e) => e.trim()).filter(Boolean) : n;
3129
- m(t.id, { value: r });
3130
- },
3131
- "data-testid": `filter-value-${t.id}`
816
+ o.map((t) => /* @__PURE__ */ y("td", {
817
+ className: "px-2 py-1 whitespace-nowrap font-medium",
818
+ children: r(e.key[t])
819
+ }, t)),
820
+ w.map((t) => {
821
+ let n = h.cells.get(`${e.id} ${t.col.id}`), r = n?.row[t.measure], a = x && n != null;
822
+ return /* @__PURE__ */ y("td", {
823
+ className: `px-2 py-1 text-right tabular-nums whitespace-nowrap${a ? ` ${ie}` : ""}`,
824
+ "data-testid": a ? "dataset-drill-cell" : void 0,
825
+ onClick: a ? () => C(e.key, t.col.key, n.index) : void 0,
826
+ children: i(r, g(t.measure)?.format, g(t.measure)?.currency)
827
+ }, `${t.col.id}-${t.measure}`);
3132
828
  }),
3133
- /* @__PURE__ */ L(p, {
3134
- type: "button",
3135
- size: "sm",
3136
- variant: "ghost",
3137
- className: "h-5 w-5 p-0 shrink-0",
3138
- onClick: () => f(t.id),
3139
- "data-testid": `filter-remove-${t.id}`,
3140
- children: /* @__PURE__ */ L(G, { className: "h-3 w-3" })
3141
- })
829
+ j && c.map((t) => /* @__PURE__ */ y("td", {
830
+ className: "px-2 py-1 text-right tabular-nums whitespace-nowrap font-medium",
831
+ "data-testid": "matrix-row-total",
832
+ children: i(E.get(e.id)?.[t], g(t)?.format, g(t)?.currency)
833
+ }, `total-${t}`))
3142
834
  ]
3143
- }, t.id)),
3144
- /* @__PURE__ */ R(p, {
3145
- type: "button",
3146
- size: "sm",
3147
- variant: "outline",
3148
- className: "h-6 text-[10px] w-full",
3149
- onClick: d,
3150
- disabled: e.length === 0,
3151
- "data-testid": "filter-add",
3152
- children: [/* @__PURE__ */ L(W, { className: "h-3 w-3 mr-1" }), i("report.editor.addCondition", "Add condition")]
3153
- })
3154
- ]
3155
- });
3156
- }
3157
- //#endregion
3158
- //#region src/editorTypes.ts
3159
- var Pt = new Set([
3160
- "date",
3161
- "datetime",
3162
- "time"
3163
- ]), Ft = new Set([
3164
- "number",
3165
- "currency",
3166
- "percent",
3167
- "rating",
3168
- "integer"
3169
- ]);
3170
- //#endregion
3171
- //#region src/FieldPickerDialog.tsx
3172
- function It({ availableFields: e, selectedValues: n, onAdd: r, t: i, triggerLabel: a, title: o, description: s, testIdPrefix: c = "field-picker", singleSelect: l = !1, commitOnSelect: u = !1, disabled: d = !1, triggerClassName: f, trigger: m }) {
3173
- let [h, g] = t.useState(!1), [_, v] = t.useState(""), [b, O] = t.useState(/* @__PURE__ */ new Set()), k = t.useMemo(() => new Set(n), [n]);
3174
- t.useEffect(() => {
3175
- h && (v(""), O(/* @__PURE__ */ new Set()));
3176
- }, [h]);
3177
- let A = _.trim().toLowerCase(), j = e.filter((e) => !k.has(e.value)), M = A ? j.filter((e) => e.label.toLowerCase().includes(A) || e.value.toLowerCase().includes(A)) : j, ee = (e) => {
3178
- if (l && u) {
3179
- r([e]), g(!1);
3180
- return;
3181
- }
3182
- O((t) => {
3183
- let n = new Set(l ? [] : t);
3184
- return t.has(e) ? n.delete(e) : n.add(e), n;
3185
- });
3186
- }, N = () => {
3187
- if (b.size === 0) {
3188
- g(!1);
3189
- return;
3190
- }
3191
- r(j.map((e) => e.value).filter((e) => b.has(e))), g(!1);
3192
- }, P = () => {
3193
- g(!1);
3194
- }, F = e.length === 0, I = !F && j.length === 0, z = a ?? i("report.editor.addColumns", "Add fields"), B = o ?? i("report.editor.fieldPickerTitle", "Select fields"), V = s ?? i("report.editor.fieldPickerDescription", "Pick one or more fields to add. Use the search box to narrow the list.");
3195
- return /* @__PURE__ */ R(x, {
3196
- open: h,
3197
- onOpenChange: g,
3198
- children: [/* @__PURE__ */ L(D, {
3199
- asChild: !0,
3200
- children: m ?? /* @__PURE__ */ R(p, {
3201
- type: "button",
3202
- variant: "outline",
3203
- size: "sm",
3204
- className: f ?? "h-8 gap-1.5",
3205
- disabled: d || F || I,
3206
- "data-testid": `${c}-trigger`,
3207
- children: [/* @__PURE__ */ L(W, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ L("span", { children: z })]
3208
- })
3209
- }), /* @__PURE__ */ R(S, {
3210
- className: "sm:max-w-md max-w-[92vw] gap-3",
3211
- "data-testid": `${c}-dialog`,
3212
- children: [
3213
- /* @__PURE__ */ R(T, { children: [/* @__PURE__ */ L(E, { children: B }), /* @__PURE__ */ L(C, { children: V })] }),
3214
- /* @__PURE__ */ R("div", {
3215
- className: "relative",
3216
- children: [/* @__PURE__ */ L(pe, { className: "pointer-events-none absolute left-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground" }), /* @__PURE__ */ L("input", {
3217
- type: "text",
3218
- className: "h-9 w-full text-sm border rounded pl-7 pr-2 bg-background",
3219
- placeholder: i("report.editor.searchFields", "Search fields…"),
3220
- value: _,
3221
- onChange: (e) => v(e.target.value),
3222
- "data-testid": `${c}-search`,
3223
- autoFocus: !0
3224
- })]
3225
- }),
3226
- /* @__PURE__ */ R("div", {
3227
- className: "text-[11px] text-muted-foreground flex items-center justify-between",
3228
- children: [/* @__PURE__ */ R("span", { children: [
3229
- M.length,
3230
- "/",
3231
- j.length,
3232
- b.size > 0 ? ` · ${i("report.editor.fieldPickerSelected", "{n} selected").replace("{n}", String(b.size))}` : ""
3233
- ] }), b.size > 0 && /* @__PURE__ */ L("button", {
3234
- type: "button",
3235
- className: "text-[11px] underline-offset-2 hover:underline text-muted-foreground",
3236
- onClick: () => O(/* @__PURE__ */ new Set()),
3237
- "data-testid": `${c}-clear`,
3238
- children: i("report.editor.fieldPickerClear", "Clear selection")
3239
- })]
3240
- }),
3241
- /* @__PURE__ */ L("div", {
3242
- className: "max-h-72 overflow-auto border rounded bg-background/40 p-1 space-y-0.5",
3243
- "data-testid": `${c}-list`,
3244
- children: F ? /* @__PURE__ */ L("div", {
3245
- className: "text-xs text-muted-foreground px-2 py-3 text-center",
3246
- children: i("report.editor.noFields", "No fields available — pick a data source first.")
3247
- }) : I ? /* @__PURE__ */ L("div", {
3248
- className: "text-xs text-muted-foreground px-2 py-3 text-center",
3249
- children: i("report.editor.noFieldsAvailable", "All fields already added.")
3250
- }) : M.length === 0 ? /* @__PURE__ */ L("div", {
3251
- className: "text-xs text-muted-foreground px-2 py-3 text-center",
3252
- children: i("report.editor.noMatchingFields", "No fields match your search.")
3253
- }) : M.map((e) => {
3254
- let t = b.has(e.value);
3255
- return /* @__PURE__ */ R("label", {
3256
- className: "flex items-center gap-2 px-2 py-1.5 rounded hover:bg-muted/50 text-sm cursor-pointer",
3257
- "data-testid": `${c}-row-${e.value}`,
3258
- children: [
3259
- /* @__PURE__ */ L(y, {
3260
- checked: t,
3261
- onCheckedChange: () => ee(e.value),
3262
- "data-testid": `${c}-toggle-${e.value}`
3263
- }),
3264
- /* @__PURE__ */ L("span", {
3265
- className: "flex-1 truncate",
3266
- title: e.label,
3267
- children: e.label
3268
- }),
3269
- e.type && /* @__PURE__ */ L("span", {
3270
- className: "text-[10px] text-muted-foreground shrink-0",
3271
- children: e.type
3272
- })
3273
- ]
3274
- }, e.value);
3275
- })
3276
- }),
3277
- !(l && u) && /* @__PURE__ */ R(w, {
3278
- className: "gap-2 sm:gap-2",
3279
- children: [/* @__PURE__ */ L(p, {
3280
- type: "button",
3281
- variant: "ghost",
3282
- size: "sm",
3283
- onClick: P,
3284
- "data-testid": `${c}-cancel`,
3285
- children: i("common.cancel", "Cancel")
3286
- }), /* @__PURE__ */ L(p, {
3287
- type: "button",
3288
- size: "sm",
3289
- onClick: N,
3290
- disabled: b.size === 0,
3291
- "data-testid": `${c}-confirm`,
3292
- children: b.size > 0 ? i("report.editor.fieldPickerAddN", "Add {n}").replace("{n}", String(b.size)) : i("report.editor.fieldPickerAdd", "Add")
3293
- })]
3294
- })
3295
- ]
3296
- })]
3297
- });
3298
- }
3299
- //#endregion
3300
- //#region src/ColumnsEditor.tsx
3301
- function Lt(e) {
3302
- return [
3303
- {
3304
- value: "",
3305
- label: e("report.editor.noneOption")
3306
- },
3307
- {
3308
- value: "sum",
3309
- label: e("report.aggregate.sum")
3310
- },
3311
- {
3312
- value: "count",
3313
- label: e("report.aggregate.count")
3314
- },
3315
- {
3316
- value: "unique",
3317
- label: e("report.aggregate.countDistinct")
3318
- },
3319
- {
3320
- value: "avg",
3321
- label: e("report.aggregate.avg")
3322
- },
3323
- {
3324
- value: "min",
3325
- label: e("report.aggregate.min")
3326
- },
3327
- {
3328
- value: "max",
3329
- label: e("report.aggregate.max")
3330
- }
3331
- ];
3332
- }
3333
- function Rt(e) {
3334
- return [
3335
- {
3336
- value: "",
3337
- label: e("report.editor.formatAuto", "Auto")
3338
- },
3339
- {
3340
- value: "currency",
3341
- label: e("report.editor.formatCurrency", "Currency")
3342
- },
3343
- {
3344
- value: "percent",
3345
- label: e("report.editor.formatPercent", "Percent")
3346
- },
3347
- {
3348
- value: "integer",
3349
- label: e("report.editor.formatInteger", "Integer")
3350
- },
3351
- {
3352
- value: "date",
3353
- label: e("report.editor.formatDate", "Date")
3354
- },
3355
- {
3356
- value: "datetime",
3357
- label: e("report.editor.formatDatetime", "Date & time")
3358
- }
3359
- ];
3360
- }
3361
- function zt(e) {
3362
- return Array.isArray(e) ? e.map((e) => typeof e == "string" ? {
3363
- field: e,
3364
- label: e,
3365
- type: "string"
3366
- } : {
3367
- field: e.field || e.name || e.value,
3368
- label: e.label,
3369
- type: e.type || "string",
3370
- aggregate: e.aggregate ?? e.aggregation,
3371
- format: e.format
3372
- }) : [];
3373
- }
3374
- function Bt({ availableFields: e, value: t, onChange: n, t: r }) {
3375
- let i = zt(t), a = new Set(i.map((e) => e.field)), o = Lt(r), s = Rt(r), c = (t) => {
3376
- if (t.length === 0) return;
3377
- let r = t.filter((e) => !a.has(e)).map((t) => {
3378
- let n = e.find((e) => e.value === t);
3379
- return {
3380
- field: t,
3381
- label: n?.label,
3382
- type: n?.type || "string"
3383
- };
3384
- });
3385
- r.length !== 0 && n([...i, ...r]);
3386
- }, l = (e) => {
3387
- n(i.filter((t) => t.field !== e));
3388
- }, u = (e, t) => {
3389
- n(i.map((n) => n.field === e ? {
3390
- ...n,
3391
- ...t
3392
- } : n));
3393
- }, d = (e, t) => {
3394
- let r = [...i], a = e + t;
3395
- a < 0 || a >= r.length || ([r[e], r[a]] = [r[a], r[e]], n(r));
3396
- };
3397
- return e.length === 0 ? /* @__PURE__ */ L("div", {
3398
- className: "text-xs text-muted-foreground py-2",
3399
- "data-testid": "columns-editor-empty",
3400
- children: r("report.editor.noFields", "No fields available — pick a data source first.")
3401
- }) : /* @__PURE__ */ R("div", {
3402
- className: "space-y-2 py-1",
3403
- "data-testid": "columns-editor",
3404
- children: [i.length > 0 && /* @__PURE__ */ L("div", {
3405
- className: "space-y-1.5",
3406
- "data-testid": "columns-selected",
3407
- children: i.map((t, n) => {
3408
- let a = e.find((e) => e.value === t.field);
3409
- return /* @__PURE__ */ R("div", {
3410
- className: "grid grid-cols-[auto_1fr_auto] gap-1.5 p-1.5 border rounded bg-muted/30 text-xs",
3411
- "data-testid": `column-row-${t.field}`,
3412
- children: [
3413
- /* @__PURE__ */ R("div", {
3414
- className: "row-span-2 flex flex-col items-center justify-center gap-0.5",
3415
- children: [/* @__PURE__ */ L("button", {
3416
- type: "button",
3417
- className: "text-muted-foreground hover:text-foreground disabled:opacity-30",
3418
- disabled: n === 0,
3419
- onClick: () => d(n, -1),
3420
- "aria-label": "Move up",
3421
- "data-testid": `column-up-${t.field}`,
3422
- children: /* @__PURE__ */ L(te, { className: "h-3 w-3" })
3423
- }), /* @__PURE__ */ L("button", {
3424
- type: "button",
3425
- className: "text-muted-foreground hover:text-foreground disabled:opacity-30",
3426
- disabled: n === i.length - 1,
3427
- onClick: () => d(n, 1),
3428
- "aria-label": "Move down",
3429
- "data-testid": `column-down-${t.field}`,
3430
- children: /* @__PURE__ */ L(U, { className: "h-3 w-3" })
3431
- })]
3432
- }),
3433
- /* @__PURE__ */ L("input", {
3434
- className: "h-7 text-xs border rounded px-2 bg-background min-w-0 w-full",
3435
- value: t.label ?? "",
3436
- placeholder: a?.label ?? t.field,
3437
- onChange: (e) => u(t.field, { label: e.target.value || void 0 }),
3438
- "data-testid": `column-label-${t.field}`,
3439
- title: a?.label ?? t.field
3440
- }),
3441
- /* @__PURE__ */ L(p, {
3442
- type: "button",
3443
- size: "sm",
3444
- variant: "ghost",
3445
- className: "row-span-2 h-7 w-7 p-0 shrink-0 self-start",
3446
- onClick: () => l(t.field),
3447
- "data-testid": `column-remove-${t.field}`,
3448
- "aria-label": "Remove column",
3449
- children: /* @__PURE__ */ L(G, { className: "h-3.5 w-3.5" })
3450
- }),
3451
- /* @__PURE__ */ R("div", {
3452
- className: "grid grid-cols-2 gap-1.5",
3453
- children: [/* @__PURE__ */ R("label", {
3454
- className: "flex flex-col gap-0.5 min-w-0",
3455
- children: [/* @__PURE__ */ L("span", {
3456
- className: "text-[10px] text-muted-foreground uppercase tracking-wide",
3457
- children: r("report.editor.aggregateColumn", "Aggregate")
3458
- }), /* @__PURE__ */ L("select", {
3459
- className: "h-7 text-xs border rounded px-1 bg-background w-full min-w-0",
3460
- value: t.aggregate ?? "",
3461
- onChange: (e) => u(t.field, { aggregate: e.target.value === "" ? void 0 : e.target.value }),
3462
- "data-testid": `column-agg-${t.field}`,
3463
- children: o.map((e) => /* @__PURE__ */ L("option", {
3464
- value: e.value,
3465
- children: e.label
3466
- }, e.value))
3467
- })]
3468
- }), /* @__PURE__ */ R("label", {
3469
- className: "flex flex-col gap-0.5 min-w-0",
3470
- children: [/* @__PURE__ */ L("span", {
3471
- className: "text-[10px] text-muted-foreground uppercase tracking-wide",
3472
- children: r("report.editor.formatColumn", "Format")
3473
- }), /* @__PURE__ */ L("select", {
3474
- className: "h-7 text-xs border rounded px-1 bg-background w-full min-w-0",
3475
- value: t.format ?? "",
3476
- onChange: (e) => u(t.field, { format: e.target.value === "" ? void 0 : e.target.value }),
3477
- "data-testid": `column-fmt-${t.field}`,
3478
- children: s.map((e) => /* @__PURE__ */ L("option", {
3479
- value: e.value,
3480
- children: e.label
3481
- }, e.value))
3482
- })]
3483
- })]
3484
- })
3485
- ]
3486
- }, t.field);
3487
- })
3488
- }), /* @__PURE__ */ R("div", {
3489
- className: "flex items-center justify-between gap-2 pt-1",
3490
- children: [/* @__PURE__ */ L("div", {
3491
- className: "text-xs text-muted-foreground",
3492
- children: i.length > 0 ? r("report.editor.columnsCount", "{n} column(s) selected").replace("{n}", String(i.length)) : r("report.editor.columnsEmpty", "No columns selected yet.")
3493
- }), /* @__PURE__ */ L(It, {
3494
- availableFields: e,
3495
- selectedValues: i.map((e) => e.field),
3496
- onAdd: c,
3497
- t: r,
3498
- testIdPrefix: "columns-picker",
3499
- triggerLabel: r("report.editor.addColumns", "Add fields")
3500
- })]
3501
- })]
3502
- });
3503
- }
3504
- //#endregion
3505
- //#region src/GroupingsBuilder.tsx
3506
- function Vt({ availableFields: e, value: t, onChange: n, t: r, testIdPrefix: i = "grouping" }) {
3507
- let a = Array.isArray(t) ? t.map((e) => ({
3508
- field: e.field ?? "",
3509
- sortOrder: e.sortOrder ?? e.sort ?? "asc",
3510
- dateGranularity: e.dateGranularity
3511
- })) : [], o = [
3512
- {
3513
- value: "",
3514
- label: r("report.editor.dateGranularityNone")
3515
- },
3516
- {
3517
- value: "day",
3518
- label: r("report.editor.day")
3519
- },
3520
- {
3521
- value: "week",
3522
- label: r("report.editor.week")
3523
- },
3524
- {
3525
- value: "month",
3526
- label: r("report.editor.month")
3527
- },
3528
- {
3529
- value: "quarter",
3530
- label: r("report.editor.quarter")
3531
- },
3532
- {
3533
- value: "year",
3534
- label: r("report.editor.year")
3535
- }
3536
- ], s = a.map((e) => e.field).filter(Boolean), c = (e) => {
3537
- n(a.filter((t, n) => n !== e));
3538
- }, l = (e, t) => {
3539
- n(a.map((n, r) => r === e ? {
3540
- ...n,
3541
- ...t
3542
- } : n));
3543
- }, u = (e, t) => {
3544
- let r = [...a], i = e + t;
3545
- i < 0 || i >= r.length || ([r[e], r[i]] = [r[i], r[e]], n(r));
3546
- }, d = (e) => {
3547
- if (e.length === 0) return;
3548
- let t = e.map((e) => ({
3549
- field: e,
3550
- sortOrder: "asc"
3551
- }));
3552
- n([...a, ...t]);
3553
- }, f = (t, n) => {
3554
- let r = n[0];
3555
- if (!r) return;
3556
- let i = e.find((e) => e.value === r);
3557
- l(t, {
3558
- field: r,
3559
- dateGranularity: i && Pt.has(i.type ?? "") ? a[t]?.dateGranularity : void 0
3560
- });
3561
- };
3562
- return /* @__PURE__ */ R("div", {
3563
- className: "space-y-1.5 py-1",
3564
- "data-testid": `${i}s-builder`,
3565
- children: [a.map((t, n) => {
3566
- let d = e.find((e) => e.value === t.field), m = d && Pt.has(d.type ?? ""), h = d?.label ?? t.field ?? r("report.editor.fieldPickerEmpty", "(pick field)");
3567
- return /* @__PURE__ */ R("div", {
3568
- className: "flex items-center gap-1.5 p-1.5 border rounded bg-muted/20 text-xs",
3569
- "data-testid": `${i}-row-${n}`,
835
+ }, e.id)), M && /* @__PURE__ */ b("tr", {
836
+ className: "border-t bg-muted/30 font-medium",
837
+ "data-testid": "matrix-total-row",
3570
838
  children: [
3571
- /* @__PURE__ */ R("div", {
3572
- className: "flex flex-col gap-0.5 shrink-0",
3573
- children: [/* @__PURE__ */ L("button", {
3574
- type: "button",
3575
- className: "text-muted-foreground hover:text-foreground disabled:opacity-30",
3576
- disabled: n === 0,
3577
- onClick: () => u(n, -1),
3578
- "aria-label": "Move up",
3579
- "data-testid": `${i}-up-${n}`,
3580
- children: /* @__PURE__ */ L(te, { className: "h-3 w-3" })
3581
- }), /* @__PURE__ */ L("button", {
3582
- type: "button",
3583
- className: "text-muted-foreground hover:text-foreground disabled:opacity-30",
3584
- disabled: n === a.length - 1,
3585
- onClick: () => u(n, 1),
3586
- "aria-label": "Move down",
3587
- "data-testid": `${i}-down-${n}`,
3588
- children: /* @__PURE__ */ L(U, { className: "h-3 w-3" })
3589
- })]
839
+ o.length > 0 && /* @__PURE__ */ y("td", {
840
+ colSpan: o.length,
841
+ className: "px-2 py-1 whitespace-nowrap",
842
+ children: v
3590
843
  }),
3591
- /* @__PURE__ */ L(It, {
3592
- availableFields: e,
3593
- selectedValues: s.filter((e) => e !== t.field),
3594
- onAdd: (e) => f(n, e),
3595
- t: r,
3596
- singleSelect: !0,
3597
- commitOnSelect: !0,
3598
- testIdPrefix: `${i}-field-picker-${n}`,
3599
- title: r("report.editor.fieldPickerChangeTitle", "Change field"),
3600
- trigger: /* @__PURE__ */ R("button", {
3601
- type: "button",
3602
- className: "h-7 flex-1 min-w-0 text-left text-xs border rounded px-2 bg-background hover:bg-muted/40 inline-flex items-center justify-between gap-1.5",
3603
- "data-testid": `${i}-field-${n}`,
3604
- title: h,
3605
- children: [/* @__PURE__ */ L("span", {
3606
- className: "truncate",
3607
- children: h
3608
- }), /* @__PURE__ */ L(re, { className: "h-3 w-3 text-muted-foreground shrink-0" })]
3609
- })
3610
- }),
3611
- /* @__PURE__ */ R("select", {
3612
- className: "h-7 text-xs border rounded px-1.5 bg-background w-20 shrink-0",
3613
- value: t.sortOrder ?? "asc",
3614
- onChange: (e) => l(n, { sortOrder: e.target.value }),
3615
- "data-testid": `${i}-sort-${n}`,
3616
- children: [/* @__PURE__ */ L("option", {
3617
- value: "asc",
3618
- children: r("report.editor.sortAsc")
3619
- }), /* @__PURE__ */ L("option", {
3620
- value: "desc",
3621
- children: r("report.editor.sortDesc")
3622
- })]
3623
- }),
3624
- m && /* @__PURE__ */ L("select", {
3625
- className: "h-7 text-xs border rounded px-1.5 bg-background w-24 shrink-0",
3626
- value: t.dateGranularity ?? "",
3627
- onChange: (e) => l(n, { dateGranularity: e.target.value || void 0 }),
3628
- "data-testid": `${i}-granularity-${n}`,
3629
- children: o.map((e) => /* @__PURE__ */ L("option", {
3630
- value: e.value,
3631
- children: e.label
3632
- }, e.value))
3633
- }),
3634
- /* @__PURE__ */ L(p, {
3635
- type: "button",
3636
- size: "sm",
3637
- variant: "ghost",
3638
- className: "h-7 w-7 p-0 shrink-0",
3639
- onClick: () => c(n),
3640
- "aria-label": "Remove grouping",
3641
- "data-testid": `${i}-remove-${n}`,
3642
- children: /* @__PURE__ */ L(G, { className: "h-3.5 w-3.5" })
3643
- })
844
+ w.map((e) => /* @__PURE__ */ y("td", {
845
+ className: "px-2 py-1 text-right tabular-nums whitespace-nowrap",
846
+ children: i(D.get(e.col.id)?.[e.measure], g(e.measure)?.format, g(e.measure)?.currency)
847
+ }, `${e.col.id}-${e.measure}`)),
848
+ j && c.map((e) => /* @__PURE__ */ y("td", {
849
+ className: "px-2 py-1 text-right tabular-nums whitespace-nowrap",
850
+ "data-testid": "matrix-grand-total",
851
+ children: i(O?.[e], g(e)?.format, g(e)?.currency)
852
+ }, `grand-${e}`))
3644
853
  ]
3645
- }, n);
3646
- }), /* @__PURE__ */ L(It, {
3647
- availableFields: e,
3648
- selectedValues: s,
3649
- onAdd: d,
3650
- t: r,
3651
- singleSelect: !0,
3652
- commitOnSelect: !0,
3653
- testIdPrefix: `${i}-add-picker`,
3654
- triggerLabel: r("report.editor.addGrouping"),
3655
- title: r("report.editor.fieldPickerAddGroupingTitle", "Add grouping"),
3656
- triggerClassName: "h-8 w-full justify-center gap-1.5"
3657
- })]
854
+ })] })]
855
+ })
3658
856
  });
3659
857
  }
3660
- //#endregion
3661
- //#region src/ChartConfig.tsx
3662
- function Ht({ availableFields: e, columns: t, value: n, onChange: r, t: i }) {
3663
- let a = n || {}, o = a.type ?? a.chartType ?? "", s = a.xAxis ?? a.xAxisField ?? "", c = a.yAxis ?? a.yAxisFields?.[0] ?? "", l = (e) => {
3664
- let t = {
3665
- ...a,
3666
- ...e
3667
- };
3668
- if ("type" in e && delete t.chartType, "xAxis" in e && delete t.xAxisField, "yAxis" in e && delete t.yAxisFields, !e.type && e.type === "") return r(void 0);
3669
- r(t);
3670
- }, u = () => r(void 0), d = [
3671
- {
3672
- value: "",
3673
- label: i("report.editor.chartNone")
3674
- },
3675
- {
3676
- value: "bar",
3677
- label: i("report.editor.chartBar")
3678
- },
3679
- {
3680
- value: "line",
3681
- label: i("report.editor.chartLine")
3682
- },
3683
- {
3684
- value: "area",
3685
- label: i("report.editor.chartArea")
3686
- },
3687
- {
3688
- value: "pie",
3689
- label: i("report.editor.chartPie")
3690
- },
3691
- {
3692
- value: "donut",
3693
- label: i("report.editor.chartDonut")
858
+ var de = ({ report: e, dataSource: t, runtimeFilter: n, onDrill: r, className: i }) => {
859
+ let a = W(e.runtimeFilter ?? e.filter, n), o = e.drilldown === !1 ? void 0 : r;
860
+ if (e.type === "joined" && Array.isArray(e.blocks)) return /* @__PURE__ */ y("div", {
861
+ className: i,
862
+ "data-testid": "dataset-joined-report",
863
+ "data-report-name": e.name,
864
+ style: {
865
+ display: "flex",
866
+ flexDirection: "column",
867
+ gap: 24
3694
868
  },
3695
- {
3696
- value: "funnel",
3697
- label: i("report.editor.chartFunnel")
3698
- }
3699
- ], f = t.filter((e) => e.aggregate).map((e) => e.field), p = e.filter((e) => Ft.has(e.type ?? "")).map((e) => e.value), m = new Set([...f, ...p]), h = e.filter((e) => m.has(e.value));
3700
- return /* @__PURE__ */ R("div", {
3701
- className: "space-y-2 py-1",
3702
- "data-testid": "chart-config",
3703
- children: [/* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("label", {
3704
- className: "text-[10px] text-muted-foreground",
3705
- children: i("report.editor.chartType")
3706
- }), /* @__PURE__ */ L("select", {
3707
- className: "w-full h-7 text-xs border rounded px-2 bg-background",
3708
- value: o,
3709
- onChange: (e) => {
3710
- let t = e.target.value;
3711
- t ? l({ type: t }) : u();
3712
- },
3713
- "data-testid": "chart-type-select",
3714
- children: d.map((e) => /* @__PURE__ */ L("option", {
3715
- value: e.value,
3716
- children: e.label
3717
- }, e.value))
3718
- })] }), o && /* @__PURE__ */ R(I, { children: [
3719
- /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("label", {
3720
- className: "text-[10px] text-muted-foreground",
3721
- children: i("report.editor.chartTitle")
3722
- }), /* @__PURE__ */ L("input", {
3723
- className: "w-full h-7 text-xs border rounded px-2 bg-background",
3724
- value: a.title ?? "",
3725
- placeholder: i("report.editor.chartTitlePlaceholder"),
3726
- onChange: (e) => l({ title: e.target.value || void 0 }),
3727
- "data-testid": "chart-title"
3728
- })] }),
3729
- /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("label", {
3730
- className: "text-[10px] text-muted-foreground",
3731
- children: i("report.editor.chartXAxis")
3732
- }), /* @__PURE__ */ R("select", {
3733
- className: "w-full h-7 text-xs border rounded px-2 bg-background",
3734
- value: s,
3735
- onChange: (e) => l({ xAxis: e.target.value || void 0 }),
3736
- "data-testid": "chart-x-field",
3737
- children: [/* @__PURE__ */ L("option", {
3738
- value: "",
3739
- children: "—"
3740
- }), e.map((e) => /* @__PURE__ */ L("option", {
3741
- value: e.value,
3742
- children: e.label
3743
- }, e.value))]
3744
- })] }),
3745
- /* @__PURE__ */ R("div", { children: [/* @__PURE__ */ L("label", {
3746
- className: "text-[10px] text-muted-foreground",
3747
- children: i("report.editor.chartYAxis")
3748
- }), /* @__PURE__ */ R("select", {
3749
- className: "w-full h-7 text-xs border rounded px-2 bg-background",
3750
- value: c,
3751
- onChange: (e) => l({ yAxis: e.target.value || void 0 }),
3752
- "data-testid": "chart-y-field",
3753
- children: [/* @__PURE__ */ L("option", {
3754
- value: "",
3755
- children: "—"
3756
- }), (h.length > 0 ? h : e).map((e) => /* @__PURE__ */ L("option", {
3757
- value: e.value,
3758
- children: e.label
3759
- }, e.value))]
3760
- })] }),
3761
- /* @__PURE__ */ R("label", {
3762
- className: "flex items-center gap-2 text-[10px]",
3763
- children: [/* @__PURE__ */ L(y, {
3764
- checked: a.showLegend !== !1,
3765
- onCheckedChange: (e) => l({ showLegend: e === !0 }),
3766
- "data-testid": "chart-show-legend"
3767
- }), /* @__PURE__ */ L("span", { children: i("report.editor.chartShowLegend") })]
3768
- }),
3769
- /* @__PURE__ */ R("label", {
3770
- className: "flex items-center gap-2 text-[10px]",
3771
- children: [/* @__PURE__ */ L(y, {
3772
- checked: !!a.showDataLabels,
3773
- onCheckedChange: (e) => l({ showDataLabels: e === !0 }),
3774
- "data-testid": "chart-show-data-labels"
3775
- }), /* @__PURE__ */ L("span", { children: i("report.editor.chartShowDataLabels") })]
3776
- })
3777
- ] })]
869
+ children: e.blocks.map((e, n) => {
870
+ let r = W(a, e.runtimeFilter ?? e.filter), i = q(e.columns), s = e.type === "matrix" && i.length > 0 ? /* @__PURE__ */ y(ue, {
871
+ dataset: String(e.dataset ?? ""),
872
+ rows: q(e.rows),
873
+ columnsAcross: i,
874
+ values: q(e.values),
875
+ runtimeFilter: r,
876
+ dataSource: t,
877
+ onDrill: o
878
+ }) : /* @__PURE__ */ y(ae, {
879
+ dataset: String(e.dataset ?? ""),
880
+ rows: q(e.rows),
881
+ values: q(e.values),
882
+ runtimeFilter: r,
883
+ dataSource: t,
884
+ onDrill: o
885
+ });
886
+ return /* @__PURE__ */ b("section", {
887
+ "data-testid": "dataset-report-block",
888
+ "data-block-id": e.name ?? `block-${n}`,
889
+ className: "flex flex-col gap-2 rounded-lg border bg-card p-4",
890
+ children: [/* @__PURE__ */ b("header", {
891
+ className: "flex flex-col gap-0.5",
892
+ children: [/* @__PURE__ */ y("h3", {
893
+ className: "text-sm font-semibold",
894
+ children: K(e.label, e.name ?? `Block ${n + 1}`)
895
+ }), e.description ? /* @__PURE__ */ y("p", {
896
+ className: "text-xs text-muted-foreground",
897
+ children: K(e.description, "")
898
+ }) : null]
899
+ }), s]
900
+ }, e.name ?? `block-${n}`);
901
+ })
3778
902
  });
3779
- }
3780
- //#endregion
3781
- //#region src/ReportConfigPanel.tsx
3782
- function Ut(e, t, n) {
3783
- let r = (e) => e.type === "summary", i = (e) => e.type === "matrix", a = (e) => e.type === "summary" || e.type === "matrix", o = [
3784
- {
3785
- key: "basic",
3786
- title: t("report.editor.basic"),
3787
- fields: [
3788
- {
3789
- key: "label",
3790
- label: t("report.editor.title"),
3791
- type: "input",
3792
- placeholder: t("report.editor.titlePlaceholder")
3793
- },
3794
- {
3795
- key: "description",
3796
- label: t("report.editor.description"),
3797
- type: "textarea",
3798
- placeholder: t("report.editor.descriptionPlaceholder")
3799
- },
3800
- {
3801
- key: "type",
3802
- label: t("report.editor.type"),
3803
- type: "select",
3804
- defaultValue: "tabular",
3805
- options: [
3806
- {
3807
- value: "tabular",
3808
- label: t("report.editor.typeTabular")
3809
- },
3810
- {
3811
- value: "summary",
3812
- label: t("report.editor.typeSummary")
3813
- },
3814
- {
3815
- value: "matrix",
3816
- label: t("report.editor.typeMatrix")
3817
- },
3818
- {
3819
- value: "joined",
3820
- label: t("report.editor.typeJoined")
3821
- }
3822
- ],
3823
- helpText: t("report.editor.typeHelp")
3824
- }
3825
- ]
3826
- },
3827
- {
3828
- key: "data",
3829
- title: t("report.editor.data"),
3830
- collapsible: !0,
3831
- fields: [{
3832
- key: "objectName",
3833
- label: t("report.editor.objectName"),
3834
- type: "input",
3835
- placeholder: t("report.editor.objectNamePlaceholder"),
3836
- helpText: t("report.editor.objectNameHelp")
3837
- }, {
3838
- key: "limit",
3839
- label: t("report.editor.limit"),
3840
- type: "input",
3841
- placeholder: t("report.editor.limitPlaceholder")
3842
- }]
3843
- },
3844
- {
3845
- key: "rows",
3846
- title: t("report.editor.rows"),
3847
- collapsible: !0,
3848
- hint: t("report.editor.rowsHint"),
3849
- visibleWhen: (e) => r(e) || i(e),
3850
- fields: [{
3851
- key: "groupingsDown",
3852
- label: t("report.editor.grouping"),
3853
- type: "custom",
3854
- render: (n, r) => /* @__PURE__ */ L(Vt, {
3855
- availableFields: e,
3856
- value: n,
3857
- onChange: r,
3858
- t,
3859
- testIdPrefix: "rows-grouping"
3860
- })
3861
- }]
3862
- },
3863
- {
3864
- key: "columnsAxis",
3865
- title: t("report.editor.columnsAxis"),
3866
- collapsible: !0,
3867
- hint: t("report.editor.columnsAxisHint"),
3868
- visibleWhen: (e) => i(e),
3869
- fields: [{
3870
- key: "groupingsAcross",
3871
- label: t("report.editor.grouping"),
3872
- type: "custom",
3873
- render: (n, r) => /* @__PURE__ */ L(Vt, {
3874
- availableFields: e,
3875
- value: n,
3876
- onChange: r,
3877
- t,
3878
- testIdPrefix: "cols-grouping"
3879
- })
3880
- }]
3881
- },
3882
- {
3883
- key: "tabular-columns",
3884
- title: t("report.editor.columns"),
3885
- collapsible: !0,
3886
- hint: t("report.editor.columnsHint"),
3887
- visibleWhen: (e) => e.type !== "joined" && !r(e) && !i(e),
3888
- fields: [{
3889
- key: "columns",
3890
- label: t("report.editor.columns"),
3891
- type: "custom",
3892
- render: (n, r) => /* @__PURE__ */ L(Bt, {
3893
- availableFields: e,
3894
- value: n,
3895
- onChange: r,
3896
- t
3897
- })
3898
- }]
3899
- },
3900
- {
3901
- key: "values",
3902
- title: t("report.editor.values"),
3903
- collapsible: !0,
3904
- hint: t("report.editor.valuesHint"),
3905
- visibleWhen: (e) => r(e) || i(e),
3906
- fields: [{
3907
- key: "columns",
3908
- label: t("report.editor.values"),
3909
- type: "custom",
3910
- render: (n, r) => /* @__PURE__ */ L(Bt, {
3911
- availableFields: e,
3912
- value: n,
3913
- onChange: r,
3914
- t
3915
- })
3916
- }]
3917
- },
3918
- {
3919
- key: "filters",
3920
- title: t("report.editor.filters"),
3921
- collapsible: !0,
3922
- hint: t("report.editor.filtersHint"),
3923
- visibleWhen: (e) => e.type !== "joined",
3924
- fields: [{
3925
- key: "filter",
3926
- label: t("report.editor.filters"),
3927
- type: "custom",
3928
- render: (n, r) => /* @__PURE__ */ L(Nt, {
3929
- availableFields: e,
3930
- value: n,
3931
- onChange: r,
3932
- t
3933
- })
3934
- }]
3935
- },
3936
- {
3937
- key: "blocks",
3938
- title: t("report.editor.blocks"),
3939
- collapsible: !0,
3940
- hint: t("report.editor.blocksHint"),
3941
- visibleWhen: (e) => e.type === "joined",
3942
- fields: [{
3943
- key: "blocks",
3944
- label: t("report.editor.blocks"),
3945
- type: "custom",
3946
- render: (r, i, a) => /* @__PURE__ */ L(Ct, {
3947
- value: r,
3948
- onChange: i,
3949
- availableFields: e,
3950
- getFieldsForObject: n,
3951
- containerObjectName: a?.objectName,
3952
- t
3953
- })
3954
- }]
3955
- },
3956
- {
3957
- key: "chart",
3958
- title: t("report.editor.chart"),
3959
- collapsible: !0,
3960
- defaultCollapsed: !0,
3961
- hint: t("report.editor.chartHint"),
3962
- visibleWhen: (e) => a(e),
3963
- fields: [{
3964
- key: "chart",
3965
- label: t("report.editor.chart"),
3966
- type: "custom",
3967
- render: (n, r, i) => /* @__PURE__ */ L(Ht, {
3968
- availableFields: e,
3969
- columns: zt(i.columns),
3970
- value: n,
3971
- onChange: r,
3972
- t
3973
- })
3974
- }]
3975
- }
3976
- ];
3977
- return {
3978
- breadcrumb: [t("report.editor.breadcrumb", "Configuration")],
3979
- sections: o
3980
- };
3981
- }
3982
- function Wt(e, t) {
3983
- let n = [], r = e.type ?? "tabular", i = Array.isArray(e.groupingsDown) ? e.groupingsDown.length : 0, a = Array.isArray(e.groupingsAcross) ? e.groupingsAcross.length : 0, o = Array.isArray(e.columns) ? e.columns.length : 0;
3984
- if (e.objectName || n.push({
3985
- level: o > 0 ? "error" : "warning",
3986
- message: t("report.editor.validationNeedsObject")
3987
- }), r === "matrix" && (i === 0 || a === 0) && n.push({
3988
- level: "error",
3989
- message: t("report.editor.validationMatrixNeedsRowsCols")
3990
- }), r === "summary" && i === 0 && n.push({
3991
- level: "error",
3992
- message: t("report.editor.validationSummaryNeedsRows")
3993
- }), r === "joined") for (let r of wt(e.blocks, t)) n.push({
3994
- level: "error",
3995
- message: r
903
+ let s = q(e.columns);
904
+ if (e.type === "matrix" && s.length > 0) return /* @__PURE__ */ y("div", {
905
+ className: i,
906
+ "data-testid": "dataset-report",
907
+ "data-report-name": e.name,
908
+ children: /* @__PURE__ */ y(ue, {
909
+ dataset: String(e.dataset ?? ""),
910
+ rows: q(e.rows),
911
+ columnsAcross: s,
912
+ values: q(e.values),
913
+ runtimeFilter: a,
914
+ dataSource: t,
915
+ onDrill: o
916
+ })
3996
917
  });
3997
- return n;
3998
- }
3999
- function Gt({ problems: e }) {
4000
- return e.length === 0 ? null : /* @__PURE__ */ L("div", {
4001
- className: "space-y-1 p-2 border-b",
4002
- "data-testid": "report-validation-banner",
4003
- children: e.map((e, t) => /* @__PURE__ */ R("div", {
4004
- className: "flex items-start gap-2 text-[11px] rounded px-2 py-1 " + (e.level === "error" ? "bg-red-50 border border-red-200 text-red-900" : "bg-amber-50 border border-amber-200 text-amber-900"),
4005
- children: [/* @__PURE__ */ L(H, { className: "h-3.5 w-3.5 mt-0.5 shrink-0" }), /* @__PURE__ */ L("span", { children: e.message })]
4006
- }, t))
918
+ let c = e.chart && typeof e.chart == "object" && e.chart.type ? e.chart : null;
919
+ return /* @__PURE__ */ b("div", {
920
+ className: `${i ?? ""} flex flex-col gap-3`,
921
+ "data-testid": "dataset-report",
922
+ "data-report-name": e.name,
923
+ children: [c ? /* @__PURE__ */ y(ce, {
924
+ dataset: String(e.dataset ?? ""),
925
+ chart: c,
926
+ runtimeFilter: a,
927
+ dataSource: t
928
+ }) : null, /* @__PURE__ */ y(ae, {
929
+ dataset: String(e.dataset ?? ""),
930
+ rows: q(e.rows),
931
+ values: q(e.values),
932
+ runtimeFilter: a,
933
+ dataSource: t,
934
+ onDrill: o
935
+ })]
4007
936
  });
4008
- }
4009
- function Kt({ open: e, onClose: n, config: r, onSave: i, onFieldChange: a, availableFields: o, getFieldsForObject: s }) {
4010
- let { t: c } = z(), l = t.useCallback((e, t, n) => t === void 0 ? c(e, n) : c(e, {
4011
- defaultValue: t,
4012
- ...n || {}
4013
- }), [c]), u = o ?? [], d = t.useMemo(() => Ut(u, l, s), [
4014
- u,
4015
- l,
4016
- s
4017
- ]), { draft: f, isDirty: p, updateField: m, discard: h } = F(t.useMemo(() => r ?? {}, [r])), g = t.useCallback((e, t) => {
4018
- m(e, t), a?.(e, t, {
4019
- ...f,
4020
- [e]: t
4021
- });
4022
- }, [
4023
- m,
4024
- a,
4025
- f
4026
- ]), _ = t.useCallback(() => {
4027
- i(f), n();
4028
- }, [
4029
- f,
4030
- i,
4031
- n
4032
- ]), v = t.useMemo(() => Wt(f, l), [f, l]);
4033
- return e ? /* @__PURE__ */ L(b, {
4034
- open: e,
4035
- onClose: n,
4036
- schema: d,
4037
- draft: f,
4038
- isDirty: p,
4039
- onFieldChange: g,
4040
- onSave: _,
4041
- onDiscard: h,
4042
- headerExtra: /* @__PURE__ */ L(Gt, { problems: v }),
4043
- style: { "--config-panel-width": "440px" }
4044
- }) : null;
4045
- }
937
+ }, $ = (e) => {
938
+ let { dataSource: t, rows: n, runtimeFilter: r, onDrill: i, className: o } = e, l = a.useContext(u), d = t ?? l?.dataSource, f = e.schema;
939
+ return f && typeof f == "object" && f.type === "spec-report" && f.report && typeof f.report == "object" && (f = f.report), G(f) ? /* @__PURE__ */ y(de, {
940
+ report: f,
941
+ dataSource: d,
942
+ runtimeFilter: r,
943
+ onDrill: i,
944
+ className: o
945
+ }) : s(f) ? /* @__PURE__ */ y("div", {
946
+ className: o,
947
+ "data-testid": "report-presentation-bridge",
948
+ children: /* @__PURE__ */ y(U, { schema: {
949
+ type: "report-viewer",
950
+ report: c(f),
951
+ data: n ?? [],
952
+ showToolbar: !1
953
+ } })
954
+ }) : /* @__PURE__ */ y(j, { schema: f });
955
+ };
4046
956
  //#endregion
4047
957
  //#region src/LiveReportExporter.ts
4048
- async function qt(e, t) {
958
+ async function fe(e, t) {
4049
959
  let { dataSource: n, resource: r, queryParams: i, format: a, exportConfig: o } = t, s = a || e.defaultExportFormat || "pdf";
4050
960
  try {
4051
961
  let t = (await n.find(r, i)).data || [];
4052
- return at(s, e, t, {
962
+ return I(s, e, t, {
4053
963
  format: s,
4054
964
  ...e.exportConfigs?.[s],
4055
965
  ...o
@@ -4067,17 +977,17 @@ async function qt(e, t) {
4067
977
  };
4068
978
  }
4069
979
  }
4070
- function Jt(e, t, n = {}) {
4071
- let { columns: r, filename: i, includeAggregationRow: a = !1 } = n, o = r || (e.fields || []).map(Xt), s = o.map((e) => e.header), c = t.map((e, t) => o.map((n) => {
980
+ function pe(e, t, n = {}) {
981
+ let { columns: r, filename: i, includeAggregationRow: a = !1 } = n, o = r || (e.fields || []).map(he), s = o.map((e) => e.header), c = t.map((e, t) => o.map((n) => {
4072
982
  if (n.formula) return n.formula.replace(/\{ROW\}/g, String(t + 2));
4073
983
  let r = e[n.name];
4074
- return Zt(r, n.numberFormat);
984
+ return ge(r, n.numberFormat);
4075
985
  }));
4076
986
  if (a && t.length > 0) {
4077
987
  let n = o.map((n, r) => {
4078
988
  let i = (e.fields || []).find((e) => e.name === n.name);
4079
989
  if (i?.aggregation) {
4080
- let e = $t(r), n = t.length + 1;
990
+ let e = ve(r), n = t.length + 1;
4081
991
  switch (i.aggregation) {
4082
992
  case "sum": return `=SUM(${e}2:${e}${n})`;
4083
993
  case "avg": return `=AVERAGE(${e}2:${e}${n})`;
@@ -4091,15 +1001,15 @@ function Jt(e, t, n = {}) {
4091
1001
  });
4092
1002
  c.push(n);
4093
1003
  }
4094
- tn("" + [s.join(" "), ...c.map((e) => e.join(" "))].join("\n"), i || `${e.title || "report"}.tsv`, "text/tab-separated-values");
1004
+ be("" + [s.join(" "), ...c.map((e) => e.join(" "))].join("\n"), i || `${e.title || "report"}.tsv`, "text/tab-separated-values");
4095
1005
  }
4096
- function Yt(e, t, n, r) {
1006
+ function me(e, t, n, r) {
4097
1007
  return async () => {
4098
1008
  let i = e.schedule;
4099
1009
  if (!i?.enabled) return [];
4100
1010
  let a = i.formats || [e.defaultExportFormat || "pdf"], o = [];
4101
1011
  for (let r of a) {
4102
- let i = await qt(e, {
1012
+ let i = await fe(e, {
4103
1013
  dataSource: t,
4104
1014
  resource: n,
4105
1015
  format: r
@@ -4109,16 +1019,16 @@ function Yt(e, t, n, r) {
4109
1019
  return r(e, i), o;
4110
1020
  };
4111
1021
  }
4112
- function Xt(e) {
1022
+ function he(e) {
4113
1023
  return {
4114
1024
  name: e.name,
4115
1025
  header: e.label || e.name
4116
1026
  };
4117
1027
  }
4118
- function Zt(e, t) {
4119
- return e == null ? "" : typeof e == "number" && t ? e.toLocaleString("en-US", Qt(t)) : en(String(e));
1028
+ function ge(e, t) {
1029
+ return e == null ? "" : typeof e == "number" && t ? e.toLocaleString("en-US", _e(t)) : ye(String(e));
4120
1030
  }
4121
- function Qt(e) {
1031
+ function _e(e) {
4122
1032
  if (e.includes("%")) return {
4123
1033
  style: "percent",
4124
1034
  minimumFractionDigits: 0
@@ -4129,23 +1039,23 @@ function Qt(e) {
4129
1039
  maximumFractionDigits: Math.max(0, t - 1)
4130
1040
  };
4131
1041
  }
4132
- function $t(e) {
1042
+ function ve(e) {
4133
1043
  let t = "", n = e;
4134
1044
  for (; n >= 0;) t = String.fromCharCode(n % 26 + 65) + t, n = Math.floor(n / 26) - 1;
4135
1045
  return t;
4136
1046
  }
4137
- function en(e) {
1047
+ function ye(e) {
4138
1048
  if (e.length > 0) {
4139
1049
  let t = e.charAt(0);
4140
1050
  if (t === "=" || t === "+" || t === "-" || t === "@" || t === "|") return `'${e}`;
4141
1051
  }
4142
1052
  return e;
4143
1053
  }
4144
- function tn(e, t, n) {
1054
+ function be(e, t, n) {
4145
1055
  let r = new Blob([e], { type: `${n};charset=utf-8` }), i = URL.createObjectURL(r), a = document.createElement("a");
4146
1056
  a.href = i, a.download = t, document.body.appendChild(a), a.click(), document.body.removeChild(a), URL.revokeObjectURL(i);
4147
1057
  }
4148
- e.register("report", $e, {
1058
+ e.register("report", $, {
4149
1059
  namespace: "report",
4150
1060
  label: "Report",
4151
1061
  category: "Report",
@@ -4166,20 +1076,20 @@ e.register("report", $e, {
4166
1076
  label: "Chart Configuration"
4167
1077
  }
4168
1078
  ]
4169
- }), e.register("spec-report", $e, {
1079
+ }), e.register("spec-report", $, {
4170
1080
  namespace: "report",
4171
1081
  label: "Spec Report",
4172
1082
  category: "Report",
4173
1083
  inputs: [{
4174
- name: "objectName",
1084
+ name: "dataset",
4175
1085
  type: "string",
4176
- label: "Object Name"
1086
+ label: "Dataset"
4177
1087
  }, {
4178
1088
  name: "type",
4179
1089
  type: "string",
4180
1090
  label: "Report Type"
4181
1091
  }]
4182
- }), e.register("report-viewer", mt, {
1092
+ }), e.register("report-viewer", U, {
4183
1093
  namespace: "report",
4184
1094
  label: "Report Viewer",
4185
1095
  category: "Report",
@@ -4192,15 +1102,6 @@ e.register("report", $e, {
4192
1102
  type: "boolean",
4193
1103
  label: "Show Toolbar"
4194
1104
  }]
4195
- }), e.register("report-builder", gt, {
4196
- namespace: "report",
4197
- label: "Report Builder",
4198
- category: "Report",
4199
- inputs: [{
4200
- name: "report",
4201
- type: "code",
4202
- label: "Initial Report"
4203
- }]
4204
1105
  });
4205
1106
  //#endregion
4206
- export { Ct as JoinedBlocksEditor, Ze as JoinedReportRenderer, _e as LegacyReportRenderer, qe as MatrixRenderer, gt as ReportBuilder, Kt as ReportConfigPanel, $e as ReportRenderer, mt as ReportViewer, ht as ScheduleConfig, He as SpecReportGrid, J as aggregateRows, ve as bucketDate, De as buildAggregateQuery, Pe as buildDrillAction, Ee as collectFields, K as columnKey, Ie as createDrillHandler, Yt as createScheduleTrigger, et as exportAsCSV, it as exportAsExcel, nt as exportAsHTML, tt as exportAsJSON, rt as exportAsPDF, Jt as exportExcelWithFormulas, at as exportReport, qt as exportWithLiveData, ut as formatValue, ye as groupAndAggregate, q as groupingValue, Fe as isDrillAction, X as mergeFilters, be as pivotRows, Le as registerDrillHandler, ke as useReportData, wt as validateJoinedBlocks };
1107
+ export { de as DatasetReportRenderer, j as LegacyReportRenderer, $ as ReportRenderer, U as ReportViewer, me as createScheduleTrigger, M as exportAsCSV, F as exportAsExcel, N as exportAsHTML, ee as exportAsJSON, P as exportAsPDF, pe as exportExcelWithFormulas, I as exportReport, fe as exportWithLiveData, H as formatValue, G as isDatasetReport, W as mergeFilters };