@feedmepos/mf-report 5.28.5 → 5.29.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 (35) hide show
  1. package/dist/{App-Bc8Mp5vR.js → App-CuBsRwfx.js} +4 -4
  2. package/dist/{DateRangeSelect-cbSEHMzW.js → DateRangeSelect-CzjlwjuC.js} +1 -1
  3. package/dist/{Default.vue_vue_type_script_setup_true_lang-BpJFA_ET.js → Default.vue_vue_type_script_setup_true_lang-Di9_F5Yk.js} +1 -1
  4. package/dist/{DynamicWidget.vue_vue_type_script_setup_true_lang-Dx-cxJP6.js → DynamicWidget.vue_vue_type_script_setup_true_lang-C73R6Fb9.js} +5 -5
  5. package/dist/{GlobalFilterSelect.vue_vue_type_script_setup_true_lang-Cxrti7_L.js → GlobalFilterSelect.vue_vue_type_script_setup_true_lang-tLRFdLNs.js} +9 -10
  6. package/dist/{InsightView-Bo0Fb5QG.js → InsightView-BcnmLQ8c.js} +5 -5
  7. package/dist/{Integration-B4tC2MlL.js → Integration-D4VFT1M8.js} +3 -3
  8. package/dist/{Integrations-RB8iuvdJ.js → Integrations-v8oF1TL7.js} +2 -2
  9. package/dist/{Layout-DBCPtUH7.js → Layout-Ds8RSWmi.js} +1 -1
  10. package/dist/{LocationSelect.vue_vue_type_script_setup_true_lang-w2H9qOgJ.js → LocationSelect.vue_vue_type_script_setup_true_lang-Dk6u8nUH.js} +1638 -1634
  11. package/dist/{MenuTab.vue_vue_type_script_setup_true_lang-BLVGUSWf.js → MenuTab.vue_vue_type_script_setup_true_lang-BWt7pqFb.js} +5 -5
  12. package/dist/{NavigationTab.vue_vue_type_script_setup_true_lang-N31ee-oZ.js → NavigationTab.vue_vue_type_script_setup_true_lang-CU00GINo.js} +3853 -3823
  13. package/dist/OverviewView-1v80g6KX.js +81 -0
  14. package/dist/{Report-Di6GyP1r.js → Report-DcFB4gM6.js} +3 -3
  15. package/dist/ReportCanvasView-BQO6Mywc.js +5190 -0
  16. package/dist/{ReportEditor-BfNmiEVn.js → ReportEditor-Bgcisf1s.js} +7 -7
  17. package/dist/{ReportView-JWJ-6FCu.js → ReportView-Q_juD8Kr.js} +6 -6
  18. package/dist/{ReportViewRoute-BMjjJqN2.js → ReportViewRoute-DwStGqyz.js} +2 -2
  19. package/dist/{Setting-D13NIemB.js → Setting-C9rlM23O.js} +3 -3
  20. package/dist/{Template-D16bqzrx.js → Template-BZd0NB5w.js} +3 -3
  21. package/dist/{TileEditor-1Sn9ZSb2.js → TileEditor-B2F9r3RS.js} +6 -6
  22. package/dist/{TilePageStack.vue_vue_type_script_setup_true_lang-BOXsV7-r.js → TilePageStack.vue_vue_type_script_setup_true_lang-BmbrJAph.js} +2 -2
  23. package/dist/{TransitionFade-DwJkmMTb.js → TransitionFade-Dkeo9qr0.js} +5 -5
  24. package/dist/{app-CVBllEjW.js → app-CoQ_GRKo.js} +1819 -1326
  25. package/dist/app.js +1 -1
  26. package/dist/assets/{formatChartData.worker-DZp5dSDQ.js → formatChartData.worker-D7sGqQhX.js} +34 -34
  27. package/dist/assets/{processTableData.worker-Kyuhw4lS.js → processTableData.worker-CltxwQxU.js} +34 -34
  28. package/dist/{report-Cn4Ik1zm.js → report-Dau_so1j.js} +1 -1
  29. package/dist/report-canvas-libs/components-1.js +1042 -0
  30. package/dist/report-canvas-libs/fm-ui-1.js +599 -180
  31. package/dist/style.css +1 -1
  32. package/dist/{useRestaurantPermission-C8bLPfk8.js → useRestaurantPermission-CPoHZTxx.js} +1 -1
  33. package/package.json +2 -1
  34. package/dist/OverviewView-WKe6Zxe1.js +0 -61
  35. package/dist/ReportCanvasView-Dg2ItHBO.js +0 -1336
