@fayz-ai/plugin-reports 0.10.0 → 0.11.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.
- package/dist/{chunk-2ZFN6ECM.js → chunk-4SPBNVQA.js} +3 -2
- package/dist/chunk-4SPBNVQA.js.map +1 -0
- package/dist/data/analytics-supabase.d.ts.map +1 -1
- package/dist/{excel-WE73YE2V.js → excel-KIJTC7OJ.js} +3 -3
- package/dist/{excel-WE73YE2V.js.map → excel-KIJTC7OJ.js.map} +1 -1
- package/dist/index.js +98 -74
- package/dist/index.js.map +1 -1
- package/dist/lib/columns.d.ts.map +1 -1
- package/dist/lib/legacy.d.ts.map +1 -1
- package/dist/{pdf-E6DXHFXU.js → pdf-7QQ3U5JQ.js} +3 -3
- package/dist/{pdf-E6DXHFXU.js.map → pdf-7QQ3U5JQ.js.map} +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/views/AnalyticsAssistant.d.ts +3 -0
- package/dist/views/AnalyticsAssistant.d.ts.map +1 -0
- package/dist/views/AnalyticsModule.d.ts.map +1 -1
- package/dist/views/AnalyticsOverview.d.ts.map +1 -1
- package/dist/views/AnalyticsSurface.d.ts +5 -0
- package/dist/views/AnalyticsSurface.d.ts.map +1 -1
- package/package.json +4 -4
- package/dist/chunk-2ZFN6ECM.js.map +0 -1
|
@@ -61,6 +61,7 @@ function reportColumnsToTanstack(columns, currency) {
|
|
|
61
61
|
content = React.createElement(PersonLink, {
|
|
62
62
|
personId: col.idKey ? row[col.idKey] : null,
|
|
63
63
|
name: String(value),
|
|
64
|
+
kind: col.personKind,
|
|
64
65
|
size: "sm",
|
|
65
66
|
className: "text-xs"
|
|
66
67
|
});
|
|
@@ -96,5 +97,5 @@ function reportColumnsToTanstack(columns, currency) {
|
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
export { formatValuePlain, reportColumnsToTanstack };
|
|
99
|
-
//# sourceMappingURL=chunk-
|
|
100
|
-
//# sourceMappingURL=chunk-
|
|
100
|
+
//# sourceMappingURL=chunk-4SPBNVQA.js.map
|
|
101
|
+
//# sourceMappingURL=chunk-4SPBNVQA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/columns.ts"],"names":["formatCurrencyLocale","formatDateLocale","formatDateTimeLocale"],"mappings":"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","file":"chunk-4SPBNVQA.js","sourcesContent":["import React from 'react'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport type { ReportColumnDef } from '../types'\nimport { PersonLink } from '@fayz-ai/admin'\nimport {\n formatCurrency as formatCurrencyLocale,\n formatDate as formatDateLocale,\n formatDateTime as formatDateTimeLocale,\n} from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Formatters (mirrors fieldToColumn.tsx logic)\n// ---------------------------------------------------------------------------\n\nfunction formatCurrency(value: any, currency?: string): string {\n const num = typeof value === 'number' ? value : parseFloat(value)\n if (isNaN(num)) return '—'\n return formatCurrencyLocale(num, currency)\n}\n\nfunction formatDate(value: any): string {\n if (!value) return '—'\n return formatDateLocale(value)\n}\n\nfunction formatDateTime(value: any): string {\n if (!value) return '—'\n return formatDateTimeLocale(value)\n}\n\nfunction formatNumber(value: any): string {\n if (value == null) return '—'\n return typeof value === 'number' ? value.toLocaleString() : String(value)\n}\n\n// ---------------------------------------------------------------------------\n// Plain-text formatter for exports\n// ---------------------------------------------------------------------------\n\nexport function formatValuePlain(value: any, col: ReportColumnDef, currency?: string): string {\n if (value == null || value === '') return ''\n switch (col.type) {\n case 'currency':\n return formatCurrency(value, col.currency ?? currency)\n case 'date':\n return formatDate(value)\n case 'datetime':\n return formatDateTime(value)\n case 'number':\n return formatNumber(value)\n case 'boolean':\n return value ? 'Yes' : 'No'\n default:\n return String(value)\n }\n}\n\n// ---------------------------------------------------------------------------\n// ReportColumnDef[] → TanStack ColumnDef[]\n// ---------------------------------------------------------------------------\n\nexport function reportColumnsToTanstack(\n columns: ReportColumnDef[],\n currency?: string,\n): ColumnDef<Record<string, any>>[] {\n return columns\n .filter((c) => c.visible !== false)\n .map((col): ColumnDef<Record<string, any>> => {\n const sortable = col.sortable ?? ['text', 'number', 'currency', 'date', 'datetime', 'email'].includes(col.type)\n const alignRight = col.align === 'right' || (!col.align && (col.type === 'currency' || col.type === 'number'))\n const alignCenter = col.align === 'center'\n\n return {\n accessorKey: col.key,\n header: col.label,\n enableSorting: sortable,\n cell: (ctx) => {\n const value = ctx.getValue()\n const row = ctx.row.original\n\n if (col.renderCell) {\n return col.renderCell(value, row)\n }\n\n if (value == null || value === '') {\n return React.createElement('span', { className: 'text-muted-foreground' }, '—')\n }\n\n let content: React.ReactNode\n switch (col.type) {\n case 'person':\n content = React.createElement(PersonLink, {\n personId: col.idKey ? row[col.idKey] : null,\n name: String(value),\n kind: col.personKind,\n size: 'sm',\n className: 'text-xs',\n })\n break\n case 'currency':\n content = formatCurrency(value, col.currency ?? currency)\n break\n case 'date':\n content = formatDate(value)\n break\n case 'datetime':\n content = formatDateTime(value)\n break\n case 'boolean':\n content = value\n ? React.createElement('svg', { className: 'h-4 w-4 text-success', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2' },\n React.createElement('polyline', { points: '20 6 9 17 4 12' }),\n )\n : React.createElement('span', { className: 'text-muted-foreground' }, '—')\n break\n case 'number':\n content = formatNumber(value)\n break\n default:\n content = String(value)\n }\n\n const cls = alignRight ? 'text-right' : alignCenter ? 'text-center' : undefined\n return cls\n ? React.createElement('div', { className: cls }, content)\n : React.createElement(React.Fragment, null, content)\n },\n meta: { align: alignRight ? 'right' : alignCenter ? 'center' : 'left' },\n }\n })\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics-supabase.d.ts","sourceRoot":"","sources":["../../src/data/analytics-supabase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAC+B,iBAAiB,EAE3D,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"analytics-supabase.d.ts","sourceRoot":"","sources":["../../src/data/analytics-supabase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAC+B,iBAAiB,EAE3D,MAAM,eAAe,CAAA;AA6MtB,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAA;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,+BAA+B,GAAG,iBAAiB,CAkJ1G"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { formatValuePlain } from './chunk-
|
|
1
|
+
import { formatValuePlain } from './chunk-4SPBNVQA.js';
|
|
2
2
|
|
|
3
3
|
// src/export/excel.ts
|
|
4
4
|
var load = (m) => new Function("m", "return import(m)")(m);
|
|
@@ -31,5 +31,5 @@ async function isExcelAvailable() {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export { exportToExcel, isExcelAvailable };
|
|
34
|
-
//# sourceMappingURL=excel-
|
|
35
|
-
//# sourceMappingURL=excel-
|
|
34
|
+
//# sourceMappingURL=excel-KIJTC7OJ.js.map
|
|
35
|
+
//# sourceMappingURL=excel-KIJTC7OJ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/export/excel.ts"],"names":[],"mappings":";;;AAKA,IAAM,IAAA,GAAO,CAAC,CAAA,KAAc,IAAI,SAAS,GAAA,EAAK,kBAAkB,EAAE,CAAC,CAAA;AAEnE,eAAsB,aAAA,CACpB,OAAA,EACA,IAAA,EACA,QAAA,EACA,QAAA,EACe;AACf,EAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,MAAM,CAAA;AAC9B,EAAA,MAAM,cAAc,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,YAAY,KAAK,CAAA;AAE7D,EAAA,MAAM,SAAS,WAAA,CAAY,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,KAAK,CAAA;AAC7C,EAAA,MAAM,OAAO,IAAA,CAAK,GAAA;AAAA,IAAI,CAAC,GAAA,KACrB,WAAA,CAAY,GAAA,CAAI,CAAC,GAAA,KAAQ;AACvB,MAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AACzB,MAAA,IAAI,GAAA,CAAI,IAAA,KAAS,QAAA,IAAY,GAAA,CAAI,SAAS,UAAA,EAAY;AACpD,QAAA,MAAM,MAAM,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,WAAW,KAAK,CAAA;AAChE,QAAA,OAAO,KAAA,CAAM,GAAG,CAAA,GAAI,EAAA,GAAK,GAAA;AAAA,MAC3B;AACA,MAAA,OAAO,gBAAA,CAAiB,KAAA,EAAO,GAAA,EAAK,QAAQ,CAAA;AAAA,IAC9C,CAAC;AAAA,GACH;AAEA,EAAA,MAAM,EAAA,GAAK,KAAK,KAAA,CAAM,YAAA,CAAa,CAAC,MAAA,EAAQ,GAAG,IAAI,CAAC,CAAA;AACpD,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAM,QAAA,EAAS;AAC/B,EAAA,IAAA,CAAK,KAAA,CAAM,iBAAA,CAAkB,EAAA,EAAI,EAAA,EAAI,QAAQ,CAAA;AAC7C,EAAA,IAAA,CAAK,SAAA,CAAU,EAAA,EAAI,CAAA,EAAG,QAAQ,CAAA,KAAA,CAAO,CAAA;AACvC;AAEA,eAAsB,gBAAA,GAAqC;AACzD,EAAA,IAAI;AACF,IAAA,MAAM,KAAK,MAAM,CAAA;AACjB,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF","file":"excel-
|
|
1
|
+
{"version":3,"sources":["../src/export/excel.ts"],"names":[],"mappings":";;;AAKA,IAAM,IAAA,GAAO,CAAC,CAAA,KAAc,IAAI,SAAS,GAAA,EAAK,kBAAkB,EAAE,CAAC,CAAA;AAEnE,eAAsB,aAAA,CACpB,OAAA,EACA,IAAA,EACA,QAAA,EACA,QAAA,EACe;AACf,EAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,MAAM,CAAA;AAC9B,EAAA,MAAM,cAAc,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,YAAY,KAAK,CAAA;AAE7D,EAAA,MAAM,SAAS,WAAA,CAAY,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,KAAK,CAAA;AAC7C,EAAA,MAAM,OAAO,IAAA,CAAK,GAAA;AAAA,IAAI,CAAC,GAAA,KACrB,WAAA,CAAY,GAAA,CAAI,CAAC,GAAA,KAAQ;AACvB,MAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AACzB,MAAA,IAAI,GAAA,CAAI,IAAA,KAAS,QAAA,IAAY,GAAA,CAAI,SAAS,UAAA,EAAY;AACpD,QAAA,MAAM,MAAM,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,WAAW,KAAK,CAAA;AAChE,QAAA,OAAO,KAAA,CAAM,GAAG,CAAA,GAAI,EAAA,GAAK,GAAA;AAAA,MAC3B;AACA,MAAA,OAAO,gBAAA,CAAiB,KAAA,EAAO,GAAA,EAAK,QAAQ,CAAA;AAAA,IAC9C,CAAC;AAAA,GACH;AAEA,EAAA,MAAM,EAAA,GAAK,KAAK,KAAA,CAAM,YAAA,CAAa,CAAC,MAAA,EAAQ,GAAG,IAAI,CAAC,CAAA;AACpD,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAM,QAAA,EAAS;AAC/B,EAAA,IAAA,CAAK,KAAA,CAAM,iBAAA,CAAkB,EAAA,EAAI,EAAA,EAAI,QAAQ,CAAA;AAC7C,EAAA,IAAA,CAAK,SAAA,CAAU,EAAA,EAAI,CAAA,EAAG,QAAQ,CAAA,KAAA,CAAO,CAAA;AACvC;AAEA,eAAsB,gBAAA,GAAqC;AACzD,EAAA,IAAI;AACF,IAAA,MAAM,KAAK,MAAM,CAAA;AACjB,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF","file":"excel-KIJTC7OJ.js","sourcesContent":["import type { ReportColumnDef } from '../types'\nimport { formatValuePlain } from '../lib/columns'\n\n// Opaque dynamic import — hidden from Vite's static analysis so it won't\n// fail when xlsx is not installed (it's an optional peer dependency).\nconst load = (m: string) => new Function('m', 'return import(m)')(m) as Promise<any>\n\nexport async function exportToExcel(\n columns: ReportColumnDef[],\n data: Record<string, any>[],\n filename: string,\n currency?: string,\n): Promise<void> {\n const XLSX = await load('xlsx')\n const visibleCols = columns.filter((c) => c.visible !== false)\n\n const header = visibleCols.map((c) => c.label)\n const rows = data.map((row) =>\n visibleCols.map((col) => {\n const value = row[col.key]\n if (col.type === 'number' || col.type === 'currency') {\n const num = typeof value === 'number' ? value : parseFloat(value)\n return isNaN(num) ? '' : num\n }\n return formatValuePlain(value, col, currency)\n }),\n )\n\n const ws = XLSX.utils.aoa_to_sheet([header, ...rows])\n const wb = XLSX.utils.book_new()\n XLSX.utils.book_append_sheet(wb, ws, 'Report')\n XLSX.writeFile(wb, `${filename}.xlsx`)\n}\n\nexport async function isExcelAvailable(): Promise<boolean> {\n try {\n await load('xlsx')\n return true\n } catch {\n return false\n }\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { reportColumnsToTanstack, formatValuePlain } from './chunk-
|
|
2
|
-
import * as
|
|
3
|
-
import
|
|
4
|
-
import { usePluginRuntime, getAnalyticsCards,
|
|
1
|
+
import { reportColumnsToTanstack, formatValuePlain } from './chunk-4SPBNVQA.js';
|
|
2
|
+
import * as React6 from 'react';
|
|
3
|
+
import React6__default, { useState, useEffect } from 'react';
|
|
4
|
+
import { usePluginRuntime, getAnalyticsCards, registerTranslations, createSafeDataProvider, getSupabaseClientOptional, hashRouterAdapter, useTranslation, exportCSV } from '@fayz-ai/core';
|
|
5
5
|
import { useOrganizationStore, useShellRailAvailable, useContextualNav, AssistantInvite } from '@fayz-ai/admin';
|
|
6
6
|
import { AnalyticsContextProvider, useModuleLayout, ModulePage, collectFilters, AnalyticsControls, AnalyticsGrid, Card, FilterChip, DataTable, Button, SubpageHeader, useAnalyticsCard, useAnalyticsContext, AnalyticsCard, Dropdown, DropdownTrigger, DropdownContent, DropdownItem } from '@fayz-ai/ui';
|
|
7
7
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -164,7 +164,7 @@ function reservedKeys(card) {
|
|
|
164
164
|
]);
|
|
165
165
|
}
|
|
166
166
|
function searchColumns(card) {
|
|
167
|
-
const cols = (card.columns ?? []).filter((c) => c.type === "text" || c.type === "email").map((c) => c.key);
|
|
167
|
+
const cols = (card.columns ?? []).filter((c) => c.type === "text" || c.type === "email" || c.type === "person").map((c) => c.key);
|
|
168
168
|
return cols.length ? cols : void 0;
|
|
169
169
|
}
|
|
170
170
|
function camelToSnake(s) {
|
|
@@ -205,6 +205,19 @@ async function selectFromView(card, state, db, tenantId, reserved) {
|
|
|
205
205
|
total: count ?? 0
|
|
206
206
|
};
|
|
207
207
|
}
|
|
208
|
+
function toError(err) {
|
|
209
|
+
if (err instanceof Error) return err;
|
|
210
|
+
if (err && typeof err === "object") {
|
|
211
|
+
const e = err;
|
|
212
|
+
const message = [...new Set(
|
|
213
|
+
[e.message, e.details, e.hint].filter(
|
|
214
|
+
(part) => typeof part === "string" && part.trim().length > 0
|
|
215
|
+
)
|
|
216
|
+
)].join(" \u2014 ");
|
|
217
|
+
if (message) return Object.assign(new Error(message), e.code ? { code: e.code } : {});
|
|
218
|
+
}
|
|
219
|
+
return new Error(String(err));
|
|
220
|
+
}
|
|
208
221
|
function isAggregateCard(card) {
|
|
209
222
|
const { source } = card.query;
|
|
210
223
|
if (source.kind !== "view" || !source.name) return false;
|
|
@@ -327,7 +340,7 @@ function createSupabaseAnalyticsProvider(config) {
|
|
|
327
340
|
const singles = requests.map((req, i) => ({ req, i })).filter(({ i }) => !batchable.includes(i)).map(({ req, i }) => this.run(req.card, req.state).then((r) => {
|
|
328
341
|
out[i] = r;
|
|
329
342
|
}).catch((e) => {
|
|
330
|
-
out[i] =
|
|
343
|
+
out[i] = toError(e);
|
|
331
344
|
}));
|
|
332
345
|
if (batchable.length > 0) {
|
|
333
346
|
const tenantId = resolveTenantId();
|
|
@@ -340,7 +353,7 @@ function createSupabaseAnalyticsProvider(config) {
|
|
|
340
353
|
...batchable.map((i) => this.run(requests[i].card, requests[i].state).then((r) => {
|
|
341
354
|
out[i] = r;
|
|
342
355
|
}).catch((e) => {
|
|
343
|
-
out[i] =
|
|
356
|
+
out[i] = toError(e);
|
|
344
357
|
}))
|
|
345
358
|
]);
|
|
346
359
|
return out;
|
|
@@ -350,7 +363,7 @@ function createSupabaseAnalyticsProvider(config) {
|
|
|
350
363
|
batchable.forEach((cardIndex, slot) => {
|
|
351
364
|
const entry = results[slot];
|
|
352
365
|
const { card } = requests[cardIndex];
|
|
353
|
-
out[cardIndex] = entry?.error ? Object.assign(
|
|
366
|
+
out[cardIndex] = entry?.error ? Object.assign(toError(entry.error), { code: entry.code }) : toResult(entry, card, reservedKeys(card));
|
|
354
367
|
});
|
|
355
368
|
}
|
|
356
369
|
await Promise.all(singles);
|
|
@@ -577,6 +590,7 @@ function reportDefToCard(report, createdBy) {
|
|
|
577
590
|
sortable: c.sortable,
|
|
578
591
|
currency: c.currency,
|
|
579
592
|
idKey: c.idKey,
|
|
593
|
+
personKind: c.personKind,
|
|
580
594
|
renderCell: c.renderCell,
|
|
581
595
|
visible: c.visible,
|
|
582
596
|
align: c.align,
|
|
@@ -611,8 +625,8 @@ function markViewed(cardId) {
|
|
|
611
625
|
for (const listener of listeners) listener(next);
|
|
612
626
|
}
|
|
613
627
|
function useLastViewed() {
|
|
614
|
-
const [map, setMap] =
|
|
615
|
-
|
|
628
|
+
const [map, setMap] = React6.useState(() => read());
|
|
629
|
+
React6.useEffect(() => {
|
|
616
630
|
listeners.add(setMap);
|
|
617
631
|
return () => {
|
|
618
632
|
listeners.delete(setMap);
|
|
@@ -622,16 +636,16 @@ function useLastViewed() {
|
|
|
622
636
|
}
|
|
623
637
|
var ANALYTICS_BASE = "/analytics";
|
|
624
638
|
var REPORTS_BASE = `${ANALYTICS_BASE}/reports`;
|
|
625
|
-
var ConfigContext =
|
|
639
|
+
var ConfigContext = React6__default.createContext(null);
|
|
626
640
|
function useAnalyticsConfig() {
|
|
627
|
-
const ctx =
|
|
641
|
+
const ctx = React6__default.useContext(ConfigContext);
|
|
628
642
|
if (!ctx) throw new Error("useAnalyticsConfig must be used inside <AnalyticsSurface>");
|
|
629
643
|
return ctx;
|
|
630
644
|
}
|
|
631
645
|
function useAnalyticsCards() {
|
|
632
646
|
const runtime = usePluginRuntime();
|
|
633
647
|
const { cards, createdBy } = useAnalyticsConfig();
|
|
634
|
-
return
|
|
648
|
+
return React6__default.useMemo(() => {
|
|
635
649
|
const byId = /* @__PURE__ */ new Map();
|
|
636
650
|
for (const card of getAnalyticsCards(runtime)) byId.set(card.id, card);
|
|
637
651
|
for (const card of cards) byId.set(card.id, card);
|
|
@@ -640,7 +654,7 @@ function useAnalyticsCards() {
|
|
|
640
654
|
}
|
|
641
655
|
function useOverviewCards() {
|
|
642
656
|
const all = useAnalyticsCards();
|
|
643
|
-
return
|
|
657
|
+
return React6__default.useMemo(
|
|
644
658
|
() => all.filter((c) => c.dashboard && c.dashboard.defaultVisible !== false).sort((a, b) => (a.dashboard?.order ?? 0) - (b.dashboard?.order ?? 0)),
|
|
645
659
|
[all]
|
|
646
660
|
);
|
|
@@ -648,10 +662,14 @@ function useOverviewCards() {
|
|
|
648
662
|
function cardColumns(card) {
|
|
649
663
|
if (card.columns?.length) return card.columns;
|
|
650
664
|
return [
|
|
651
|
-
|
|
665
|
+
// A hidden dimension is group-by only — the id a person column reads from,
|
|
666
|
+
// never a column of UUIDs next to the name it belongs to.
|
|
667
|
+
...(card.query.dimensions ?? []).filter((d) => !d.hidden).map((d) => ({
|
|
652
668
|
key: d.key,
|
|
653
669
|
label: d.label,
|
|
654
|
-
type: d.format ?? (d.grain ? "date" : "text"),
|
|
670
|
+
type: d.person ? "person" : d.format ?? (d.grain ? "date" : "text"),
|
|
671
|
+
idKey: d.person?.idKey,
|
|
672
|
+
personKind: d.person?.kind,
|
|
655
673
|
align: "left"
|
|
656
674
|
})),
|
|
657
675
|
...(card.query.measures ?? []).map((m) => ({
|
|
@@ -667,7 +685,7 @@ function navigateAnalytics(path) {
|
|
|
667
685
|
hashRouterAdapter().navigate(path);
|
|
668
686
|
}
|
|
669
687
|
function AnalyticsSurface({ config, provider, children }) {
|
|
670
|
-
const openCard =
|
|
688
|
+
const openCard = React6__default.useCallback((card) => {
|
|
671
689
|
markViewed(card.id);
|
|
672
690
|
navigateAnalytics(`${REPORTS_BASE}/${encodeURIComponent(card.id)}`);
|
|
673
691
|
}, []);
|
|
@@ -685,6 +703,28 @@ function AnalyticsSurface({ config, provider, children }) {
|
|
|
685
703
|
}
|
|
686
704
|
) });
|
|
687
705
|
}
|
|
706
|
+
function AnalyticsAssistant() {
|
|
707
|
+
const { assistant } = useAnalyticsConfig();
|
|
708
|
+
const t = useTranslation();
|
|
709
|
+
const suggestions = React6__default.useMemo(
|
|
710
|
+
() => assistant?.suggestions ?? [0, 1, 2].map((i) => ({ label: t(`reports.assistant.suggestion.${i}`) })),
|
|
711
|
+
[assistant?.suggestions, t]
|
|
712
|
+
);
|
|
713
|
+
if (!assistant) return null;
|
|
714
|
+
return /* @__PURE__ */ jsx(
|
|
715
|
+
AssistantInvite,
|
|
716
|
+
{
|
|
717
|
+
id: "analytics",
|
|
718
|
+
auto: assistant.auto ?? false,
|
|
719
|
+
persona: assistant.persona ?? t("reports.assistant.persona"),
|
|
720
|
+
headline: assistant.headline ?? t("reports.assistant.headline"),
|
|
721
|
+
pitch: assistant.pitch ?? t("reports.assistant.pitch"),
|
|
722
|
+
description: assistant.description ?? t("reports.assistant.description"),
|
|
723
|
+
placeholder: assistant.placeholder ?? t("reports.assistant.placeholder"),
|
|
724
|
+
suggestions
|
|
725
|
+
}
|
|
726
|
+
);
|
|
727
|
+
}
|
|
688
728
|
var reportRoute = (cardId) => `${REPORTS_BASE}/${encodeURIComponent(cardId)}`;
|
|
689
729
|
function groupCards(cards) {
|
|
690
730
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -699,7 +739,7 @@ function useAnalyticsTree() {
|
|
|
699
739
|
const t = useTranslation();
|
|
700
740
|
const { labels, showLiveView } = useAnalyticsConfig();
|
|
701
741
|
const cards = useAnalyticsCards();
|
|
702
|
-
return
|
|
742
|
+
return React6__default.useMemo(() => ({
|
|
703
743
|
title: labels.analytics,
|
|
704
744
|
// Only the overview. The searchable catalogue (/analytics/reports) is still
|
|
705
745
|
// routed — bookmarks and the legacy /reports link resolve — but it is not
|
|
@@ -718,7 +758,7 @@ function AnalyticsModule({ view, cardId, children }) {
|
|
|
718
758
|
const activeId = cardId ? decodeURIComponent(cardId) : void 0;
|
|
719
759
|
const shellRail = useShellRailAvailable();
|
|
720
760
|
const claimsRail = shellRail ?? variant !== "rail";
|
|
721
|
-
const entries =
|
|
761
|
+
const entries = React6__default.useMemo(() => [
|
|
722
762
|
...tree.fixed.map((f) => ({
|
|
723
763
|
id: `analytics:${f.id}`,
|
|
724
764
|
label: f.label,
|
|
@@ -745,7 +785,7 @@ function AnalyticsModule({ view, cardId, children }) {
|
|
|
745
785
|
}] : []
|
|
746
786
|
], [tree]);
|
|
747
787
|
useContextualNav(claimsRail ? { base: ANALYTICS_BASE, entries, label: tree.title } : null);
|
|
748
|
-
const nav =
|
|
788
|
+
const nav = React6__default.useMemo(() => {
|
|
749
789
|
if (claimsRail) return [];
|
|
750
790
|
return [
|
|
751
791
|
...tree.fixed.map((f) => ({
|
|
@@ -774,7 +814,7 @@ function AnalyticsModule({ view, cardId, children }) {
|
|
|
774
814
|
}] : []
|
|
775
815
|
];
|
|
776
816
|
}, [tree, view, activeId, claimsRail]);
|
|
777
|
-
return /* @__PURE__ */
|
|
817
|
+
return /* @__PURE__ */ jsxs(
|
|
778
818
|
ModulePage,
|
|
779
819
|
{
|
|
780
820
|
title: tree.title,
|
|
@@ -782,45 +822,29 @@ function AnalyticsModule({ view, cardId, children }) {
|
|
|
782
822
|
navVariant: claimsRail ? "sidebar" : "rail",
|
|
783
823
|
showHeader: false,
|
|
784
824
|
viewKey: view === "report" ? `report:${activeId}` : view,
|
|
785
|
-
children
|
|
825
|
+
children: [
|
|
826
|
+
/* @__PURE__ */ jsx(AnalyticsAssistant, {}),
|
|
827
|
+
/* @__PURE__ */ jsx("div", { className: "md:pb-16", children })
|
|
828
|
+
]
|
|
786
829
|
}
|
|
787
830
|
);
|
|
788
831
|
}
|
|
789
832
|
function AnalyticsOverview() {
|
|
790
|
-
const { labels, showHeader
|
|
833
|
+
const { labels, showHeader } = useAnalyticsConfig();
|
|
791
834
|
const cards = useOverviewCards();
|
|
792
|
-
const filters =
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
{
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
pitch: assistant.pitch ?? t("reports.assistant.pitch"),
|
|
806
|
-
description: assistant.description ?? t("reports.assistant.description"),
|
|
807
|
-
placeholder: assistant.placeholder ?? t("reports.assistant.placeholder"),
|
|
808
|
-
suggestions
|
|
809
|
-
}
|
|
810
|
-
),
|
|
811
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
812
|
-
showHeader ? /* @__PURE__ */ jsxs("div", { children: [
|
|
813
|
-
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: labels.analytics }),
|
|
814
|
-
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: labels.overviewSubtitle })
|
|
815
|
-
] }) : null,
|
|
816
|
-
/* @__PURE__ */ jsx(AnalyticsControls, { filters, className: "sticky top-3 z-20" }),
|
|
817
|
-
cards.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center rounded-xl border border-dashed py-16 text-center", children: [
|
|
818
|
-
/* @__PURE__ */ jsx("div", { className: "mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted", children: /* @__PURE__ */ jsx(BarChart3, { className: "h-5 w-5 text-muted-foreground" }) }),
|
|
819
|
-
/* @__PURE__ */ jsx("p", { className: "font-medium", children: labels.emptyOverviewTitle }),
|
|
820
|
-
/* @__PURE__ */ jsx("p", { className: "mt-1 max-w-sm text-sm text-muted-foreground", children: labels.emptyOverviewDescription })
|
|
821
|
-
] }) : /* @__PURE__ */ jsx(AnalyticsGrid, { cards })
|
|
822
|
-
] })
|
|
823
|
-
] });
|
|
835
|
+
const filters = React6__default.useMemo(() => collectFilters(cards), [cards]);
|
|
836
|
+
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
837
|
+
showHeader ? /* @__PURE__ */ jsxs("div", { children: [
|
|
838
|
+
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: labels.analytics }),
|
|
839
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: labels.overviewSubtitle })
|
|
840
|
+
] }) : null,
|
|
841
|
+
/* @__PURE__ */ jsx(AnalyticsControls, { filters, className: "sticky top-3 z-20" }),
|
|
842
|
+
cards.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center rounded-xl border border-dashed py-16 text-center", children: [
|
|
843
|
+
/* @__PURE__ */ jsx("div", { className: "mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted", children: /* @__PURE__ */ jsx(BarChart3, { className: "h-5 w-5 text-muted-foreground" }) }),
|
|
844
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium", children: labels.emptyOverviewTitle }),
|
|
845
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 max-w-sm text-sm text-muted-foreground", children: labels.emptyOverviewDescription })
|
|
846
|
+
] }) : /* @__PURE__ */ jsx(AnalyticsGrid, { cards })
|
|
847
|
+
] }) });
|
|
824
848
|
}
|
|
825
849
|
function formatViewed(iso, locale, never) {
|
|
826
850
|
if (!iso) return never;
|
|
@@ -832,18 +856,18 @@ function ReportsListPage() {
|
|
|
832
856
|
const { labels, currency, showHeader } = useAnalyticsConfig();
|
|
833
857
|
const cards = useAnalyticsCards();
|
|
834
858
|
const lastViewed = useLastViewed();
|
|
835
|
-
const [search, setSearch] =
|
|
836
|
-
const [category, setCategory] =
|
|
837
|
-
const [author, setAuthor] =
|
|
838
|
-
const categoryOptions =
|
|
859
|
+
const [search, setSearch] = React6__default.useState("");
|
|
860
|
+
const [category, setCategory] = React6__default.useState();
|
|
861
|
+
const [author, setAuthor] = React6__default.useState();
|
|
862
|
+
const categoryOptions = React6__default.useMemo(
|
|
839
863
|
() => [...new Set(cards.map((c) => c.category))].sort((a, b) => a.localeCompare(b)).map((c) => ({ value: c, label: c })),
|
|
840
864
|
[cards]
|
|
841
865
|
);
|
|
842
|
-
const authorOptions =
|
|
866
|
+
const authorOptions = React6__default.useMemo(
|
|
843
867
|
() => [...new Set(cards.map((c) => c.createdBy ?? "\u2014"))].sort((a, b) => a.localeCompare(b)).map((a) => ({ value: a, label: a })),
|
|
844
868
|
[cards]
|
|
845
869
|
);
|
|
846
|
-
const rows =
|
|
870
|
+
const rows = React6__default.useMemo(() => {
|
|
847
871
|
const q = search.trim().toLowerCase();
|
|
848
872
|
return cards.filter((card) => {
|
|
849
873
|
if (category && card.category !== category) return false;
|
|
@@ -852,7 +876,7 @@ function ReportsListPage() {
|
|
|
852
876
|
return card.name.toLowerCase().includes(q) || card.description?.toLowerCase().includes(q) || card.category.toLowerCase().includes(q);
|
|
853
877
|
});
|
|
854
878
|
}, [cards, search, category, author]);
|
|
855
|
-
const columns =
|
|
879
|
+
const columns = React6__default.useMemo(() => [
|
|
856
880
|
{
|
|
857
881
|
id: "name",
|
|
858
882
|
accessorFn: (card) => card.name,
|
|
@@ -972,18 +996,18 @@ function ExportDropdown({ columns, data, filename, currency, title }) {
|
|
|
972
996
|
const [excelAvailable, setExcelAvailable] = useState(false);
|
|
973
997
|
const [pdfAvailable, setPdfAvailable] = useState(false);
|
|
974
998
|
useEffect(() => {
|
|
975
|
-
import('./excel-
|
|
999
|
+
import('./excel-KIJTC7OJ.js').then((m) => m.isExcelAvailable()).then(setExcelAvailable).catch(() => {
|
|
976
1000
|
});
|
|
977
|
-
import('./pdf-
|
|
1001
|
+
import('./pdf-7QQ3U5JQ.js').then((m) => m.isPdfAvailable()).then(setPdfAvailable).catch(() => {
|
|
978
1002
|
});
|
|
979
1003
|
}, []);
|
|
980
1004
|
const handleCsv = () => exportToCsv(columns, data, filename, currency);
|
|
981
1005
|
const handleExcel = async () => {
|
|
982
|
-
const { exportToExcel } = await import('./excel-
|
|
1006
|
+
const { exportToExcel } = await import('./excel-KIJTC7OJ.js');
|
|
983
1007
|
await exportToExcel(columns, data, filename, currency);
|
|
984
1008
|
};
|
|
985
1009
|
const handlePdf = async () => {
|
|
986
|
-
const { exportToPdf } = await import('./pdf-
|
|
1010
|
+
const { exportToPdf } = await import('./pdf-7QQ3U5JQ.js');
|
|
987
1011
|
await exportToPdf(columns, data, filename, { title, currency });
|
|
988
1012
|
};
|
|
989
1013
|
return /* @__PURE__ */ jsxs(Dropdown, { children: [
|
|
@@ -1051,8 +1075,8 @@ function ViewerBody({ card }) {
|
|
|
1051
1075
|
const { labels, currency } = useAnalyticsConfig();
|
|
1052
1076
|
const { state, setPage, setPageSize } = useAnalyticsContext();
|
|
1053
1077
|
const { result, loading, error, engineMissing } = useAnalyticsCard(card);
|
|
1054
|
-
const columns =
|
|
1055
|
-
const tanstackColumns =
|
|
1078
|
+
const columns = React6__default.useMemo(() => cardColumns(card), [card]);
|
|
1079
|
+
const tanstackColumns = React6__default.useMemo(
|
|
1056
1080
|
() => reportColumnsToTanstack(columns, currency.code),
|
|
1057
1081
|
[columns, currency.code]
|
|
1058
1082
|
);
|
|
@@ -1109,7 +1133,7 @@ function AnalyticsReportViewer({ cardId }) {
|
|
|
1109
1133
|
const { labels } = useAnalyticsConfig();
|
|
1110
1134
|
const cards = useAnalyticsCards();
|
|
1111
1135
|
const card = cards.find((c) => c.id === decodeURIComponent(cardId ?? ""));
|
|
1112
|
-
|
|
1136
|
+
React6__default.useEffect(() => {
|
|
1113
1137
|
if (card) markViewed(card.id);
|
|
1114
1138
|
}, [card?.id]);
|
|
1115
1139
|
if (!card) {
|
|
@@ -1146,7 +1170,7 @@ function AnalyticsReportViewer({ cardId }) {
|
|
|
1146
1170
|
function ViewerActions({ card }) {
|
|
1147
1171
|
const { currency } = useAnalyticsConfig();
|
|
1148
1172
|
const { result } = useAnalyticsCard(card);
|
|
1149
|
-
const columns =
|
|
1173
|
+
const columns = React6__default.useMemo(() => cardColumns(card), [card]);
|
|
1150
1174
|
if (!result?.rows?.length) return null;
|
|
1151
1175
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1152
1176
|
/* @__PURE__ */ jsx(
|
|
@@ -1234,7 +1258,7 @@ async function fetchViaView(reportDef, query, getClient, resolveTenantId, tenant
|
|
|
1234
1258
|
}
|
|
1235
1259
|
}
|
|
1236
1260
|
if (query.search) {
|
|
1237
|
-
const searchableCols = reportDef.columns.filter((c) => c.type === "text" || c.type === "email").map((c) => camelToSnake2(c.key));
|
|
1261
|
+
const searchableCols = reportDef.columns.filter((c) => c.type === "text" || c.type === "email" || c.type === "person").map((c) => camelToSnake2(c.key));
|
|
1238
1262
|
if (searchableCols.length > 0) {
|
|
1239
1263
|
const term = `%${query.search}%`;
|
|
1240
1264
|
const orClause = searchableCols.map((col) => `${col}.ilike.${term}`).join(",");
|
|
@@ -1349,13 +1373,13 @@ function createAnalyticsPlugin(options = {}) {
|
|
|
1349
1373
|
() => createSupabaseAnalyticsProvider({ tenantId: () => getReportsTenantId() }),
|
|
1350
1374
|
() => createMockAnalyticsProvider()
|
|
1351
1375
|
);
|
|
1352
|
-
const page2 = (Body, view) => (props) =>
|
|
1376
|
+
const page2 = (Body, view) => (props) => React6__default.createElement(
|
|
1353
1377
|
AnalyticsSurface,
|
|
1354
1378
|
{ config, provider },
|
|
1355
|
-
|
|
1379
|
+
React6__default.createElement(
|
|
1356
1380
|
AnalyticsModule,
|
|
1357
1381
|
{ view, cardId: props?.cardId },
|
|
1358
|
-
|
|
1382
|
+
React6__default.createElement(Body, props)
|
|
1359
1383
|
)
|
|
1360
1384
|
);
|
|
1361
1385
|
const READ = { feature: "reports", action: "read" };
|