@object-ui/plugin-report 6.2.3 → 7.0.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 +89 -0
  2. package/dist/DatasetReportRenderer.d.ts +93 -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 +532 -3684
  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 = L(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
+ B([...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
+ B(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 = z(n?.orientation), a = R(n?.pageSize);
85
+ B(`<!DOCTYPE html>
1200
86
  <html>
1201
87
  <head>
1202
88
  <meta charset="utf-8">
1203
- <title>${Q(e.title || "Report")}</title>
89
+ <title>${I(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>${I(e.title || "Report")}</h1>
104
+ ${e.description ? `<p class="description">${I(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>${I(e.label || e.name)}</th>`).join("")}</tr></thead>
108
+ <tbody>${t.map((e) => `<tr>${r.map((t) => `<td>${I(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 = z(n?.orientation), a = R(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>${I(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>${I(e.title || "Report")}</h1>
143
+ ${e.description ? `<p class="description">${I(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>${I(e.label || e.name)}</th>`).join("")}</tr></thead>
147
+ <tbody>${t.map((e) => `<tr>${r.map((t) => `<td>${I(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 te(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 = L(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
+ B("" + [...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 F(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
+ te(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 I(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 L(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 R(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 z(e) {
1314
200
  return e === "landscape" ? "landscape" : "portrait";
1315
201
  }
1316
- function lt(e, t, n) {
202
+ function B(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 V(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" || ne(e)) return re(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 ne(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 re(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 ie(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 H = ({ 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
+ F(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 V(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 V(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: V(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 = ie(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,448 @@ 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 U(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 W(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 G(e, t) {
537
+ return e ? typeof e == "string" ? e : typeof e == "object" && typeof e.default == "string" ? e.default : t : t;
538
+ }
539
+ function K(e) {
540
+ return Array.isArray(e) ? e.filter((e) => typeof e == "string" && !!e) : [];
541
+ }
542
+ function q(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
1865
- });
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
- })]
2580
- });
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
- }
2598
- function bt(e) {
2599
- return typeof e.description == "string" ? e.description : e.description && typeof e.description == "object" ? e.description.default ?? "" : "";
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;
2600
593
  }
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}`,
594
+ function J({ 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",
2609
597
  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
- })
598
+ "This report binds the “",
599
+ e,
600
+ "” dataset — choose at least one measure (values) to render."
2774
601
  ]
2775
602
  });
2776
603
  }
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
- ]
604
+ function Y({ 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…"]
2832
615
  });
2833
616
  }
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;
617
+ function X() {
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
+ });
2848
622
  }
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);
623
+ var Z = "cursor-pointer hover:bg-accent/40";
624
+ function ae({ dataset: e, rows: a, values: o, runtimeFilter: s, dataSource: c, onDrill: l }) {
625
+ let u = q(e, a, o, s, c), { fieldLabel: d } = k();
626
+ if (o.length === 0) return /* @__PURE__ */ y(J, { dataset: e });
627
+ if (u.status === "loading" || u.status === "idle") return /* @__PURE__ */ y(Y, { status: u.status });
628
+ if (u.status === "error") return /* @__PURE__ */ y(Y, {
629
+ status: "error",
630
+ error: u.error
631
+ });
632
+ if (u.rows.length === 0) return /* @__PURE__ */ y(X, {});
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
643
+ });
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 ? ` ${Z}` : ""}`,
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
+ })
665
+ });
2881
666
  }
2882
- function $() {
2883
- return Math.random().toString(36).slice(2, 10);
667
+ function Q(e, t) {
668
+ return e.map((e) => String(t[e] ?? "∅")).join("");
2884
669
  }
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;
670
+ function oe(e, t) {
671
+ return e.map((e) => r(t[e])).join(" / ");
2922
672
  }
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;
673
+ function se({ dataset: e, rows: o, columnsAcross: s, values: c, runtimeFilter: l, dataSource: u, onDrill: d }) {
674
+ let f = q(e, [...o, ...s], c, l, u, [
675
+ o,
676
+ s,
677
+ []
678
+ ]), p = A(), { fieldLabel: m } = k(), h = a.useMemo(() => {
679
+ if (f.status !== "ok") return null;
680
+ let e = [], t = [], n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Map();
681
+ return f.rows.forEach((a, c) => {
682
+ let l = Q(o, a), u = Q(s, a);
683
+ if (!n.has(l)) {
684
+ n.add(l);
685
+ let t = {};
686
+ for (let e of o) t[e] = a[e];
687
+ e.push({
688
+ id: l,
689
+ label: oe(o, a),
690
+ key: t
691
+ });
2948
692
  }
2949
- for (let [t, n] of Object.entries(e)) {
2950
- let e = kt(t, n);
2951
- e ? i.push(...e) : a = !0;
693
+ if (!r.has(u)) {
694
+ r.add(u);
695
+ let e = {};
696
+ for (let t of s) e[t] = a[t];
697
+ t.push({
698
+ id: u,
699
+ label: oe(s, a),
700
+ key: e
701
+ });
2952
702
  }
2953
- }
2954
- return {
2955
- group: {
2956
- id: "root",
2957
- logic: n,
2958
- conditions: i
2959
- },
2960
- complex: a
703
+ i.set(`${l} ${u}`, {
704
+ row: a,
705
+ index: c
706
+ });
707
+ }), {
708
+ rowHeaders: e,
709
+ colHeaders: t,
710
+ cells: i
2961
711
  };
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") })]
712
+ }, [
713
+ f,
714
+ o,
715
+ s
716
+ ]);
717
+ if (c.length === 0) return /* @__PURE__ */ y(J, { dataset: e });
718
+ if (f.status === "loading" || f.status === "idle") return /* @__PURE__ */ y(Y, { status: f.status });
719
+ if (f.status === "error") return /* @__PURE__ */ y(Y, {
720
+ status: "error",
721
+ error: f.error
3007
722
  });
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 ? {
723
+ if (!h || h.rowHeaders.length === 0) return /* @__PURE__ */ y(X, {});
724
+ 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) => {
725
+ let a = f.object && f.dimensionFields && S.length > 0 ? t(f.drillRawRows?.[i], S, f.dimensionFields, l) : void 0;
726
+ d({
727
+ dataset: e,
728
+ groupKey: {
3027
729
  ...n,
3028
- ...t
3029
- } : n)
730
+ ...r
731
+ },
732
+ runtimeFilter: l,
733
+ object: f.object,
734
+ objectFilter: a
3030
735
  });
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",
736
+ }, w = h.colHeaders.flatMap((e) => c.map((t) => ({
737
+ col: e,
738
+ measure: t,
739
+ header: c.length === 1 ? e.label : `${e.label} · ${_(t)}`
740
+ }))), T = (e) => f.totals?.find((t) => Array.isArray(t.dimensions) && t.dimensions.join(",") === e.join(","))?.rows, E = /* @__PURE__ */ new Map();
741
+ for (let e of T(o) ?? []) E.set(Q(o, e), e);
742
+ let D = /* @__PURE__ */ new Map();
743
+ for (let e of T(s) ?? []) D.set(Q(s, e), e);
744
+ let O = T([])?.[0], j = E.size > 0, M = D.size > 0;
745
+ return /* @__PURE__ */ y("div", {
746
+ className: "overflow-auto max-h-[70vh] rounded-md border",
747
+ "data-testid": "dataset-matrix",
748
+ children: /* @__PURE__ */ b("table", {
749
+ className: "w-full text-xs",
750
+ children: [/* @__PURE__ */ y("thead", {
751
+ className: "bg-muted/40",
752
+ children: /* @__PURE__ */ b("tr", { children: [
753
+ o.map((e) => /* @__PURE__ */ y("th", {
754
+ className: "px-2 py-1.5 text-left font-medium whitespace-nowrap",
755
+ children: _(e)
756
+ }, e)),
757
+ w.map((e) => /* @__PURE__ */ y("th", {
758
+ className: "px-2 py-1.5 text-right font-medium whitespace-nowrap",
759
+ children: e.header
760
+ }, `${e.col.id}-${e.measure}`)),
761
+ j && c.map((e) => /* @__PURE__ */ y("th", {
762
+ className: "px-2 py-1.5 text-right font-medium whitespace-nowrap",
763
+ "data-testid": "matrix-total-col-header",
764
+ children: c.length === 1 ? v : `${v} · ${_(e)}`
765
+ }, `total-${e}`))
766
+ ] })
767
+ }), /* @__PURE__ */ b("tbody", { children: [h.rowHeaders.map((e) => /* @__PURE__ */ b("tr", {
768
+ className: "border-t",
3102
769
  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))
770
+ o.map((t) => /* @__PURE__ */ y("td", {
771
+ className: "px-2 py-1 whitespace-nowrap font-medium",
772
+ children: r(e.key[t])
773
+ }, t)),
774
+ w.map((t) => {
775
+ let n = h.cells.get(`${e.id} ${t.col.id}`), r = n?.row[t.measure], a = x && n != null;
776
+ return /* @__PURE__ */ y("td", {
777
+ className: `px-2 py-1 text-right tabular-nums whitespace-nowrap${a ? ` ${Z}` : ""}`,
778
+ "data-testid": a ? "dataset-drill-cell" : void 0,
779
+ onClick: a ? () => C(e.key, t.col.key, n.index) : void 0,
780
+ children: i(r, g(t.measure)?.format, g(t.measure)?.currency)
781
+ }, `${t.col.id}-${t.measure}`);
3122
782
  }),
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}`
3132
- }),
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
- })
783
+ j && c.map((t) => /* @__PURE__ */ y("td", {
784
+ className: "px-2 py-1 text-right tabular-nums whitespace-nowrap font-medium",
785
+ "data-testid": "matrix-row-total",
786
+ children: i(E.get(e.id)?.[t], g(t)?.format, g(t)?.currency)
787
+ }, `total-${t}`))
3142
788
  ]
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}`,
789
+ }, e.id)), M && /* @__PURE__ */ b("tr", {
790
+ className: "border-t bg-muted/30 font-medium",
791
+ "data-testid": "matrix-total-row",
3570
792
  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
- })]
3590
- }),
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
- })]
793
+ o.length > 0 && /* @__PURE__ */ y("td", {
794
+ colSpan: o.length,
795
+ className: "px-2 py-1 whitespace-nowrap",
796
+ children: v
3623
797
  }),
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
- })
798
+ w.map((e) => /* @__PURE__ */ y("td", {
799
+ className: "px-2 py-1 text-right tabular-nums whitespace-nowrap",
800
+ children: i(D.get(e.col.id)?.[e.measure], g(e.measure)?.format, g(e.measure)?.currency)
801
+ }, `${e.col.id}-${e.measure}`)),
802
+ j && c.map((e) => /* @__PURE__ */ y("td", {
803
+ className: "px-2 py-1 text-right tabular-nums whitespace-nowrap",
804
+ "data-testid": "matrix-grand-total",
805
+ children: i(O?.[e], g(e)?.format, g(e)?.currency)
806
+ }, `grand-${e}`))
3644
807
  ]
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
- })]
3658
- });
3659
- }
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")
3694
- },
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
- ] })]
808
+ })] })]
809
+ })
3778
810
  });
3779
811
  }
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
- }]
812
+ var ce = ({ report: e, dataSource: t, runtimeFilter: n, onDrill: r, className: i }) => {
813
+ let a = U(e.runtimeFilter ?? e.filter, n), o = e.drilldown === !1 ? void 0 : r;
814
+ if (e.type === "joined" && Array.isArray(e.blocks)) return /* @__PURE__ */ y("div", {
815
+ className: i,
816
+ "data-testid": "dataset-joined-report",
817
+ "data-report-name": e.name,
818
+ style: {
819
+ display: "flex",
820
+ flexDirection: "column",
821
+ gap: 24
3955
822
  },
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
823
+ children: e.blocks.map((e, n) => {
824
+ let r = U(a, e.runtimeFilter ?? e.filter), i = K(e.columns), s = e.type === "matrix" && i.length > 0 ? /* @__PURE__ */ y(se, {
825
+ dataset: String(e.dataset ?? ""),
826
+ rows: K(e.rows),
827
+ columnsAcross: i,
828
+ values: K(e.values),
829
+ runtimeFilter: r,
830
+ dataSource: t,
831
+ onDrill: o
832
+ }) : /* @__PURE__ */ y(ae, {
833
+ dataset: String(e.dataset ?? ""),
834
+ rows: K(e.rows),
835
+ values: K(e.values),
836
+ runtimeFilter: r,
837
+ dataSource: t,
838
+ onDrill: o
839
+ });
840
+ return /* @__PURE__ */ b("section", {
841
+ "data-testid": "dataset-report-block",
842
+ "data-block-id": e.name ?? `block-${n}`,
843
+ className: "flex flex-col gap-2 rounded-lg border bg-card p-4",
844
+ children: [/* @__PURE__ */ b("header", {
845
+ className: "flex flex-col gap-0.5",
846
+ children: [/* @__PURE__ */ y("h3", {
847
+ className: "text-sm font-semibold",
848
+ children: G(e.label, e.name ?? `Block ${n + 1}`)
849
+ }), e.description ? /* @__PURE__ */ y("p", {
850
+ className: "text-xs text-muted-foreground",
851
+ children: G(e.description, "")
852
+ }) : null]
853
+ }), s]
854
+ }, e.name ?? `block-${n}`);
855
+ })
3996
856
  });
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))
857
+ let s = K(e.columns);
858
+ return e.type === "matrix" && s.length > 0 ? /* @__PURE__ */ y("div", {
859
+ className: i,
860
+ "data-testid": "dataset-report",
861
+ "data-report-name": e.name,
862
+ children: /* @__PURE__ */ y(se, {
863
+ dataset: String(e.dataset ?? ""),
864
+ rows: K(e.rows),
865
+ columnsAcross: s,
866
+ values: K(e.values),
867
+ runtimeFilter: a,
868
+ dataSource: t,
869
+ onDrill: o
870
+ })
871
+ }) : /* @__PURE__ */ y("div", {
872
+ className: i,
873
+ "data-testid": "dataset-report",
874
+ "data-report-name": e.name,
875
+ children: /* @__PURE__ */ y(ae, {
876
+ dataset: String(e.dataset ?? ""),
877
+ rows: K(e.rows),
878
+ values: K(e.values),
879
+ runtimeFilter: a,
880
+ dataSource: t,
881
+ onDrill: o
882
+ })
4007
883
  });
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
- }
884
+ }, $ = (e) => {
885
+ let { dataSource: t, rows: n, runtimeFilter: r, onDrill: i, className: o } = e, l = a.useContext(u), d = t ?? l?.dataSource, f = e.schema;
886
+ return f && typeof f == "object" && f.type === "spec-report" && f.report && typeof f.report == "object" && (f = f.report), W(f) ? /* @__PURE__ */ y(ce, {
887
+ report: f,
888
+ dataSource: d,
889
+ runtimeFilter: r,
890
+ onDrill: i,
891
+ className: o
892
+ }) : s(f) ? /* @__PURE__ */ y("div", {
893
+ className: o,
894
+ "data-testid": "report-presentation-bridge",
895
+ children: /* @__PURE__ */ y(H, { schema: {
896
+ type: "report-viewer",
897
+ report: c(f),
898
+ data: n ?? [],
899
+ showToolbar: !1
900
+ } })
901
+ }) : /* @__PURE__ */ y(j, { schema: f });
902
+ };
4046
903
  //#endregion
4047
904
  //#region src/LiveReportExporter.ts
4048
- async function qt(e, t) {
905
+ async function le(e, t) {
4049
906
  let { dataSource: n, resource: r, queryParams: i, format: a, exportConfig: o } = t, s = a || e.defaultExportFormat || "pdf";
4050
907
  try {
4051
908
  let t = (await n.find(r, i)).data || [];
4052
- return at(s, e, t, {
909
+ return F(s, e, t, {
4053
910
  format: s,
4054
911
  ...e.exportConfigs?.[s],
4055
912
  ...o
@@ -4067,17 +924,17 @@ async function qt(e, t) {
4067
924
  };
4068
925
  }
4069
926
  }
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) => {
927
+ function ue(e, t, n = {}) {
928
+ let { columns: r, filename: i, includeAggregationRow: a = !1 } = n, o = r || (e.fields || []).map(fe), s = o.map((e) => e.header), c = t.map((e, t) => o.map((n) => {
4072
929
  if (n.formula) return n.formula.replace(/\{ROW\}/g, String(t + 2));
4073
930
  let r = e[n.name];
4074
- return Zt(r, n.numberFormat);
931
+ return pe(r, n.numberFormat);
4075
932
  }));
4076
933
  if (a && t.length > 0) {
4077
934
  let n = o.map((n, r) => {
4078
935
  let i = (e.fields || []).find((e) => e.name === n.name);
4079
936
  if (i?.aggregation) {
4080
- let e = $t(r), n = t.length + 1;
937
+ let e = he(r), n = t.length + 1;
4081
938
  switch (i.aggregation) {
4082
939
  case "sum": return `=SUM(${e}2:${e}${n})`;
4083
940
  case "avg": return `=AVERAGE(${e}2:${e}${n})`;
@@ -4091,15 +948,15 @@ function Jt(e, t, n = {}) {
4091
948
  });
4092
949
  c.push(n);
4093
950
  }
4094
- tn("" + [s.join(" "), ...c.map((e) => e.join(" "))].join("\n"), i || `${e.title || "report"}.tsv`, "text/tab-separated-values");
951
+ _e("" + [s.join(" "), ...c.map((e) => e.join(" "))].join("\n"), i || `${e.title || "report"}.tsv`, "text/tab-separated-values");
4095
952
  }
4096
- function Yt(e, t, n, r) {
953
+ function de(e, t, n, r) {
4097
954
  return async () => {
4098
955
  let i = e.schedule;
4099
956
  if (!i?.enabled) return [];
4100
957
  let a = i.formats || [e.defaultExportFormat || "pdf"], o = [];
4101
958
  for (let r of a) {
4102
- let i = await qt(e, {
959
+ let i = await le(e, {
4103
960
  dataSource: t,
4104
961
  resource: n,
4105
962
  format: r
@@ -4109,16 +966,16 @@ function Yt(e, t, n, r) {
4109
966
  return r(e, i), o;
4110
967
  };
4111
968
  }
4112
- function Xt(e) {
969
+ function fe(e) {
4113
970
  return {
4114
971
  name: e.name,
4115
972
  header: e.label || e.name
4116
973
  };
4117
974
  }
4118
- function Zt(e, t) {
4119
- return e == null ? "" : typeof e == "number" && t ? e.toLocaleString("en-US", Qt(t)) : en(String(e));
975
+ function pe(e, t) {
976
+ return e == null ? "" : typeof e == "number" && t ? e.toLocaleString("en-US", me(t)) : ge(String(e));
4120
977
  }
4121
- function Qt(e) {
978
+ function me(e) {
4122
979
  if (e.includes("%")) return {
4123
980
  style: "percent",
4124
981
  minimumFractionDigits: 0
@@ -4129,23 +986,23 @@ function Qt(e) {
4129
986
  maximumFractionDigits: Math.max(0, t - 1)
4130
987
  };
4131
988
  }
4132
- function $t(e) {
989
+ function he(e) {
4133
990
  let t = "", n = e;
4134
991
  for (; n >= 0;) t = String.fromCharCode(n % 26 + 65) + t, n = Math.floor(n / 26) - 1;
4135
992
  return t;
4136
993
  }
4137
- function en(e) {
994
+ function ge(e) {
4138
995
  if (e.length > 0) {
4139
996
  let t = e.charAt(0);
4140
997
  if (t === "=" || t === "+" || t === "-" || t === "@" || t === "|") return `'${e}`;