@@ -1,1336 +0,0 @@
1
- import { ref as q, shallowRef as en, onMounted as W, onBeforeUnmount as tn, defineComponent as rn, watch as H, computed as on, createElementBlock as T, openBlock as L, createElementVNode as P, createCommentVNode as U, withDirectives as an, createVNode as V, unref as j, isRef as F, withCtx as sn, toDisplayString as J, vShow as dn } from "vue";
2
- import { useRoute as cn } from "vue-router";
3
- import { u as ln } from "./_plugin-vue_export-helper-C6QDExPN.js";
4
- import { storeToRefs as N } from "pinia";
5
- import { _ as un } from "./LocationSelect.vue_vue_type_script_setup_true_lang-w2H9qOgJ.js";
6
- import { D as fn } from "./DateRangeSelect-cbSEHMzW.js";
7
- import { F as B, r as D, u as G, a as X, a0 as mn } from "./app-CVBllEjW.js";
8
- function $(r) {
9
- const { businessId: c } = N(G());
10
- if (!c.value) throw new Error("Business Id is not defined");
11
- return `/${c.value}/report-canvas/${r}`;
12
- }
13
- const pn = (r) => {
14
- const c = {
15
- fetchType: B.Get,
16
- url: $(r)
17
- };
18
- return D.fetch(c);
19
- }, gn = (r, c, l, s) => {
20
- const p = {
21
- fetchType: B.Post,
22
- url: `${$(r)}/query/${c}`,
23
- data: { params: l, timezone: s }
24
- };
25
- return D.fetch(p);
26
- }, hn = (r, c, l) => {
27
- const s = {
28
- fetchType: B.Post,
29
- url: `${$(r)}/section/${c}/ack`,
30
- data: l
31
- };
32
- return D.fetch(s);
33
- }, vn = ["@from", "@to", "@locationIds", "@timezone"], bn = ["@from", "@to", "@locationIds"], yn = 1, xn = 1500;
34
- function wn(r) {
35
- if (!(!(r instanceof mn) || r.status !== 429))
36
- return Math.min(Math.max(r.retryAfterMs ?? xn, 500), 5e3);
37
- }
38
- const kn = {
39
- MY: "MYR",
40
- SG: "SGD",
41
- TH: "THB",
42
- ID: "IDR",
43
- PH: "PHP",
44
- VN: "VND",
45
- BN: "BND",
46
- KH: "KHR",
47
- MM: "MMK",
48
- AE: "AED",
49
- MO: "MOP",
50
- MV: "MVR",
51
- AU: "AUD",
52
- JP: "JPY",
53
- TW: "TWD",
54
- HK: "HKD"
55
- };
56
- function K(r) {
57
- return r == null ? !0 : Array.isArray(r) ? r.length === 0 : r === "";
58
- }
59
- function In(r) {
60
- const c = X(), { dateRange: l, selectedLocationIds: s, locations: p, timezone: g } = N(c), { country: I } = N(G()), o = q({}), i = en({}), w = q([]), S = [], y = {}, h = {};
61
- function C(n) {
62
- S.push(n);
63
- }
64
- function O(n) {
65
- i.value = { ...i.value, [n.queryId]: n }, S.forEach((t) => t(n));
66
- }
67
- function _(n) {
68
- const t = {};
69
- for (const m of n.params)
70
- t[m.name] = m.default ?? null;
71
- t["@from"] = l.value.startDate ?? null, t["@to"] = l.value.endDate ?? null, t["@timezone"] = g.value, t["@locationIds"] = s.value.length ? [...s.value] : p.value.map((m) => m.id), o.value = t;
72
- }
73
- function a() {
74
- return {
75
- locations: p.value.map((n) => ({
76
- id: n.id,
77
- name: n.name || n.id,
78
- code: n.code
79
- })),
80
- timezone: g.value,
81
- locale: navigator.language || "en-US",
82
- currency: kn[(I.value || "").toUpperCase()] ?? ""
83
- };
84
- }
85
- function v(n) {
86
- return JSON.stringify(n.dependsOn.map((t) => o.value[t] ?? null));
87
- }
88
- function x(n) {
89
- return !!n.lazy && n.dependsOn.some((t) => K(o.value[t] ?? null));
90
- }
91
- function A() {
92
- return !bn.some((n) => n in o.value && K(o.value[n] ?? null));
93
- }
94
- async function E(n) {
95
- var m;
96
- const t = (y[n.id] ?? 0) + 1;
97
- y[n.id] = t, O({
98
- queryId: n.id,
99
- runId: t,
100
- status: "loading",
101
- rows: ((m = i.value[n.id]) == null ? void 0 : m.rows) ?? [],
102
- truncated: !1
103
- });
104
- for (let k = 0; ; k++)
105
- try {
106
- const b = await gn(
107
- r,
108
- n.id,
109
- o.value,
110
- g.value
111
- );
112
- if (y[n.id] !== t) return;
113
- O({
114
- queryId: n.id,
115
- runId: t,
116
- status: "ok",
117
- rows: b.rows ?? [],
118
- truncated: !!b.truncated
119
- });
120
- return;
121
- } catch (b) {
122
- if (y[n.id] !== t) return;
123
- const f = wn(b);
124
- if (f !== void 0 && k < yn) {
125
- if (await new Promise((d) => setTimeout(d, f)), y[n.id] !== t) return;
126
- continue;
127
- }
128
- O({
129
- queryId: n.id,
130
- runId: t,
131
- status: "error",
132
- rows: [],
133
- truncated: !1,
134
- error: b instanceof Error ? b.message : String(b)
135
- });
136
- return;
137
- }
138
- }
139
- function R(n = {}) {
140
- var m, k, b;
141
- const t = !A();
142
- for (const f of w.value) {
143
- if (x(f)) {
144
- delete h[f.id], ((m = i.value[f.id]) == null ? void 0 : m.status) !== "idle" && O({
145
- queryId: f.id,
146
- runId: y[f.id] ?? 0,
147
- status: "idle",
148
- rows: [],
149
- truncated: !1
150
- });
151
- continue;
152
- }
153
- if (t) {
154
- ((k = i.value[f.id]) == null ? void 0 : k.status) !== "loading" && O({
155
- queryId: f.id,
156
- runId: y[f.id] ?? 0,
157
- status: "loading",
158
- rows: ((b = i.value[f.id]) == null ? void 0 : b.rows) ?? [],
159
- truncated: !1
160
- });
161
- continue;
162
- }
163
- const d = v(f);
164
- !n.force && h[f.id] === d || (h[f.id] = d, E(f));
165
- }
166
- }
167
- function M(n) {
168
- const t = { ...o.value };
169
- let m = !1;
170
- for (const [k, b] of Object.entries(n))
171
- k in t && JSON.stringify(t[k] ?? null) !== JSON.stringify(b ?? null) && (t[k] = b, m = !0);
172
- return m ? (o.value = t, R(), !0) : !1;
173
- }
174
- function e(n) {
175
- w.value = n.queries, i.value = {};
176
- for (const t of Object.keys(y)) delete y[t];
177
- for (const t of Object.keys(h)) delete h[t];
178
- _(n), R();
179
- }
180
- function u(n, t = []) {
181
- w.value = n.queries;
182
- const m = JSON.stringify(o.value), k = {};
183
- for (const d of n.params)
184
- k[d.name] = d.name in o.value ? o.value[d.name] : d.default ?? null;
185
- o.value = k;
186
- const b = new Set(n.queries.map((d) => d.id));
187
- for (const d of Object.keys(y)) b.has(d) || delete y[d];
188
- for (const d of Object.keys(h)) b.has(d) || delete h[d];
189
- const f = Object.keys(i.value).filter((d) => !b.has(d));
190
- if (f.length) {
191
- const d = { ...i.value };
192
- for (const nn of f) delete d[nn];
193
- i.value = d;
194
- }
195
- for (const d of t) delete h[d];
196
- return R(), JSON.stringify(o.value) !== m;
197
- }
198
- return {
199
- params: o,
200
- results: i,
201
- queries: w,
202
- env: a,
203
- load: e,
204
- applyCanvas: u,
205
- run: R,
206
- setParams: M,
207
- onResult: C,
208
- RESERVED: vn
209
- };
210
- }
211
- function En(r) {
212
- const c = r.replace(/^\//, "");
213
- try {
214
- const l = new URL(import.meta.url);
215
- if (typeof location < "u" && location.hostname !== l.hostname)
216
- return new URL(c, l).href;
217
- } catch {
218
- }
219
- return `${"/".replace(/\/$/, "")}/${c}`;
220
- }
221
- const Z = {
222
- "chart.js@4": "chart.js-4.js",
223
- "fm-ui@1": "fm-ui-1.js"
224
- }, z = /* @__PURE__ */ new Map();
225
- function Sn(r) {
226
- return En(`report-canvas-libs/${Z[r]}`);
227
- }
228
- async function Y(r) {
229
- const c = [...new Set(r)].filter((s) => Z[s]), l = {};
230
- return await Promise.all(
231
- c.map(async (s) => {
232
- if (!z.has(s)) {
233
- const g = await fetch(Sn(s));
234
- if (!g.ok) return;
235
- z.set(s, await g.text());
236
- }
237
- const p = z.get(s);
238
- p && (l[s] = p);
239
- })
240
- ), l;
241
- }
242
- const On = `<meta charset="utf-8" />
243
- <meta name="viewport" content="width=device-width, initial-scale=1" />
244
- <!--
245
- Runtime shell for AI-written report sections. Loaded into ONE iframe per report with
246
- sandbox="allow-scripts" and no allow-same-origin, so this document runs on an opaque
247
- origin and cannot reach the host. Section code needs inline+eval by design; the sandbox
248
- attribute is the boundary, and this CSP's job is to keep the frame off the network.
249
- -->
250
- <meta
251
- http-equiv="Content-Security-Policy"
252
- content="default-src 'none'; script-src 'unsafe-inline' 'unsafe-eval'; style-src 'unsafe-inline'; img-src data: blob:; font-src data:; connect-src 'none'; form-action 'none'; base-uri 'none'"
253
- />
254
- <title>Report</title>
255
- <style>
256
- /* Design tokens, from the B2B_POS working file's Report page. A report reads these;
257
- a merchant asking for a different look is one redefinition here, not a rewrite. */
258
- :root {
259
- color-scheme: light;
260
- --fm-fg: #1c1c1e;
261
- --fm-body: #2e2e2e;
262
- --fm-muted: #6b6c70;
263
- --fm-faint: #aeaeb2;
264
- --fm-line: #f0f0f0;
265
- --fm-card: #ffffff;
266
- --fm-page: #f3f3f6;
267
- --fm-signature: #ff7823;
268
- --fm-signature-tint: #fff3e6;
269
- --fm-signature-dark: #6b3100;
270
- --fm-danger: #99231d;
271
- --fm-danger-bg: #ffebea;
272
- --fm-aqua-500: #0a5384;
273
- --fm-aqua-300: #3ab0ff;
274
- --fm-aqua-100: #b7e2ff;
275
- --fm-purple-500: #512191;
276
- --fm-purple-300: #8f61e8;
277
- --fm-purple-100: #eddfff;
278
- --fm-green-500: #306a01;
279
- --fm-green-300: #aeef4b;
280
- --fm-green-100: #f4fde6;
281
- --fm-plum-500: #8c146a;
282
- --fm-plum-300: #ffc4c3;
283
- --fm-plum-100: #fff7fc;
284
- --fm-mustard-500: #903e1f;
285
- --fm-mustard-300: #ffc746;
286
- --fm-mustard-100: #fef5ea;
287
- --fm-berry-500: #5f090a;
288
- --fm-berry-300: #e94850;
289
- --fm-berry-100: #fee4dc;
290
- --fm-success: #1f7735;
291
- --fm-success-bg: #ebf9ee;
292
- --fm-warning: #995900;
293
- --fm-warning-bg: #fff4e6;
294
- --fm-error: #99231d;
295
- --fm-error-bg: #ffebea;
296
- --fm-info: #004999;
297
- --fm-info-bg: #e6f2ff;
298
- --fm-radius: 12px;
299
- --fm-radius-sm: 8px;
300
- --fm-gap: 12px;
301
- }
302
- * {
303
- box-sizing: border-box;
304
- }
305
- html,
306
- body {
307
- margin: 0;
308
- padding: 0;
309
- height: 100%;
310
- }
311
- body {
312
- font: 14px/1.5 Inter, "Helvetica Neue", Arial, sans-serif;
313
- color: var(--fm-fg);
314
- background: #fff;
315
- overflow-y: auto;
316
- }
317
- body.fmr-page {
318
- background: var(--fm-page);
319
- }
320
- /* The board: 12 columns, ragged bottoms. A section spans all 12 unless it says otherwise. */
321
- #report {
322
- display: grid;
323
- grid-template-columns: repeat(12, minmax(0, 1fr));
324
- align-items: start;
325
- gap: var(--fm-gap);
326
- padding: 12px 16px 24px;
327
- }
328
- #report > section {
329
- grid-column: 1 / -1;
330
- min-width: 0;
331
- }
332
- /* ---- components ------------------------------------------------------
333
- The FeedMe report component set. A report is composed from these; each one
334
- is already the design system, so nothing here needs restyling to look right. */
335
- .fmr-card {
336
- background: var(--fm-card);
337
- border: 1px solid var(--fm-line);
338
- border-radius: var(--fm-radius);
339
- }
340
- .fmr-tile {
341
- display: flex;
342
- flex-direction: column;
343
- overflow: hidden;
344
- }
345
- .fmr-tile-head {
346
- display: flex;
347
- align-items: flex-start;
348
- justify-content: space-between;
349
- gap: 16px;
350
- flex-wrap: wrap;
351
- padding: 16px 20px 12px;
352
- }
353
- .fmr-tile-title {
354
- margin: 0;
355
- font-size: 16px;
356
- font-weight: 600;
357
- color: var(--fm-fg);
358
- }
359
- /* One factual line. Not a place to explain the report. */
360
- .fmr-tile-note {
361
- margin: 4px 0 0;
362
- font-size: 12px;
363
- color: var(--fm-muted);
364
- }
365
- .fmr-tile-body {
366
- padding: 0 20px 16px;
367
- }
368
- .fmr-tile-foot {
369
- display: flex;
370
- align-items: center;
371
- justify-content: space-between;
372
- gap: 12px;
373
- flex-wrap: wrap;
374
- border-top: 1px solid var(--fm-line);
375
- padding: 10px 20px 12px;
376
- font-size: 12px;
377
- color: var(--fm-muted);
378
- }
379
-
380
- /* Scorecards: label, value, optional trend. */
381
- .fmr-kpis {
382
- display: grid;
383
- grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
384
- gap: var(--fm-gap);
385
- }
386
- .fmr-kpi {
387
- padding: 14px 16px;
388
- min-width: 0;
389
- }
390
- .fmr-kpi-label {
391
- font-size: 14px;
392
- color: var(--fm-muted);
393
- }
394
- .fmr-kpi-value {
395
- display: flex;
396
- align-items: baseline;
397
- gap: 6px;
398
- margin-top: 5px;
399
- font-size: 24px;
400
- font-weight: 700;
401
- color: var(--fm-fg);
402
- font-variant-numeric: tabular-nums;
403
- }
404
- .fmr-kpi-cur {
405
- font-size: 14px;
406
- font-weight: 600;
407
- }
408
- .fmr-kpi-note {
409
- margin-top: 6px;
410
- font-size: 12px;
411
- color: var(--fm-muted);
412
- }
413
- .fmr-trend {
414
- display: inline-flex;
415
- align-items: center;
416
- gap: 4px;
417
- border-radius: 999px;
418
- padding: 3px 8px;
419
- font-size: 12px;
420
- font-weight: 600;
421
- }
422
- .fmr-trend.up { color: var(--fm-success); background: var(--fm-green-100); }
423
- .fmr-trend.down { color: var(--fm-error); background: var(--fm-berry-100); }
424
- .fmr-trend.flat { color: var(--fm-muted); background: var(--fm-line); }
425
-
426
- /* Breakdown: a share row over one stacked bar. */
427
- .fmr-breakdown {
428
- display: grid;
429
- grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
430
- gap: 12px 24px;
431
- }
432
- .fmr-breakdown-label {
433
- display: flex;
434
- align-items: center;
435
- gap: 6px;
436
- font-size: 14px;
437
- color: var(--fm-muted);
438
- }
439
- .fmr-breakdown-value {
440
- margin-top: 2px;
441
- font-size: 14px;
442
- font-weight: 600;
443
- color: var(--fm-fg);
444
- font-variant-numeric: tabular-nums;
445
- }
446
- .fmr-stack {
447
- display: flex;
448
- gap: 2px;
449
- height: 12px;
450
- margin-top: 14px;
451
- }
452
- .fmr-stack > span {
453
- border-radius: 4px;
454
- min-width: 2px;
455
- }
456
-
457
- /* Legend — you draw it in HTML; chart.js legends stay off. */
458
- .fmr-legend {
459
- display: flex;
460
- align-items: center;
461
- flex-wrap: wrap;
462
- gap: 6px 20px;
463
- }
464
- .fmr-legend-item {
465
- display: inline-flex;
466
- align-items: center;
467
- gap: 6px;
468
- font-size: 12px;
469
- color: var(--fm-muted);
470
- }
471
- .fmr-swatch {
472
- width: 10px;
473
- height: 10px;
474
- border-radius: 2px;
475
- flex: none;
476
- }
477
- .fmr-swatch.line {
478
- width: 12px;
479
- height: 2px;
480
- border-radius: 0;
481
- }
482
-
483
- /* Table: no zebra, no vertical rules. */
484
- table.fmr-table {
485
- width: 100%;
486
- border-collapse: collapse;
487
- }
488
- table.fmr-table th {
489
- padding: 0 12px 10px;
490
- text-align: left;
491
- font-size: 14px;
492
- font-weight: 400;
493
- color: var(--fm-muted);
494
- white-space: nowrap;
495
- }
496
- table.fmr-table td {
497
- height: 52px;
498
- padding: 7px 12px;
499
- border-top: 1px solid var(--fm-line);
500
- font-size: 14px;
501
- color: var(--fm-fg);
502
- vertical-align: middle;
503
- }
504
- table.fmr-table th:first-child,
505
- table.fmr-table td:first-child {
506
- padding-left: 20px;
507
- }
508
- table.fmr-table th:last-child,
509
- table.fmr-table td:last-child {
510
- padding-right: 20px;
511
- }
512
- table.fmr-table td:first-child {
513
- font-weight: 600;
514
- }
515
- .fmr-num {
516
- text-align: right;
517
- font-variant-numeric: tabular-nums;
518
- }
519
- .fmr-dim {
520
- color: var(--fm-muted);
521
- }
522
- /* the th/td rules above outrank a bare class, so the table needs its own. */
523
- table.fmr-table th.fmr-num,
524
- table.fmr-table td.fmr-num {
525
- text-align: right;
526
- }
527
- table.fmr-table td.fmr-dim {
528
- color: var(--fm-muted);
529
- }
530
- table.fmr-table td.fmr-empty {
531
- font-weight: 400;
532
- color: var(--fm-muted);
533
- }
534
- .fmr-scroll-x {
535
- overflow-x: auto;
536
- }
537
-
538
- /* Pager: a table's footer. fmr-tile-foot gives it the frame, this adds the two buttons. */
539
- .fmr-pager[hidden] {
540
- display: none;
541
- }
542
- .fmr-pager-btns {
543
- display: flex;
544
- align-items: center;
545
- gap: 16px;
546
- }
547
- .fmr-pager-btns .fmr-link[disabled] {
548
- color: var(--fm-faint);
549
- cursor: default;
550
- text-decoration: none;
551
- }
552
-
553
- /* Tabs — orange marks the active one, the only place a report uses the signature. */
554
- .fmr-tabs {
555
- display: flex;
556
- gap: 4px;
557
- border-bottom: 1px solid var(--fm-line);
558
- padding: 0 20px;
559
- }
560
- .fmr-tab {
561
- border: 0;
562
- background: none;
563
- padding: 12px 16px;
564
- font: inherit;
565
- font-size: 14px;
566
- font-weight: 600;
567
- color: var(--fm-muted);
568
- cursor: pointer;
569
- border-bottom: 2px solid transparent;
570
- margin-bottom: -1px;
571
- }
572
- .fmr-tab[aria-selected="true"] {
573
- color: var(--fm-signature);
574
- border-bottom-color: var(--fm-signature);
575
- }
576
-
577
- /* Status pairs — the dark tone on its own pale ground, never a brand tint. */
578
- .fmr-badge {
579
- display: inline-block;
580
- border-radius: 999px;
581
- padding: 3px 8px;
582
- font-size: 12px;
583
- font-weight: 600;
584
- }
585
- .fmr-badge.success { color: var(--fm-success); background: var(--fm-success-bg); }
586
- .fmr-badge.warning { color: var(--fm-warning); background: var(--fm-warning-bg); }
587
- .fmr-badge.error { color: var(--fm-error); background: var(--fm-error-bg); }
588
- .fmr-badge.info { color: var(--fm-info); background: var(--fm-info-bg); }
589
-
590
- .fmr-link {
591
- border: 0;
592
- background: none;
593
- padding: 0;
594
- font: inherit;
595
- font-weight: 600;
596
- color: var(--fm-info);
597
- cursor: pointer;
598
- text-decoration: underline;
599
- text-decoration-color: transparent;
600
- text-underline-offset: 2px;
601
- }
602
- .fmr-link:hover,
603
- .fmr-link:focus-visible {
604
- text-decoration-color: currentColor;
605
- }
606
-
607
- /* A chart canvas needs a height its parent does not give it. */
608
- .fmr-chart {
609
- position: relative;
610
- height: 240px;
611
- }
612
- .fmr-chart.sm { height: 180px; }
613
- .fmr-chart.lg { height: 320px; }
614
-
615
- /* The two states the shell does not paint. */
616
- .fmr-note {
617
- margin: 0 20px 16px;
618
- padding: 8px 0;
619
- font-size: 14px;
620
- color: var(--fm-muted);
621
- }
622
- .fmr-note.error {
623
- border-radius: var(--fm-radius-sm);
624
- padding: 11px 12px;
625
- color: var(--fm-error);
626
- background: var(--fm-error-bg);
627
- }
628
- .fm-section-error {
629
- border: 1px solid var(--fm-line);
630
- border-left: 3px solid var(--fm-danger);
631
- background: var(--fm-danger-bg);
632
- border-radius: 6px;
633
- padding: 12px 14px;
634
- }
635
- .fm-section-error b {
636
- color: var(--fm-danger);
637
- }
638
- .fm-section-error pre {
639
- margin: 6px 0 0;
640
- white-space: pre-wrap;
641
- font-size: 12px;
642
- color: var(--fm-muted);
643
- }
644
- .fm-placeholder {
645
- color: var(--fm-muted);
646
- padding: 24px 16px;
647
- }
648
- /* Loading belongs to the shell: a section declares its queries and never draws a skeleton. */
649
- #fm-progress {
650
- position: fixed;
651
- inset: 0 0 auto;
652
- z-index: 30;
653
- height: 2px;
654
- overflow: hidden;
655
- background: var(--fm-signature-tint);
656
- opacity: 0;
657
- transition: opacity 0.15s linear;
658
- pointer-events: none;
659
- }
660
- #fm-progress[data-on] {
661
- opacity: 1;
662
- }
663
- #fm-progress i {
664
- display: block;
665
- width: 32%;
666
- height: 100%;
667
- background: var(--fm-signature);
668
- }
669
- section[data-fm-busy] {
670
- position: relative;
671
- min-height: 48px;
672
- }
673
- /* A scrim, not a replacement: the designed panel stays put and stale values stay clickable. */
674
- section[data-fm-busy]::after {
675
- content: "";
676
- position: absolute;
677
- inset: -4px;
678
- border-radius: 10px;
679
- background: rgba(255, 255, 255, 0.62);
680
- pointer-events: none;
681
- }
682
- @media (prefers-reduced-motion: no-preference) {
683
- #fm-progress i {
684
- animation: fm-slide 1.1s linear infinite;
685
- }
686
- }
687
- @keyframes fm-slide {
688
- from {
689
- transform: translateX(-100%);
690
- }
691
- to {
692
- transform: translateX(320%);
693
- }
694
- }
695
- .fm-text h1,
696
- .fm-text h2,
697
- .fm-text h3 {
698
- margin: 0 0 8px;
699
- line-height: 1.3;
700
- }
701
- .fm-text p {
702
- margin: 0 0 8px;
703
- }
704
- .fm-text code {
705
- background: #f0f0f0;
706
- border-radius: 3px;
707
- padding: 1px 4px;
708
- font-size: 12px;
709
- }
710
- </style>
711
-
712
- <div id="fm-progress" data-on aria-hidden="true"><i></i></div>
713
- <div id="report" aria-busy="true"></div>
714
-
715
- <script>
716
- ;(function () {
717
- "use strict"
718
-
719
- var root = document.getElementById("report")
720
-
721
- var env = {}
722
- var params = {}
723
- var results = Object.create(null) // queryId -> { rows, status, runId, truncated, error }
724
- var subs = Object.create(null) // queryId -> [cb]
725
- var loadedLibs = Object.create(null)
726
- var mounted = Object.create(null) // sectionId -> container element
727
- var versions = Object.create(null) // sectionId -> mounted source version
728
- var failed = Object.create(null) // sectionId -> true once this mount reported an error
729
- var order = [] // section ids, render order
730
- var mounting = null // section id currently executing, for window.onerror attribution
731
- var declared = Object.create(null) // sectionId -> the query ids that section reads
732
- var progress = document.getElementById("fm-progress")
733
-
734
- /**
735
- * Section code shares this window and can call parent.postMessage itself, so a render
736
- * outcome carries a nonce only this closure holds — never on \`window\`, never in the DOM.
737
- * The host learns it from \`ready\` and drops any ack without it.
738
- */
739
- var NONCE = (function () {
740
- try {
741
- var buffer = new Uint32Array(4)
742
- crypto.getRandomValues(buffer)
743
- return Array.prototype.map
744
- .call(buffer, function (value) {
745
- return value.toString(36)
746
- })
747
- .join("")
748
- } catch (err) {
749
- return String(Math.random()).slice(2) + String(new Date().getTime())
750
- }
751
- })()
752
-
753
- function post(message) {
754
- // Opaque origins cannot be named, so "*" is the only usable target. The host
755
- // authenticates us by comparing event.source to its own iframe.contentWindow.
756
- parent.postMessage(message, "*")
757
- }
758
-
759
- /** Only the shell may claim a section rendered or threw. */
760
- function postOutcome(message) {
761
- message.nonce = NONCE
762
- post(message)
763
- }
764
-
765
- function reportError(sectionId, err) {
766
- var message = err && err.message ? String(err.message) : String(err)
767
- var stack = err && err.stack ? String(err.stack).slice(0, 4000) : undefined
768
- failed[sectionId] = true
769
- renderError(sectionId, message)
770
- postOutcome({
771
- type: "error",
772
- sectionId: sectionId,
773
- version: versions[sectionId],
774
- message: message,
775
- stack: stack
776
- })
777
- }
778
-
779
- function renderError(sectionId, message) {
780
- var el = mounted[sectionId]
781
- if (!el) return
782
- el.innerHTML = ""
783
- var box = document.createElement("div")
784
- box.className = "fm-section-error"
785
- var title = document.createElement("b")
786
- title.textContent = "This part of the report could not be shown"
787
- var detail = document.createElement("pre")
788
- detail.textContent = message
789
- box.appendChild(title)
790
- box.appendChild(detail)
791
- el.appendChild(box)
792
- }
793
-
794
- // --- markdown (text sections): escape first, then a small safe subset
795
-
796
- function escapeHtml(text) {
797
- return text
798
- .replace(/&/g, "&amp;")
799
- .replace(/</g, "&lt;")
800
- .replace(/>/g, "&gt;")
801
- .replace(/"/g, "&quot;")
802
- }
803
-
804
- function renderMarkdown(source) {
805
- var lines = escapeHtml(String(source || "")).split(/\\r?\\n/)
806
- var out = []
807
- var list = null
808
- function closeList() {
809
- if (list) {
810
- out.push("<" + list.tag + ">" + list.items.join("") + "</" + list.tag + ">")
811
- list = null
812
- }
813
- }
814
- for (var i = 0; i < lines.length; i++) {
815
- var line = lines[i]
816
- var heading = /^(#{1,3})\\s+(.*)$/.exec(line)
817
- var bullet = /^\\s*[-*]\\s+(.*)$/.exec(line)
818
- var numbered = /^\\s*\\d+\\.\\s+(.*)$/.exec(line)
819
- if (heading) {
820
- closeList()
821
- var level = heading[1].length
822
- out.push("<h" + level + ">" + inline(heading[2]) + "</h" + level + ">")
823
- } else if (bullet || numbered) {
824
- var tag = bullet ? "ul" : "ol"
825
- if (!list || list.tag !== tag) {
826
- closeList()
827
- list = { tag: tag, items: [] }
828
- }
829
- list.items.push("<li>" + inline((bullet || numbered)[1]) + "</li>")
830
- } else if (!line.trim()) {
831
- closeList()
832
- } else {
833
- closeList()
834
- out.push("<p>" + inline(line) + "</p>")
835
- }
836
- }
837
- closeList()
838
- return out.join("")
839
- }
840
-
841
- function inline(text) {
842
- return text
843
- .replace(/\`([^\`]+)\`/g, "<code>$1</code>")
844
- .replace(/\\*\\*([^*]+)\\*\\*/g, "<strong>$1</strong>")
845
- .replace(/(^|[^*])\\*([^*]+)\\*/g, "$1<em>$2</em>")
846
- .replace(/\\[([^\\]]+)\\]\\((https?:\\/\\/[^)\\s]+|mailto:[^)\\s]+)\\)/g, function (_all, label, href) {
847
- return '<a href="' + href + '" target="_blank" rel="noreferrer noopener">' + label + "</a>"
848
- })
849
- }
850
-
851
- // --- libs
852
-
853
- function installLibs(bundles) {
854
- if (!bundles) return
855
- Object.keys(bundles).forEach(function (key) {
856
- if (loadedLibs[key]) return
857
- var script = document.createElement("script")
858
- script.textContent = bundles[key]
859
- document.head.appendChild(script)
860
- loadedLibs[key] = true
861
- })
862
- }
863
-
864
- // --- sections
865
-
866
- function container(sectionId) {
867
- var el = mounted[sectionId]
868
- if (el) {
869
- el.innerHTML = ""
870
- return el
871
- }
872
- el = document.createElement("section")
873
- el.id = sectionId
874
- el.dataset.sectionId = sectionId
875
- mounted[sectionId] = el
876
- return el
877
- }
878
-
879
- /**
880
- * Sections share one DOM and one CSS cascade on purpose, but top-level JS is wrapped
881
- * so two sections cannot collide on a \`const\` — they share state through \`window\`.
882
- * Always attempts the persisted source, even one saved as \`status: "error"\`: that is
883
- * what "restore last good source" means, and a genuinely broken one throws and re-acks.
884
- */
885
- function mountSection(section) {
886
- var el = container(section.id)
887
- versions[section.id] = section.version
888
- failed[section.id] = false
889
- declared[section.id] = (section.queryIds || []).slice()
890
- mounting = section.id
891
- try {
892
- if (section.kind === "text") {
893
- var text = document.createElement("div")
894
- text.className = "fm-text"
895
- text.innerHTML = renderMarkdown(section.source)
896
- el.appendChild(text)
897
- return
898
- }
899
- var doc = new DOMParser().parseFromString(
900
- "<body>" + String(section.source || "") + "</body>",
901
- "text/html"
902
- )
903
- var scripts = []
904
- Array.prototype.slice.call(doc.body.childNodes).forEach(function (node) {
905
- if (node.tagName === "SCRIPT") {
906
- scripts.push(node.textContent || "")
907
- } else {
908
- el.appendChild(document.importNode(node, true))
909
- }
910
- })
911
- // Inline scripts throw past the caller's try/catch, so wrap the source itself.
912
- scripts.forEach(function (code, index) {
913
- var tag = document.createElement("script")
914
- tag.textContent = "try{(function(){\\n" + code + "\\n})()}catch(e){window.FM.__err(e)}"
915
- el.appendChild(tag)
916
- void index
917
- })
918
- } catch (err) {
919
- reportError(section.id, err)
920
- } finally {
921
- mounting = null
922
- if (!failed[section.id]) {
923
- postOutcome({ type: "rendered", sectionId: section.id, version: section.version })
924
- }
925
- }
926
- }
927
-
928
- function unmountSection(sectionId) {
929
- var el = mounted[sectionId]
930
- if (el && el.parentNode) el.parentNode.removeChild(el)
931
- delete mounted[sectionId]
932
- delete versions[sectionId]
933
- delete failed[sectionId]
934
- delete declared[sectionId]
935
- Object.keys(subs).forEach(function (queryId) {
936
- subs[queryId] = subs[queryId].filter(function (entry) {
937
- return entry.sectionId !== sectionId
938
- })
939
- })
940
- }
941
-
942
- function renderAll(sections) {
943
- root.innerHTML = ""
944
- mounted = Object.create(null)
945
- versions = Object.create(null)
946
- failed = Object.create(null)
947
- declared = Object.create(null)
948
- subs = Object.create(null)
949
- order = sections.map(function (section) {
950
- return section.id
951
- })
952
- sections.forEach(function (section) {
953
- var el = container(section.id)
954
- root.appendChild(el)
955
- mountSection(section)
956
- })
957
- if (sections.length === 0) {
958
- var empty = document.createElement("div")
959
- empty.className = "fm-placeholder"
960
- empty.textContent = "This report is empty. Ask in the chat to build it."
961
- root.appendChild(empty)
962
- }
963
- root.removeAttribute("aria-busy")
964
- paintBusy()
965
- }
966
-
967
- /** Hot-swap: replace only the named sections, appending any that are new. */
968
- function swapSections(sections) {
969
- sections.forEach(function (section) {
970
- var existing = mounted[section.id]
971
- if (existing) {
972
- unmountSection(section.id)
973
- var replacement = container(section.id)
974
- root.insertBefore(replacement, positionAfter(section.id))
975
- mountSection(section)
976
- return
977
- }
978
- order.push(section.id)
979
- var el = container(section.id)
980
- root.appendChild(el)
981
- mountSection(section)
982
- })
983
- paintBusy()
984
- }
985
-
986
- function positionAfter(sectionId) {
987
- var index = order.indexOf(sectionId)
988
- for (var i = index + 1; i < order.length; i++) {
989
- if (mounted[order[i]]) return mounted[order[i]]
990
- }
991
- return null
992
- }
993
-
994
- function notify(queryId) {
995
- var list = subs[queryId] || []
996
- list.slice().forEach(function (entry) {
997
- try {
998
- entry.cb(results[queryId] ? results[queryId].rows : [])
999
- } catch (err) {
1000
- reportError(entry.sectionId, err)
1001
- }
1002
- })
1003
- }
1004
-
1005
- // --- loading
1006
-
1007
- /**
1008
- * Every report gets the same loading affordance, so no section hand-rolls one: a scrim
1009
- * over each section whose declared query is in flight, plus one bar for the report.
1010
- * Only \`loading\` counts — an idle lazy query keeps the empty state it was designed with,
1011
- * and a query the shell has not heard about yet is not assumed to be running.
1012
- */
1013
- function paintBusy() {
1014
- Object.keys(mounted).forEach(function (sectionId) {
1015
- var el = mounted[sectionId]
1016
- var busy = !failed[sectionId] && (declared[sectionId] || []).some(isRunning)
1017
- if (busy) {
1018
- el.setAttribute("data-fm-busy", "")
1019
- el.setAttribute("aria-busy", "true")
1020
- } else {
1021
- el.removeAttribute("data-fm-busy")
1022
- el.removeAttribute("aria-busy")
1023
- }
1024
- })
1025
- if (progress) {
1026
- if (Object.keys(results).some(isRunning)) progress.setAttribute("data-on", "")
1027
- else progress.removeAttribute("data-on")
1028
- }
1029
- }
1030
-
1031
- function isRunning(queryId) {
1032
- var result = results[queryId]
1033
- return !!result && result.status === "loading"
1034
- }
1035
-
1036
- // --- FM: the only API section code may use (see the agent system prompt)
1037
-
1038
- window.env = env
1039
- window.FM = {
1040
- rows: function (queryId) {
1041
- var result = results[queryId]
1042
- return result && result.rows ? result.rows : []
1043
- },
1044
- status: function (queryId) {
1045
- var result = results[queryId]
1046
- return result ? result.status : "idle"
1047
- },
1048
- onRows: function (queryId, cb) {
1049
- if (typeof cb !== "function") return
1050
- if (!subs[queryId]) subs[queryId] = []
1051
- subs[queryId].push({ sectionId: mounting, cb: cb })
1052
- // fire immediately so a section renders its current state without waiting
1053
- try {
1054
- cb(window.FM.rows(queryId))
1055
- } catch (err) {
1056
- reportError(mounting, err)
1057
- }
1058
- },
1059
- setParams: function (values) {
1060
- if (!values || typeof values !== "object") return
1061
- post({ type: "setParams", values: values })
1062
- },
1063
- params: function () {
1064
- return JSON.parse(JSON.stringify(params))
1065
- },
1066
- /** Takes no section id on purpose: the shell attributes the failure to what it is mounting. */
1067
- __err: function (err) {
1068
- if (mounting) reportError(mounting, err)
1069
- }
1070
- }
1071
-
1072
- window.addEventListener("error", function (event) {
1073
- if (!mounting) return
1074
- reportError(mounting, event.error || new Error(event.message))
1075
- })
1076
- window.addEventListener("unhandledrejection", function (event) {
1077
- if (!mounting) return
1078
- reportError(mounting, event.reason || new Error("unhandled rejection"))
1079
- })
1080
-
1081
- // --- host channel
1082
-
1083
- window.addEventListener("message", function (event) {
1084
- // the host is the only window that can reach us; anything else is not ours
1085
- if (event.source !== window.parent) return
1086
- var data = event.data
1087
- if (!data || typeof data !== "object") return
1088
- switch (data.type) {
1089
- case "init":
1090
- env = data.env || {}
1091
- window.env = env
1092
- params = data.params || {}
1093
- installLibs(data.libs)
1094
- renderAll(data.sections || [])
1095
- break
1096
- case "sections":
1097
- installLibs(data.libs)
1098
- swapSections(data.sections || [])
1099
- break
1100
- case "params":
1101
- params = data.values || {}
1102
- Object.keys(subs).forEach(notify)
1103
- break
1104
- // Mutated in place, never replaced: sections captured \`env\` at mount and a new
1105
- // object would leave every one of them reading the empty first snapshot.
1106
- case "env":
1107
- Object.keys(env).forEach(function (key) { delete env[key] })
1108
- Object.keys(data.env || {}).forEach(function (key) { env[key] = data.env[key] })
1109
- Object.keys(subs).forEach(notify)
1110
- break
1111
- case "rows":
1112
- var previous = results[data.queryId]
1113
- if (previous && previous.runId > data.runId) return // superseded run
1114
- results[data.queryId] = {
1115
- rows: data.rows || [],
1116
- status: data.status,
1117
- runId: data.runId,
1118
- truncated: !!data.truncated,
1119
- error: data.error
1120
- }
1121
- notify(data.queryId)
1122
- paintBusy()
1123
- break
1124
- }
1125
- })
1126
-
1127
- post({ type: "ready", nonce: NONCE })
1128
- })()
1129
- <\/script>
1130
- `, Rn = On, Q = 8e3;
1131
- function Cn(r, c) {
1132
- const l = q(!1);
1133
- let s = null;
1134
- const p = /* @__PURE__ */ new Map();
1135
- let g;
1136
- const I = /* @__PURE__ */ new Map();
1137
- function o() {
1138
- var e;
1139
- return ((e = r.value) == null ? void 0 : e.contentWindow) ?? null;
1140
- }
1141
- function i(e) {
1142
- var u;
1143
- (u = o()) == null || u.postMessage(JSON.parse(JSON.stringify(e)), "*");
1144
- }
1145
- function w(e) {
1146
- const u = o();
1147
- if (!u || e.source !== u) return;
1148
- const n = e.data;
1149
- if (!(!n || typeof n != "object"))
1150
- switch (n.type) {
1151
- case "ready":
1152
- if (l.value) return;
1153
- g = n.nonce, l.value = !0, s == null || s(), s = null, A();
1154
- break;
1155
- case "setParams":
1156
- c.onSetParams(n.values ?? {});
1157
- break;
1158
- case "rendered":
1159
- if (!S(n)) return;
1160
- h(n.sectionId, n.version), c.onSectionRendered(n.sectionId, n.version);
1161
- break;
1162
- case "error":
1163
- if (!S(n)) return;
1164
- h(n.sectionId, n.version), c.onSectionError(n.sectionId, n.version, n.message);
1165
- break;
1166
- }
1167
- }
1168
- function S(e) {
1169
- return !g || e.nonce === g ? !0 : (console.warn("[report-canvas] dropped a render outcome without the shell nonce"), !1);
1170
- }
1171
- function y(e, u) {
1172
- return `${e}@${u}`;
1173
- }
1174
- function h(e, u) {
1175
- if (u === void 0) return;
1176
- const n = y(e, u), t = I.get(n);
1177
- t !== void 0 && (clearTimeout(t), I.delete(n));
1178
- }
1179
- function C() {
1180
- I.forEach((e) => clearTimeout(e)), I.clear();
1181
- }
1182
- function O(e) {
1183
- for (const u of e) {
1184
- const n = y(u.id, u.version);
1185
- I.has(n) || I.set(
1186
- n,
1187
- setTimeout(() => {
1188
- I.delete(n), c.onSectionError(
1189
- u.id,
1190
- u.version,
1191
- `the section did not report a render within ${Q}ms`
1192
- );
1193
- }, Q)
1194
- );
1195
- }
1196
- }
1197
- async function _(e, u, n) {
1198
- const t = await Y(e.flatMap((k) => k.libs ?? [])), m = () => {
1199
- i({ type: "init", sections: e, params: u, libs: t, env: n }), C(), O(e);
1200
- };
1201
- l.value ? m() : s = m;
1202
- }
1203
- async function a(e) {
1204
- const u = await Y(e.flatMap((n) => n.libs ?? []));
1205
- i({ type: "sections", sections: e, libs: u }), O(e);
1206
- }
1207
- function v(e) {
1208
- i({ type: "params", values: e });
1209
- }
1210
- function x(e) {
1211
- i({ type: "env", env: e });
1212
- }
1213
- function A() {
1214
- const e = [...p.values()];
1215
- p.clear(), e.forEach(E);
1216
- }
1217
- function E(e) {
1218
- i({
1219
- type: "rows",
1220
- queryId: e.queryId,
1221
- runId: e.runId,
1222
- rows: e.rows,
1223
- status: e.status,
1224
- truncated: e.truncated,
1225
- error: e.error
1226
- });
1227
- }
1228
- function R(e) {
1229
- if (!l.value) {
1230
- p.set(e.queryId, e);
1231
- return;
1232
- }
1233
- E(e);
1234
- }
1235
- W(() => window.addEventListener("message", w)), tn(() => {
1236
- window.removeEventListener("message", w), C();
1237
- });
1238
- function M() {
1239
- l.value = !1, s = null, g = void 0, p.clear(), C();
1240
- }
1241
- return { ready: l, init: _, swapSections: a, pushParams: v, pushEnv: x, pushRows: R, reset: M };
1242
- }
1243
- const Mn = { class: "flex h-full min-h-0 w-full" }, jn = { class: "flex min-w-0 grow flex-col" }, qn = { class: "flex items-start overflow-x-auto border-b border-fm-color-border-secondary px-16 py-8 scrollbar-hide" }, _n = {
1244
- key: 0,
1245
- class: "fm-typo-en-body-xs-400 border-b border-fm-color-border-secondary bg-fm-color-system-warning-100 px-16 py-8"
1246
- }, An = {
1247
- key: 1,
1248
- class: "fm-typo-en-body-sm-400 p-16 text-fm-color-typo-error"
1249
- }, Nn = ["srcdoc", "title"], Hn = /* @__PURE__ */ rn({
1250
- __name: "ReportCanvasView",
1251
- setup(r) {
1252
- const c = cn(), { t: l } = ln(), s = String(c.query.reportId ?? ""), p = q(), g = q(""), I = q(), o = In(s), { dateRange: i, selectedLocationIds: w, locations: S, timezone: y } = N(X()), h = Cn(I, {
1253
- onSetParams: (a) => {
1254
- o.setParams(a) && h.pushParams(o.params.value);
1255
- },
1256
- onSectionRendered: (a, v) => void C(a, v, "ok"),
1257
- onSectionError: (a, v, x) => {
1258
- console.warn("[report-canvas] section failed", { reportId: s, sectionId: a, message: x }), C(a, v, "error", x);
1259
- }
1260
- });
1261
- o.onResult((a) => h.pushRows(a));
1262
- async function C(a, v, x, A) {
1263
- var M;
1264
- const E = (M = p.value) == null ? void 0 : M.sections.find((e) => e.id === a);
1265
- if (!E || v !== E.version) return;
1266
- const R = x === "error" ? A ?? "the section failed to render" : void 0;
1267
- if (!(E.status === x && E.error === R)) {
1268
- E.status = x, E.error = R;
1269
- try {
1270
- await hn(s, a, { version: v, status: x, error: R });
1271
- } catch (e) {
1272
- console.warn("[report-canvas] ack failed", { reportId: s, sectionId: a, err: e });
1273
- }
1274
- }
1275
- }
1276
- async function O() {
1277
- try {
1278
- g.value = "";
1279
- const a = await pn(s);
1280
- p.value = a, o.load(a), await h.init(a.sections, o.params.value, o.env());
1281
- } catch (a) {
1282
- g.value = a instanceof Error ? a.message : String(a);
1283
- }
1284
- }
1285
- H([i, w, S], () => {
1286
- if (!p.value) return;
1287
- o.setParams({
1288
- "@from": i.value.startDate ?? null,
1289
- "@to": i.value.endDate ?? null,
1290
- "@locationIds": w.value.length ? [...w.value] : S.value.map((v) => v.id)
1291
- }) && h.pushParams(o.params.value);
1292
- }), H([S, y], () => {
1293
- p.value && h.pushEnv(o.env());
1294
- });
1295
- const _ = on(
1296
- () => Object.values(o.results.value).some((a) => a.truncated)
1297
- );
1298
- return W(async () => {
1299
- await O();
1300
- }), (a, v) => (L(), T("div", Mn, [
1301
- P("div", jn, [
1302
- P("div", qn, [
1303
- V(un, {
1304
- modelValue: j(w),
1305
- "onUpdate:modelValue": v[1] || (v[1] = (x) => F(w) ? w.value = x : null),
1306
- options: j(S)
1307
- }, {
1308
- default: sn(() => [
1309
- V(fn, {
1310
- "date-range": j(i),
1311
- "onUpdate:dateRange": v[0] || (v[0] = (x) => F(i) ? i.value = x : null)
1312
- }, null, 8, ["date-range"])
1313
- ]),
1314
- _: 1
1315
- }, 8, ["modelValue", "options"])
1316
- ]),
1317
- _.value ? (L(), T("div", _n, J(j(l)("reportV5.reportCanvas.canvas.truncated")), 1)) : U("", !0),
1318
- g.value ? (L(), T("p", An, J(g.value), 1)) : U("", !0),
1319
- an(P("iframe", {
1320
- ref_key: "frame",
1321
- ref: I,
1322
- "data-testid": "report-canvas-frame",
1323
- class: "min-h-0 grow border-0",
1324
- srcdoc: j(Rn),
1325
- sandbox: "allow-scripts",
1326
- title: j(l)("reportV5.reportCanvas.canvas.title")
1327
- }, null, 8, Nn), [
1328
- [dn, !g.value]
1329
- ])
1330
- ])
1331
- ]));
1332
- }
1333
- });
1334
- export {
1335
- Hn as default
1336
- };