4141
998
  }
4142
999
  return e;
4143
1000
  }
4144
- function tn(e, t, n) {
1001
+ function _e(e, t, n) {
4145
1002
  let r = new Blob([e], { type: `${n};charset=utf-8` }), i = URL.createObjectURL(r), a = document.createElement("a");
4146
1003
  a.href = i, a.download = t, document.body.appendChild(a), a.click(), document.body.removeChild(a), URL.revokeObjectURL(i);
4147
1004
  }
4148
- e.register("report", $e, {
1005
+ e.register("report", $, {
4149
1006
  namespace: "report",
4150
1007
  label: "Report",
4151
1008
  category: "Report",
@@ -4166,20 +1023,20 @@ e.register("report", $e, {
4166
1023
  label: "Chart Configuration"
4167
1024
  }
4168
1025
  ]
4169
- }), e.register("spec-report", $e, {
1026
+ }), e.register("spec-report", $, {
4170
1027
  namespace: "report",
4171
1028
  label: "Spec Report",
4172
1029
  category: "Report",
4173
1030
  inputs: [{
4174
- name: "objectName",
1031
+ name: "dataset",
4175
1032
  type: "string",
4176
- label: "Object Name"
1033
+ label: "Dataset"
4177
1034
  }, {
4178
1035
  name: "type",
4179
1036
  type: "string",
4180
1037
  label: "Report Type"
4181
1038
  }]
4182
- }), e.register("report-viewer", mt, {
1039
+ }), e.register("report-viewer", H, {
4183
1040
  namespace: "report",
4184
1041
  label: "Report Viewer",
4185
1042
  category: "Report",
@@ -4192,15 +1049,6 @@ e.register("report", $e, {
4192
1049
  type: "boolean",
4193
1050
  label: "Show Toolbar"
4194
1051
  }]
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
1052
  });
4205
1053
  //#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 };
1054
+ export { ce as DatasetReportRenderer, j as LegacyReportRenderer, $ as ReportRenderer, H as ReportViewer, de as createScheduleTrigger, M as exportAsCSV, te as exportAsExcel, N as exportAsHTML, ee as exportAsJSON, P as exportAsPDF, ue as exportExcelWithFormulas, F as exportReport, le as exportWithLiveData, V as formatValue, W as isDatasetReport, U as mergeFilters };