@quillsql/react 2.16.101 → 2.16.102
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/index.cjs +414 -23
- package/dist/index.js +414 -23
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -23368,7 +23368,7 @@ async function fetchReportRows({
|
|
|
23368
23368
|
additionalProcessing,
|
|
23369
23369
|
overwriteCache = false
|
|
23370
23370
|
}) {
|
|
23371
|
-
const
|
|
23371
|
+
const startedAt2 = performance.now();
|
|
23372
23372
|
profileDashboard("raw-report-rows-fetch-start", { reportId });
|
|
23373
23373
|
const fetchResp = await quillFetch({
|
|
23374
23374
|
client,
|
|
@@ -23389,7 +23389,7 @@ async function fetchReportRows({
|
|
|
23389
23389
|
const resp = await parseFetchResponse(client, "report", fetchResp, getToken);
|
|
23390
23390
|
profileDashboard("raw-report-rows-fetch-finish", {
|
|
23391
23391
|
reportId,
|
|
23392
|
-
elapsedMs: Math.round(performance.now() -
|
|
23392
|
+
elapsedMs: Math.round(performance.now() - startedAt2),
|
|
23393
23393
|
rowCount: resp.rows?.length ?? 0
|
|
23394
23394
|
});
|
|
23395
23395
|
if (client.databaseType?.toLowerCase() === "bigquery") {
|
|
@@ -23427,7 +23427,7 @@ async function fetchReport({
|
|
|
23427
23427
|
}) {
|
|
23428
23428
|
let reportInfo = void 0;
|
|
23429
23429
|
let errorMessage = void 0;
|
|
23430
|
-
const
|
|
23430
|
+
const startedAt2 = performance.now();
|
|
23431
23431
|
try {
|
|
23432
23432
|
const task = usePivotTask ? "pivot-template" : useReportTask ? "report" : "item";
|
|
23433
23433
|
profileDashboard("fetch-report-start", {
|
|
@@ -23482,7 +23482,7 @@ async function fetchReport({
|
|
|
23482
23482
|
profileDashboard("fetch-report-response", {
|
|
23483
23483
|
reportId: reportId ?? null,
|
|
23484
23484
|
task,
|
|
23485
|
-
elapsedMs: Math.round(performance.now() -
|
|
23485
|
+
elapsedMs: Math.round(performance.now() - startedAt2),
|
|
23486
23486
|
hasRows: !!resp?.rows,
|
|
23487
23487
|
rowCount: resp?.rows?.length ?? 0,
|
|
23488
23488
|
hasFields: !!resp?.fields,
|
|
@@ -23507,7 +23507,7 @@ async function fetchReport({
|
|
|
23507
23507
|
profileDashboard("fetch-report-processed", {
|
|
23508
23508
|
reportId: reportId ?? null,
|
|
23509
23509
|
task,
|
|
23510
|
-
elapsedMs: Math.round(performance.now() -
|
|
23510
|
+
elapsedMs: Math.round(performance.now() - startedAt2),
|
|
23511
23511
|
rowCount: reportInfo.rows?.length ?? 0,
|
|
23512
23512
|
pivotRowCount: reportInfo.pivotRows?.length ?? 0
|
|
23513
23513
|
});
|
|
@@ -23736,6 +23736,15 @@ async function saveReport({
|
|
|
23736
23736
|
}
|
|
23737
23737
|
return data;
|
|
23738
23738
|
}
|
|
23739
|
+
function isPlainNumericCellValue(value) {
|
|
23740
|
+
if (value === null || value === void 0 || value === "") return true;
|
|
23741
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
23742
|
+
if (typeof value === "bigint") return true;
|
|
23743
|
+
if (typeof value !== "string") return false;
|
|
23744
|
+
const trimmed = value.trim();
|
|
23745
|
+
if (!trimmed) return true;
|
|
23746
|
+
return /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/i.test(trimmed);
|
|
23747
|
+
}
|
|
23739
23748
|
var formatRowsFromReport = (report, xAxisField, xAxisFormat) => {
|
|
23740
23749
|
if (!report.rows || !report.columns) {
|
|
23741
23750
|
return [];
|
|
@@ -23763,6 +23772,10 @@ var formatRowsFromReport = (report, xAxisField, xAxisFormat) => {
|
|
|
23763
23772
|
const formattedRow = {};
|
|
23764
23773
|
for (const column of resolvedColumns) {
|
|
23765
23774
|
const rawValue = row[column.field];
|
|
23775
|
+
if (NUMBER_FORMAT_TYPES.includes(String(column.format ?? "")) && !isPlainNumericCellValue(rawValue)) {
|
|
23776
|
+
formattedRow[column.field] = rawValue === null || rawValue === void 0 || rawValue === "" ? "-" : String(rawValue);
|
|
23777
|
+
continue;
|
|
23778
|
+
}
|
|
23766
23779
|
formattedRow[column.field] = column.inferFormat ? quillAutoFormat(rawValue) : getFormattedWithCache(column.format, rawValue);
|
|
23767
23780
|
}
|
|
23768
23781
|
return formattedRow;
|
|
@@ -39693,7 +39706,7 @@ var ChartDataLoader = ({
|
|
|
39693
39706
|
}
|
|
39694
39707
|
const fetchRowsRequestId = rowsRequestId.current + 1;
|
|
39695
39708
|
rowsRequestId.current = fetchRowsRequestId;
|
|
39696
|
-
const
|
|
39709
|
+
const startedAt2 = performance.now();
|
|
39697
39710
|
profileDashboard("chart-data-loader-fetch-start", {
|
|
39698
39711
|
reportId: item.id,
|
|
39699
39712
|
requestId: fetchRowsRequestId,
|
|
@@ -39839,7 +39852,7 @@ var ChartDataLoader = ({
|
|
|
39839
39852
|
reportId: item.id,
|
|
39840
39853
|
requestId: fetchRowsRequestId,
|
|
39841
39854
|
reason,
|
|
39842
|
-
elapsedMs: Math.round(performance.now() -
|
|
39855
|
+
elapsedMs: Math.round(performance.now() - startedAt2),
|
|
39843
39856
|
isLatestRequest: fetchRowsRequestId === rowsRequestId.current,
|
|
39844
39857
|
startsBackgroundFetch: !!backgroundFetch
|
|
39845
39858
|
});
|
|
@@ -62391,6 +62404,345 @@ function resolveReportFromCacheCab({
|
|
|
62391
62404
|
|
|
62392
62405
|
// src/hooks/useForm.tsx
|
|
62393
62406
|
init_dashboardProfiler();
|
|
62407
|
+
|
|
62408
|
+
// src/hooks/useReport.nanPivotDiag.ts
|
|
62409
|
+
init_valueFormatter();
|
|
62410
|
+
var NAN_PIVOT_DEBUG_FLAG = "__QUILL_DEBUG_NAN_PIVOT__";
|
|
62411
|
+
var NAN_PIVOT_LOG_FLAG = "__QUILL_NAN_PIVOT_LOG__";
|
|
62412
|
+
var startedAt = Date.now();
|
|
62413
|
+
function globalRecord() {
|
|
62414
|
+
return globalThis;
|
|
62415
|
+
}
|
|
62416
|
+
function isNanPivotDebugEnabled() {
|
|
62417
|
+
const globalValue = globalRecord()[NAN_PIVOT_DEBUG_FLAG];
|
|
62418
|
+
if (globalValue === true) return true;
|
|
62419
|
+
if (typeof process !== "undefined" && typeof process.env !== "undefined") {
|
|
62420
|
+
const envValue = String(process.env.QUILL_DEBUG_NAN_PIVOT ?? "").trim().toLowerCase();
|
|
62421
|
+
return envValue === "1" || envValue === "true";
|
|
62422
|
+
}
|
|
62423
|
+
return false;
|
|
62424
|
+
}
|
|
62425
|
+
function getNanPivotLog() {
|
|
62426
|
+
const log = globalRecord()[NAN_PIVOT_LOG_FLAG];
|
|
62427
|
+
return Array.isArray(log) ? log : [];
|
|
62428
|
+
}
|
|
62429
|
+
function findNanValues(value, path = "root") {
|
|
62430
|
+
if (typeof value === "number" && Number.isNaN(value)) {
|
|
62431
|
+
return [`${path}=NaN`];
|
|
62432
|
+
}
|
|
62433
|
+
if (typeof value === "string" && /^[-+]?NaN(?:%|\s*)$/i.test(value.trim())) {
|
|
62434
|
+
return [`${path}=${JSON.stringify(value)}`];
|
|
62435
|
+
}
|
|
62436
|
+
if (Array.isArray(value)) {
|
|
62437
|
+
return value.flatMap(
|
|
62438
|
+
(entry, index) => findNanValues(entry, `${path}[${index}]`)
|
|
62439
|
+
);
|
|
62440
|
+
}
|
|
62441
|
+
if (value && typeof value === "object") {
|
|
62442
|
+
return Object.entries(value).flatMap(
|
|
62443
|
+
([key, entry]) => findNanValues(entry, `${path}.${key}`)
|
|
62444
|
+
);
|
|
62445
|
+
}
|
|
62446
|
+
return [];
|
|
62447
|
+
}
|
|
62448
|
+
function pivotKindOf(pivot) {
|
|
62449
|
+
if (pivot == null) return "none";
|
|
62450
|
+
if (typeof pivot !== "object") return "none";
|
|
62451
|
+
const value = pivot;
|
|
62452
|
+
const rowField = String(value.rowField ?? "").trim();
|
|
62453
|
+
const columnField = String(value.columnField ?? "").trim();
|
|
62454
|
+
const hasAggregation = Array.isArray(value.aggregations) && value.aggregations.length > 0 || Boolean(String(value.aggregationType ?? "").trim());
|
|
62455
|
+
if (rowField && columnField) return "2D";
|
|
62456
|
+
if (rowField || columnField) return "1D";
|
|
62457
|
+
if (hasAggregation) return "aggregation-only";
|
|
62458
|
+
return "empty-object";
|
|
62459
|
+
}
|
|
62460
|
+
function reportDetailSurfaceOf(chart) {
|
|
62461
|
+
if (!chart || typeof chart !== "object") return "none";
|
|
62462
|
+
const value = chart;
|
|
62463
|
+
const chartType = String(value.chartType ?? "").trim().toLowerCase();
|
|
62464
|
+
if (chartType !== "table") {
|
|
62465
|
+
return "chart-display-chart";
|
|
62466
|
+
}
|
|
62467
|
+
const isPivotTable = Boolean(value.pivot) && Array.isArray(value.columns) && value.columns.length > 0;
|
|
62468
|
+
return isPivotTable ? "chart-display-pivot-table" : "flat-table";
|
|
62469
|
+
}
|
|
62470
|
+
function columnFormats(columns) {
|
|
62471
|
+
if (!Array.isArray(columns)) return [];
|
|
62472
|
+
return columns.map((column) => {
|
|
62473
|
+
const value = column ?? {};
|
|
62474
|
+
return {
|
|
62475
|
+
field: String(value.field ?? ""),
|
|
62476
|
+
label: String(value.label ?? ""),
|
|
62477
|
+
format: String(value.format ?? "")
|
|
62478
|
+
};
|
|
62479
|
+
});
|
|
62480
|
+
}
|
|
62481
|
+
function sampleRows(rows, count = 2) {
|
|
62482
|
+
return Array.isArray(rows) ? rows.slice(0, count) : [];
|
|
62483
|
+
}
|
|
62484
|
+
function hitsFor(surface, value) {
|
|
62485
|
+
return findNanValues(value).map((path) => ({ surface, path }));
|
|
62486
|
+
}
|
|
62487
|
+
function looksNumeric(value) {
|
|
62488
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
62489
|
+
if (typeof value !== "string") return false;
|
|
62490
|
+
const trimmed = value.trim();
|
|
62491
|
+
if (!trimmed) return false;
|
|
62492
|
+
return Number.isFinite(Number(trimmed.replace(/,/g, "")));
|
|
62493
|
+
}
|
|
62494
|
+
function alreadyGroupedNumberString(value) {
|
|
62495
|
+
return typeof value === "string" && /^-?\d{1,3}(?:,\d{3})+(?:\.\d+)?$/.test(value.trim());
|
|
62496
|
+
}
|
|
62497
|
+
function formatRowsAsChartDisplay(chart, rows, columns) {
|
|
62498
|
+
if (!Array.isArray(rows) || rows.length === 0) return [];
|
|
62499
|
+
const value = chart ?? {};
|
|
62500
|
+
try {
|
|
62501
|
+
return formatRowsFromReport(
|
|
62502
|
+
{
|
|
62503
|
+
...value,
|
|
62504
|
+
rows,
|
|
62505
|
+
columns: Array.isArray(columns) ? columns : [],
|
|
62506
|
+
pivot: chart?.pivot
|
|
62507
|
+
},
|
|
62508
|
+
value.xAxisField,
|
|
62509
|
+
value.xAxisFormat
|
|
62510
|
+
);
|
|
62511
|
+
} catch {
|
|
62512
|
+
return [];
|
|
62513
|
+
}
|
|
62514
|
+
}
|
|
62515
|
+
function formatMismatchesFor(columns, rows) {
|
|
62516
|
+
if (!Array.isArray(rows) || rows.length === 0) return [];
|
|
62517
|
+
const mismatches = [];
|
|
62518
|
+
for (const column of columns) {
|
|
62519
|
+
if (!NUMBER_FORMAT_TYPES.includes(column.format)) continue;
|
|
62520
|
+
for (let index = 0; index < Math.min(rows.length, 8); index += 1) {
|
|
62521
|
+
const row = rows[index];
|
|
62522
|
+
if (!row || typeof row !== "object") continue;
|
|
62523
|
+
const cell = row[column.field];
|
|
62524
|
+
if (cell == null || cell === "") continue;
|
|
62525
|
+
if (looksNumeric(cell)) continue;
|
|
62526
|
+
mismatches.push(
|
|
62527
|
+
`${column.field} format=${column.format} row[${index}]=${JSON.stringify(cell)}`
|
|
62528
|
+
);
|
|
62529
|
+
break;
|
|
62530
|
+
}
|
|
62531
|
+
}
|
|
62532
|
+
return mismatches;
|
|
62533
|
+
}
|
|
62534
|
+
function chartDisplayRows(chart) {
|
|
62535
|
+
if (!chart || typeof chart !== "object") return [];
|
|
62536
|
+
const value = chart;
|
|
62537
|
+
if (String(value.chartType ?? "").toLowerCase() !== "table") {
|
|
62538
|
+
return Array.isArray(value.rows) ? value.rows : [];
|
|
62539
|
+
}
|
|
62540
|
+
const tableColumns = value.includeCustomFields && value.columnsWithCustomFields && !value.pivot ? value.columnsWithCustomFields : value.columns ?? value.yAxisFields ?? [];
|
|
62541
|
+
try {
|
|
62542
|
+
return formatRowsFromReport(
|
|
62543
|
+
{ ...value, rows: value.rows ?? [], columns: tableColumns },
|
|
62544
|
+
value.xAxisField,
|
|
62545
|
+
value.xAxisFormat
|
|
62546
|
+
);
|
|
62547
|
+
} catch {
|
|
62548
|
+
return [];
|
|
62549
|
+
}
|
|
62550
|
+
}
|
|
62551
|
+
function pivotFieldHits(pivot) {
|
|
62552
|
+
if (!pivot || typeof pivot !== "object") return [];
|
|
62553
|
+
return hitsFor("pivotFields", {
|
|
62554
|
+
rowField: pivot.rowField,
|
|
62555
|
+
columnField: pivot.columnField,
|
|
62556
|
+
rowFieldTable: pivot.rowFieldTable,
|
|
62557
|
+
columnFieldTable: pivot.columnFieldTable
|
|
62558
|
+
});
|
|
62559
|
+
}
|
|
62560
|
+
function jsonSafe(value) {
|
|
62561
|
+
try {
|
|
62562
|
+
return JSON.parse(
|
|
62563
|
+
JSON.stringify(value, (_key, current) => {
|
|
62564
|
+
if (typeof current === "number" && Number.isNaN(current)) {
|
|
62565
|
+
return "__NaN__";
|
|
62566
|
+
}
|
|
62567
|
+
if (current === void 0) return "__undefined__";
|
|
62568
|
+
return current;
|
|
62569
|
+
})
|
|
62570
|
+
);
|
|
62571
|
+
} catch {
|
|
62572
|
+
return value;
|
|
62573
|
+
}
|
|
62574
|
+
}
|
|
62575
|
+
function snapshotUseReportNanState(input) {
|
|
62576
|
+
const chart = input.chart ?? null;
|
|
62577
|
+
const table = input.table ?? null;
|
|
62578
|
+
const sourceReport = input.sourceReport ?? null;
|
|
62579
|
+
const chartType = String(chart?.chartType ?? input.chartType ?? "").trim();
|
|
62580
|
+
const tableColumns = columnFormats(table?.columns);
|
|
62581
|
+
const chartColumns = columnFormats(chart?.columns);
|
|
62582
|
+
const tableRows = Array.isArray(table?.rows) ? table.rows : [];
|
|
62583
|
+
const chartRows = Array.isArray(chart?.rows) ? chart.rows : [];
|
|
62584
|
+
const pivotRows = Array.isArray(chart?.pivotRows) ? chart.pivotRows : [];
|
|
62585
|
+
const sourceRows = Array.isArray(sourceReport?.rows) ? sourceReport.rows : [];
|
|
62586
|
+
const sourcePivotRows = Array.isArray(sourceReport?.pivotRows) ? sourceReport.pivotRows : [];
|
|
62587
|
+
const displayRows = chartDisplayRows(chart);
|
|
62588
|
+
const doubleFormatRows = formatRowsAsChartDisplay(
|
|
62589
|
+
chart,
|
|
62590
|
+
tableRows,
|
|
62591
|
+
table?.columns ?? chart?.columns
|
|
62592
|
+
);
|
|
62593
|
+
const formPivot = input.formPivot ?? null;
|
|
62594
|
+
const nextPivot = input.nextPivot ?? null;
|
|
62595
|
+
const sourcePivot = sourceReport?.pivot ?? null;
|
|
62596
|
+
const chartPivot = chart?.pivot ?? null;
|
|
62597
|
+
const kind = pivotKindOf(chartPivot ?? nextPivot ?? formPivot ?? sourcePivot);
|
|
62598
|
+
const groupRowsBy = String(input.groupRowsBy ?? "").trim() || null;
|
|
62599
|
+
const groupColumnsBy = String(input.groupColumnsBy ?? "").trim() || null;
|
|
62600
|
+
const hasFormPivotSelection = Boolean(
|
|
62601
|
+
groupRowsBy || groupColumnsBy || Array.isArray(input.aggregations) && input.aggregations.some((value) => String(value ?? "").trim())
|
|
62602
|
+
);
|
|
62603
|
+
const unexpectedPivot = !hasFormPivotSelection && (kind === "1D" || kind === "2D" || kind === "aggregation-only" || kind === "empty-object");
|
|
62604
|
+
const nanHits = [
|
|
62605
|
+
...hitsFor("useReport.table", tableRows),
|
|
62606
|
+
...hitsFor("useReport.chart.rows", chartRows),
|
|
62607
|
+
...hitsFor("useReport.chart.pivotRows", pivotRows),
|
|
62608
|
+
...hitsFor("sourceReport.rows", sourceRows),
|
|
62609
|
+
...hitsFor("sourceReport.pivotRows", sourcePivotRows),
|
|
62610
|
+
...hitsFor("chartDisplay.formattedRows", displayRows),
|
|
62611
|
+
...hitsFor("chartDisplay.doubleFormatTableRows", doubleFormatRows),
|
|
62612
|
+
...hitsFor("columnLabels", [
|
|
62613
|
+
...tableColumns.map((column) => column.label),
|
|
62614
|
+
...chartColumns.map((column) => column.label)
|
|
62615
|
+
]),
|
|
62616
|
+
...hitsFor("columnFields", [
|
|
62617
|
+
...tableColumns.map((column) => column.field),
|
|
62618
|
+
...chartColumns.map((column) => column.field)
|
|
62619
|
+
]),
|
|
62620
|
+
...pivotFieldHits(chartPivot),
|
|
62621
|
+
...pivotFieldHits(formPivot),
|
|
62622
|
+
...pivotFieldHits(sourcePivot)
|
|
62623
|
+
];
|
|
62624
|
+
return {
|
|
62625
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
62626
|
+
atMs: Date.now() - startedAt,
|
|
62627
|
+
source: input.source ?? "useReport",
|
|
62628
|
+
flow: input.flow,
|
|
62629
|
+
step: input.step,
|
|
62630
|
+
reportId: String(input.reportId ?? ""),
|
|
62631
|
+
datasources: Array.isArray(input.datasources) ? input.datasources.map((value) => String(value)) : [],
|
|
62632
|
+
chartType,
|
|
62633
|
+
chartLoading: Boolean(input.chartLoading),
|
|
62634
|
+
tableLoading: Boolean(input.tableLoading),
|
|
62635
|
+
loading: Boolean(input.loading),
|
|
62636
|
+
groupRowsBy,
|
|
62637
|
+
groupColumnsBy,
|
|
62638
|
+
aggregations: input.aggregations ?? [],
|
|
62639
|
+
formPivot,
|
|
62640
|
+
nextPivot,
|
|
62641
|
+
sourcePivot,
|
|
62642
|
+
chartPivot,
|
|
62643
|
+
pivotKind: kind,
|
|
62644
|
+
unexpectedPivot,
|
|
62645
|
+
isPivotTableChart: Boolean(input.isPivotTableChart),
|
|
62646
|
+
reportDetailSurface: reportDetailSurfaceOf(chart),
|
|
62647
|
+
tableColumnFormats: tableColumns,
|
|
62648
|
+
chartColumnFormats: chartColumns,
|
|
62649
|
+
tableRowCount: tableRows.length,
|
|
62650
|
+
chartRowCount: chartRows.length,
|
|
62651
|
+
pivotRowCount: pivotRows.length,
|
|
62652
|
+
tableSample: sampleRows(tableRows),
|
|
62653
|
+
chartRowSample: sampleRows(chartRows),
|
|
62654
|
+
pivotRowSample: sampleRows(pivotRows),
|
|
62655
|
+
chartDisplaySample: sampleRows(displayRows),
|
|
62656
|
+
doubleFormatSample: sampleRows(doubleFormatRows),
|
|
62657
|
+
formatMismatches: [
|
|
62658
|
+
...formatMismatchesFor(tableColumns, sourceRows.length ? sourceRows : tableRows),
|
|
62659
|
+
...formatMismatchesFor(chartColumns, chartRows.length ? chartRows : pivotRows),
|
|
62660
|
+
...tableRows.flatMap((row, index) => {
|
|
62661
|
+
if (!row || typeof row !== "object") return [];
|
|
62662
|
+
return tableColumns.filter(
|
|
62663
|
+
(column) => NUMBER_FORMAT_TYPES.includes(column.format) && alreadyGroupedNumberString(
|
|
62664
|
+
row[column.field]
|
|
62665
|
+
)
|
|
62666
|
+
).map(
|
|
62667
|
+
(column) => `already-formatted ${column.field} row[${index}]=${JSON.stringify(
|
|
62668
|
+
row[column.field]
|
|
62669
|
+
)}`
|
|
62670
|
+
);
|
|
62671
|
+
})
|
|
62672
|
+
],
|
|
62673
|
+
nanHits
|
|
62674
|
+
};
|
|
62675
|
+
}
|
|
62676
|
+
var lastSerializedBySource = /* @__PURE__ */ new Map();
|
|
62677
|
+
function recordUseReportNanPivotState(input) {
|
|
62678
|
+
if (!isNanPivotDebugEnabled()) return null;
|
|
62679
|
+
const snapshot = snapshotUseReportNanState(input);
|
|
62680
|
+
const key = `${snapshot.source}:${snapshot.flow ?? ""}:${snapshot.reportId}`;
|
|
62681
|
+
const serialized = JSON.stringify(jsonSafe(snapshot));
|
|
62682
|
+
if (lastSerializedBySource.get(key) === serialized) {
|
|
62683
|
+
return snapshot;
|
|
62684
|
+
}
|
|
62685
|
+
lastSerializedBySource.set(key, serialized);
|
|
62686
|
+
const log = getNanPivotLog();
|
|
62687
|
+
log.push(snapshot);
|
|
62688
|
+
globalRecord()[NAN_PIVOT_LOG_FLAG] = log;
|
|
62689
|
+
const liveHits = snapshot.nanHits.filter(
|
|
62690
|
+
(hit) => hit.surface !== "chartDisplay.doubleFormatTableRows"
|
|
62691
|
+
);
|
|
62692
|
+
const compact = {
|
|
62693
|
+
atMs: snapshot.atMs,
|
|
62694
|
+
source: snapshot.source,
|
|
62695
|
+
flow: snapshot.flow,
|
|
62696
|
+
step: snapshot.step,
|
|
62697
|
+
reportId: snapshot.reportId,
|
|
62698
|
+
datasources: snapshot.datasources,
|
|
62699
|
+
chartType: snapshot.chartType,
|
|
62700
|
+
loading: snapshot.loading,
|
|
62701
|
+
chartLoading: snapshot.chartLoading,
|
|
62702
|
+
tableLoading: snapshot.tableLoading,
|
|
62703
|
+
groupRowsBy: snapshot.groupRowsBy,
|
|
62704
|
+
groupColumnsBy: snapshot.groupColumnsBy,
|
|
62705
|
+
pivotKind: snapshot.pivotKind,
|
|
62706
|
+
unexpectedPivot: snapshot.unexpectedPivot,
|
|
62707
|
+
isPivotTableChart: snapshot.isPivotTableChart,
|
|
62708
|
+
reportDetailSurface: snapshot.reportDetailSurface,
|
|
62709
|
+
tableRowCount: snapshot.tableRowCount,
|
|
62710
|
+
chartRowCount: snapshot.chartRowCount,
|
|
62711
|
+
pivotRowCount: snapshot.pivotRowCount,
|
|
62712
|
+
formatMismatches: snapshot.formatMismatches.slice(0, 8),
|
|
62713
|
+
nanHits: snapshot.nanHits.slice(0, 12)
|
|
62714
|
+
};
|
|
62715
|
+
if (liveHits.length > 0 || snapshot.unexpectedPivot) {
|
|
62716
|
+
console.log(
|
|
62717
|
+
"[useReport][nan-pivot][hit]",
|
|
62718
|
+
JSON.stringify(
|
|
62719
|
+
jsonSafe({
|
|
62720
|
+
...compact,
|
|
62721
|
+
tableSample: snapshot.tableSample,
|
|
62722
|
+
chartRowSample: snapshot.chartRowSample,
|
|
62723
|
+
pivotRowSample: snapshot.pivotRowSample,
|
|
62724
|
+
chartDisplaySample: snapshot.chartDisplaySample,
|
|
62725
|
+
doubleFormatSample: snapshot.doubleFormatSample,
|
|
62726
|
+
formPivot: snapshot.formPivot,
|
|
62727
|
+
chartPivot: snapshot.chartPivot,
|
|
62728
|
+
sourcePivot: snapshot.sourcePivot
|
|
62729
|
+
}),
|
|
62730
|
+
null,
|
|
62731
|
+
2
|
|
62732
|
+
)
|
|
62733
|
+
);
|
|
62734
|
+
} else if (snapshot.nanHits.length > 0) {
|
|
62735
|
+
console.log(
|
|
62736
|
+
"[useReport][nan-pivot][double-format]",
|
|
62737
|
+
JSON.stringify(compact)
|
|
62738
|
+
);
|
|
62739
|
+
} else {
|
|
62740
|
+
console.log("[useReport][nan-pivot][state]", JSON.stringify(compact));
|
|
62741
|
+
}
|
|
62742
|
+
return snapshot;
|
|
62743
|
+
}
|
|
62744
|
+
|
|
62745
|
+
// src/hooks/useForm.tsx
|
|
62394
62746
|
init_reportRequestPool();
|
|
62395
62747
|
|
|
62396
62748
|
// src/hooks/useForm.queries.ts
|
|
@@ -66598,7 +66950,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66598
66950
|
pivot,
|
|
66599
66951
|
operation
|
|
66600
66952
|
}) => {
|
|
66601
|
-
const
|
|
66953
|
+
const startedAt2 = performance.now();
|
|
66602
66954
|
const snapshot = await cacheCab.getReportSnapshot(
|
|
66603
66955
|
effectiveReportId,
|
|
66604
66956
|
tenants
|
|
@@ -66617,7 +66969,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66617
66969
|
)
|
|
66618
66970
|
});
|
|
66619
66971
|
const diagnostics = globalThis.__QUILL_CACHECAB_DIAGNOSTICS__;
|
|
66620
|
-
const durationMs = performance.now() -
|
|
66972
|
+
const durationMs = performance.now() - startedAt2;
|
|
66621
66973
|
const outcome = resolution.resolved ? "hit" : "fallback";
|
|
66622
66974
|
if (Array.isArray(diagnostics)) {
|
|
66623
66975
|
diagnostics.push({
|
|
@@ -69605,11 +69957,12 @@ function useReport(reportIdArg, options = {}) {
|
|
|
69605
69957
|
registerOption(column.field, column.label, column.format);
|
|
69606
69958
|
}
|
|
69607
69959
|
for (const yAxis2 of yAxisResolved.measures) {
|
|
69608
|
-
|
|
69960
|
+
const field = String(yAxis2.field ?? "").trim();
|
|
69961
|
+
registerOption(field, field, yAxis2.format);
|
|
69609
69962
|
if (yAxis2.format) {
|
|
69610
|
-
const existing = optionsByField.get(
|
|
69963
|
+
const existing = optionsByField.get(field);
|
|
69611
69964
|
if (existing) {
|
|
69612
|
-
optionsByField.set(
|
|
69965
|
+
optionsByField.set(field, {
|
|
69613
69966
|
...existing,
|
|
69614
69967
|
format: toAxisFormat(yAxis2.format, existing.format)
|
|
69615
69968
|
});
|
|
@@ -69686,12 +70039,17 @@ function useReport(reportIdArg, options = {}) {
|
|
|
69686
70039
|
];
|
|
69687
70040
|
}, [chartAxisOptions, yAxisResolved.measures]);
|
|
69688
70041
|
const yAxisOptions = (0, import_react63.useMemo)(
|
|
69689
|
-
() => yAxisMeasures.map((measure) =>
|
|
69690
|
-
|
|
69691
|
-
|
|
69692
|
-
|
|
69693
|
-
|
|
69694
|
-
|
|
70042
|
+
() => yAxisMeasures.map((measure) => {
|
|
70043
|
+
const field = String(measure.field ?? "").trim();
|
|
70044
|
+
const catalog = chartAxisOptionByField.get(field);
|
|
70045
|
+
if (catalog) return catalog;
|
|
70046
|
+
return {
|
|
70047
|
+
value: field,
|
|
70048
|
+
label: toTitleCaseLabel(field),
|
|
70049
|
+
format: toAxisFormat(measure.format, "string")
|
|
70050
|
+
};
|
|
70051
|
+
}),
|
|
70052
|
+
[chartAxisOptionByField, yAxisMeasures]
|
|
69695
70053
|
);
|
|
69696
70054
|
const normalizedChartYAxisOptions = (0, import_react63.useMemo)(() => {
|
|
69697
70055
|
return yAxisOptions.map((option) => ({
|
|
@@ -70031,11 +70389,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
70031
70389
|
);
|
|
70032
70390
|
const isPivotTableChart = String(chartType ?? "").toLowerCase() === "table" && Boolean(pivotState);
|
|
70033
70391
|
const pivotTableColumns = (0, import_react63.useMemo)(
|
|
70034
|
-
() => isPivotTableChart ? buildPivotTableColumns(
|
|
70035
|
-
pivotState,
|
|
70036
|
-
chart,
|
|
70037
|
-
resolveTableDisplayLabel
|
|
70038
|
-
) : null,
|
|
70392
|
+
() => isPivotTableChart ? buildPivotTableColumns(pivotState, chart, resolveTableDisplayLabel) : null,
|
|
70039
70393
|
[chart, isPivotTableChart, pivotState, resolveTableDisplayLabel]
|
|
70040
70394
|
);
|
|
70041
70395
|
const chartAxes = (0, import_react63.useMemo)(() => {
|
|
@@ -70686,6 +71040,43 @@ function useReport(reportIdArg, options = {}) {
|
|
|
70686
71040
|
tableRefreshQuery.isFetching,
|
|
70687
71041
|
tableRefreshQueryEnabled
|
|
70688
71042
|
]);
|
|
71043
|
+
(0, import_react63.useEffect)(() => {
|
|
71044
|
+
if (!isNanPivotDebugEnabled()) return;
|
|
71045
|
+
recordUseReportNanPivotState({
|
|
71046
|
+
source: "useReport",
|
|
71047
|
+
reportId: effectiveReportId,
|
|
71048
|
+
datasources,
|
|
71049
|
+
chartType: resolvedChartType,
|
|
71050
|
+
chartLoading,
|
|
71051
|
+
tableLoading,
|
|
71052
|
+
loading,
|
|
71053
|
+
groupRowsBy,
|
|
71054
|
+
groupColumnsBy,
|
|
71055
|
+
aggregations: aggregationValues,
|
|
71056
|
+
formPivot: pivotState,
|
|
71057
|
+
nextPivot,
|
|
71058
|
+
sourceReport,
|
|
71059
|
+
chart: chartWithSort,
|
|
71060
|
+
table,
|
|
71061
|
+
isPivotTableChart
|
|
71062
|
+
});
|
|
71063
|
+
}, [
|
|
71064
|
+
aggregationValues,
|
|
71065
|
+
chartLoading,
|
|
71066
|
+
chartWithSort,
|
|
71067
|
+
datasources,
|
|
71068
|
+
effectiveReportId,
|
|
71069
|
+
groupColumnsBy,
|
|
71070
|
+
groupRowsBy,
|
|
71071
|
+
isPivotTableChart,
|
|
71072
|
+
loading,
|
|
71073
|
+
nextPivot,
|
|
71074
|
+
pivotState,
|
|
71075
|
+
resolvedChartType,
|
|
71076
|
+
sourceReport,
|
|
71077
|
+
table,
|
|
71078
|
+
tableLoading
|
|
71079
|
+
]);
|
|
70689
71080
|
const buildSetReportColumnsFromIds = (nextColumnIds, settingsById) => {
|
|
70690
71081
|
const normalizedNextIds = nextColumnIds.map((columnId) => String(columnId ?? "").trim()).filter(Boolean);
|
|
70691
71082
|
return normalizedNextIds.map((columnId) => {
|
package/dist/index.js
CHANGED
|
@@ -23350,7 +23350,7 @@ async function fetchReportRows({
|
|
|
23350
23350
|
additionalProcessing,
|
|
23351
23351
|
overwriteCache = false
|
|
23352
23352
|
}) {
|
|
23353
|
-
const
|
|
23353
|
+
const startedAt2 = performance.now();
|
|
23354
23354
|
profileDashboard("raw-report-rows-fetch-start", { reportId });
|
|
23355
23355
|
const fetchResp = await quillFetch({
|
|
23356
23356
|
client,
|
|
@@ -23371,7 +23371,7 @@ async function fetchReportRows({
|
|
|
23371
23371
|
const resp = await parseFetchResponse(client, "report", fetchResp, getToken);
|
|
23372
23372
|
profileDashboard("raw-report-rows-fetch-finish", {
|
|
23373
23373
|
reportId,
|
|
23374
|
-
elapsedMs: Math.round(performance.now() -
|
|
23374
|
+
elapsedMs: Math.round(performance.now() - startedAt2),
|
|
23375
23375
|
rowCount: resp.rows?.length ?? 0
|
|
23376
23376
|
});
|
|
23377
23377
|
if (client.databaseType?.toLowerCase() === "bigquery") {
|
|
@@ -23409,7 +23409,7 @@ async function fetchReport({
|
|
|
23409
23409
|
}) {
|
|
23410
23410
|
let reportInfo = void 0;
|
|
23411
23411
|
let errorMessage = void 0;
|
|
23412
|
-
const
|
|
23412
|
+
const startedAt2 = performance.now();
|
|
23413
23413
|
try {
|
|
23414
23414
|
const task = usePivotTask ? "pivot-template" : useReportTask ? "report" : "item";
|
|
23415
23415
|
profileDashboard("fetch-report-start", {
|
|
@@ -23464,7 +23464,7 @@ async function fetchReport({
|
|
|
23464
23464
|
profileDashboard("fetch-report-response", {
|
|
23465
23465
|
reportId: reportId ?? null,
|
|
23466
23466
|
task,
|
|
23467
|
-
elapsedMs: Math.round(performance.now() -
|
|
23467
|
+
elapsedMs: Math.round(performance.now() - startedAt2),
|
|
23468
23468
|
hasRows: !!resp?.rows,
|
|
23469
23469
|
rowCount: resp?.rows?.length ?? 0,
|
|
23470
23470
|
hasFields: !!resp?.fields,
|
|
@@ -23489,7 +23489,7 @@ async function fetchReport({
|
|
|
23489
23489
|
profileDashboard("fetch-report-processed", {
|
|
23490
23490
|
reportId: reportId ?? null,
|
|
23491
23491
|
task,
|
|
23492
|
-
elapsedMs: Math.round(performance.now() -
|
|
23492
|
+
elapsedMs: Math.round(performance.now() - startedAt2),
|
|
23493
23493
|
rowCount: reportInfo.rows?.length ?? 0,
|
|
23494
23494
|
pivotRowCount: reportInfo.pivotRows?.length ?? 0
|
|
23495
23495
|
});
|
|
@@ -23718,6 +23718,15 @@ async function saveReport({
|
|
|
23718
23718
|
}
|
|
23719
23719
|
return data;
|
|
23720
23720
|
}
|
|
23721
|
+
function isPlainNumericCellValue(value) {
|
|
23722
|
+
if (value === null || value === void 0 || value === "") return true;
|
|
23723
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
23724
|
+
if (typeof value === "bigint") return true;
|
|
23725
|
+
if (typeof value !== "string") return false;
|
|
23726
|
+
const trimmed = value.trim();
|
|
23727
|
+
if (!trimmed) return true;
|
|
23728
|
+
return /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/i.test(trimmed);
|
|
23729
|
+
}
|
|
23721
23730
|
var formatRowsFromReport = (report, xAxisField, xAxisFormat) => {
|
|
23722
23731
|
if (!report.rows || !report.columns) {
|
|
23723
23732
|
return [];
|
|
@@ -23745,6 +23754,10 @@ var formatRowsFromReport = (report, xAxisField, xAxisFormat) => {
|
|
|
23745
23754
|
const formattedRow = {};
|
|
23746
23755
|
for (const column of resolvedColumns) {
|
|
23747
23756
|
const rawValue = row[column.field];
|
|
23757
|
+
if (NUMBER_FORMAT_TYPES.includes(String(column.format ?? "")) && !isPlainNumericCellValue(rawValue)) {
|
|
23758
|
+
formattedRow[column.field] = rawValue === null || rawValue === void 0 || rawValue === "" ? "-" : String(rawValue);
|
|
23759
|
+
continue;
|
|
23760
|
+
}
|
|
23748
23761
|
formattedRow[column.field] = column.inferFormat ? quillAutoFormat(rawValue) : getFormattedWithCache(column.format, rawValue);
|
|
23749
23762
|
}
|
|
23750
23763
|
return formattedRow;
|
|
@@ -39780,7 +39793,7 @@ var ChartDataLoader = ({
|
|
|
39780
39793
|
}
|
|
39781
39794
|
const fetchRowsRequestId = rowsRequestId.current + 1;
|
|
39782
39795
|
rowsRequestId.current = fetchRowsRequestId;
|
|
39783
|
-
const
|
|
39796
|
+
const startedAt2 = performance.now();
|
|
39784
39797
|
profileDashboard("chart-data-loader-fetch-start", {
|
|
39785
39798
|
reportId: item.id,
|
|
39786
39799
|
requestId: fetchRowsRequestId,
|
|
@@ -39926,7 +39939,7 @@ var ChartDataLoader = ({
|
|
|
39926
39939
|
reportId: item.id,
|
|
39927
39940
|
requestId: fetchRowsRequestId,
|
|
39928
39941
|
reason,
|
|
39929
|
-
elapsedMs: Math.round(performance.now() -
|
|
39942
|
+
elapsedMs: Math.round(performance.now() - startedAt2),
|
|
39930
39943
|
isLatestRequest: fetchRowsRequestId === rowsRequestId.current,
|
|
39931
39944
|
startsBackgroundFetch: !!backgroundFetch
|
|
39932
39945
|
});
|
|
@@ -62599,6 +62612,345 @@ function resolveReportFromCacheCab({
|
|
|
62599
62612
|
|
|
62600
62613
|
// src/hooks/useForm.tsx
|
|
62601
62614
|
init_dashboardProfiler();
|
|
62615
|
+
|
|
62616
|
+
// src/hooks/useReport.nanPivotDiag.ts
|
|
62617
|
+
init_valueFormatter();
|
|
62618
|
+
var NAN_PIVOT_DEBUG_FLAG = "__QUILL_DEBUG_NAN_PIVOT__";
|
|
62619
|
+
var NAN_PIVOT_LOG_FLAG = "__QUILL_NAN_PIVOT_LOG__";
|
|
62620
|
+
var startedAt = Date.now();
|
|
62621
|
+
function globalRecord() {
|
|
62622
|
+
return globalThis;
|
|
62623
|
+
}
|
|
62624
|
+
function isNanPivotDebugEnabled() {
|
|
62625
|
+
const globalValue = globalRecord()[NAN_PIVOT_DEBUG_FLAG];
|
|
62626
|
+
if (globalValue === true) return true;
|
|
62627
|
+
if (typeof process !== "undefined" && typeof process.env !== "undefined") {
|
|
62628
|
+
const envValue = String(process.env.QUILL_DEBUG_NAN_PIVOT ?? "").trim().toLowerCase();
|
|
62629
|
+
return envValue === "1" || envValue === "true";
|
|
62630
|
+
}
|
|
62631
|
+
return false;
|
|
62632
|
+
}
|
|
62633
|
+
function getNanPivotLog() {
|
|
62634
|
+
const log = globalRecord()[NAN_PIVOT_LOG_FLAG];
|
|
62635
|
+
return Array.isArray(log) ? log : [];
|
|
62636
|
+
}
|
|
62637
|
+
function findNanValues(value, path = "root") {
|
|
62638
|
+
if (typeof value === "number" && Number.isNaN(value)) {
|
|
62639
|
+
return [`${path}=NaN`];
|
|
62640
|
+
}
|
|
62641
|
+
if (typeof value === "string" && /^[-+]?NaN(?:%|\s*)$/i.test(value.trim())) {
|
|
62642
|
+
return [`${path}=${JSON.stringify(value)}`];
|
|
62643
|
+
}
|
|
62644
|
+
if (Array.isArray(value)) {
|
|
62645
|
+
return value.flatMap(
|
|
62646
|
+
(entry, index) => findNanValues(entry, `${path}[${index}]`)
|
|
62647
|
+
);
|
|
62648
|
+
}
|
|
62649
|
+
if (value && typeof value === "object") {
|
|
62650
|
+
return Object.entries(value).flatMap(
|
|
62651
|
+
([key, entry]) => findNanValues(entry, `${path}.${key}`)
|
|
62652
|
+
);
|
|
62653
|
+
}
|
|
62654
|
+
return [];
|
|
62655
|
+
}
|
|
62656
|
+
function pivotKindOf(pivot) {
|
|
62657
|
+
if (pivot == null) return "none";
|
|
62658
|
+
if (typeof pivot !== "object") return "none";
|
|
62659
|
+
const value = pivot;
|
|
62660
|
+
const rowField = String(value.rowField ?? "").trim();
|
|
62661
|
+
const columnField = String(value.columnField ?? "").trim();
|
|
62662
|
+
const hasAggregation = Array.isArray(value.aggregations) && value.aggregations.length > 0 || Boolean(String(value.aggregationType ?? "").trim());
|
|
62663
|
+
if (rowField && columnField) return "2D";
|
|
62664
|
+
if (rowField || columnField) return "1D";
|
|
62665
|
+
if (hasAggregation) return "aggregation-only";
|
|
62666
|
+
return "empty-object";
|
|
62667
|
+
}
|
|
62668
|
+
function reportDetailSurfaceOf(chart) {
|
|
62669
|
+
if (!chart || typeof chart !== "object") return "none";
|
|
62670
|
+
const value = chart;
|
|
62671
|
+
const chartType = String(value.chartType ?? "").trim().toLowerCase();
|
|
62672
|
+
if (chartType !== "table") {
|
|
62673
|
+
return "chart-display-chart";
|
|
62674
|
+
}
|
|
62675
|
+
const isPivotTable = Boolean(value.pivot) && Array.isArray(value.columns) && value.columns.length > 0;
|
|
62676
|
+
return isPivotTable ? "chart-display-pivot-table" : "flat-table";
|
|
62677
|
+
}
|
|
62678
|
+
function columnFormats(columns) {
|
|
62679
|
+
if (!Array.isArray(columns)) return [];
|
|
62680
|
+
return columns.map((column) => {
|
|
62681
|
+
const value = column ?? {};
|
|
62682
|
+
return {
|
|
62683
|
+
field: String(value.field ?? ""),
|
|
62684
|
+
label: String(value.label ?? ""),
|
|
62685
|
+
format: String(value.format ?? "")
|
|
62686
|
+
};
|
|
62687
|
+
});
|
|
62688
|
+
}
|
|
62689
|
+
function sampleRows(rows, count = 2) {
|
|
62690
|
+
return Array.isArray(rows) ? rows.slice(0, count) : [];
|
|
62691
|
+
}
|
|
62692
|
+
function hitsFor(surface, value) {
|
|
62693
|
+
return findNanValues(value).map((path) => ({ surface, path }));
|
|
62694
|
+
}
|
|
62695
|
+
function looksNumeric(value) {
|
|
62696
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
62697
|
+
if (typeof value !== "string") return false;
|
|
62698
|
+
const trimmed = value.trim();
|
|
62699
|
+
if (!trimmed) return false;
|
|
62700
|
+
return Number.isFinite(Number(trimmed.replace(/,/g, "")));
|
|
62701
|
+
}
|
|
62702
|
+
function alreadyGroupedNumberString(value) {
|
|
62703
|
+
return typeof value === "string" && /^-?\d{1,3}(?:,\d{3})+(?:\.\d+)?$/.test(value.trim());
|
|
62704
|
+
}
|
|
62705
|
+
function formatRowsAsChartDisplay(chart, rows, columns) {
|
|
62706
|
+
if (!Array.isArray(rows) || rows.length === 0) return [];
|
|
62707
|
+
const value = chart ?? {};
|
|
62708
|
+
try {
|
|
62709
|
+
return formatRowsFromReport(
|
|
62710
|
+
{
|
|
62711
|
+
...value,
|
|
62712
|
+
rows,
|
|
62713
|
+
columns: Array.isArray(columns) ? columns : [],
|
|
62714
|
+
pivot: chart?.pivot
|
|
62715
|
+
},
|
|
62716
|
+
value.xAxisField,
|
|
62717
|
+
value.xAxisFormat
|
|
62718
|
+
);
|
|
62719
|
+
} catch {
|
|
62720
|
+
return [];
|
|
62721
|
+
}
|
|
62722
|
+
}
|
|
62723
|
+
function formatMismatchesFor(columns, rows) {
|
|
62724
|
+
if (!Array.isArray(rows) || rows.length === 0) return [];
|
|
62725
|
+
const mismatches = [];
|
|
62726
|
+
for (const column of columns) {
|
|
62727
|
+
if (!NUMBER_FORMAT_TYPES.includes(column.format)) continue;
|
|
62728
|
+
for (let index = 0; index < Math.min(rows.length, 8); index += 1) {
|
|
62729
|
+
const row = rows[index];
|
|
62730
|
+
if (!row || typeof row !== "object") continue;
|
|
62731
|
+
const cell = row[column.field];
|
|
62732
|
+
if (cell == null || cell === "") continue;
|
|
62733
|
+
if (looksNumeric(cell)) continue;
|
|
62734
|
+
mismatches.push(
|
|
62735
|
+
`${column.field} format=${column.format} row[${index}]=${JSON.stringify(cell)}`
|
|
62736
|
+
);
|
|
62737
|
+
break;
|
|
62738
|
+
}
|
|
62739
|
+
}
|
|
62740
|
+
return mismatches;
|
|
62741
|
+
}
|
|
62742
|
+
function chartDisplayRows(chart) {
|
|
62743
|
+
if (!chart || typeof chart !== "object") return [];
|
|
62744
|
+
const value = chart;
|
|
62745
|
+
if (String(value.chartType ?? "").toLowerCase() !== "table") {
|
|
62746
|
+
return Array.isArray(value.rows) ? value.rows : [];
|
|
62747
|
+
}
|
|
62748
|
+
const tableColumns = value.includeCustomFields && value.columnsWithCustomFields && !value.pivot ? value.columnsWithCustomFields : value.columns ?? value.yAxisFields ?? [];
|
|
62749
|
+
try {
|
|
62750
|
+
return formatRowsFromReport(
|
|
62751
|
+
{ ...value, rows: value.rows ?? [], columns: tableColumns },
|
|
62752
|
+
value.xAxisField,
|
|
62753
|
+
value.xAxisFormat
|
|
62754
|
+
);
|
|
62755
|
+
} catch {
|
|
62756
|
+
return [];
|
|
62757
|
+
}
|
|
62758
|
+
}
|
|
62759
|
+
function pivotFieldHits(pivot) {
|
|
62760
|
+
if (!pivot || typeof pivot !== "object") return [];
|
|
62761
|
+
return hitsFor("pivotFields", {
|
|
62762
|
+
rowField: pivot.rowField,
|
|
62763
|
+
columnField: pivot.columnField,
|
|
62764
|
+
rowFieldTable: pivot.rowFieldTable,
|
|
62765
|
+
columnFieldTable: pivot.columnFieldTable
|
|
62766
|
+
});
|
|
62767
|
+
}
|
|
62768
|
+
function jsonSafe(value) {
|
|
62769
|
+
try {
|
|
62770
|
+
return JSON.parse(
|
|
62771
|
+
JSON.stringify(value, (_key, current) => {
|
|
62772
|
+
if (typeof current === "number" && Number.isNaN(current)) {
|
|
62773
|
+
return "__NaN__";
|
|
62774
|
+
}
|
|
62775
|
+
if (current === void 0) return "__undefined__";
|
|
62776
|
+
return current;
|
|
62777
|
+
})
|
|
62778
|
+
);
|
|
62779
|
+
} catch {
|
|
62780
|
+
return value;
|
|
62781
|
+
}
|
|
62782
|
+
}
|
|
62783
|
+
function snapshotUseReportNanState(input) {
|
|
62784
|
+
const chart = input.chart ?? null;
|
|
62785
|
+
const table = input.table ?? null;
|
|
62786
|
+
const sourceReport = input.sourceReport ?? null;
|
|
62787
|
+
const chartType = String(chart?.chartType ?? input.chartType ?? "").trim();
|
|
62788
|
+
const tableColumns = columnFormats(table?.columns);
|
|
62789
|
+
const chartColumns = columnFormats(chart?.columns);
|
|
62790
|
+
const tableRows = Array.isArray(table?.rows) ? table.rows : [];
|
|
62791
|
+
const chartRows = Array.isArray(chart?.rows) ? chart.rows : [];
|
|
62792
|
+
const pivotRows = Array.isArray(chart?.pivotRows) ? chart.pivotRows : [];
|
|
62793
|
+
const sourceRows = Array.isArray(sourceReport?.rows) ? sourceReport.rows : [];
|
|
62794
|
+
const sourcePivotRows = Array.isArray(sourceReport?.pivotRows) ? sourceReport.pivotRows : [];
|
|
62795
|
+
const displayRows = chartDisplayRows(chart);
|
|
62796
|
+
const doubleFormatRows = formatRowsAsChartDisplay(
|
|
62797
|
+
chart,
|
|
62798
|
+
tableRows,
|
|
62799
|
+
table?.columns ?? chart?.columns
|
|
62800
|
+
);
|
|
62801
|
+
const formPivot = input.formPivot ?? null;
|
|
62802
|
+
const nextPivot = input.nextPivot ?? null;
|
|
62803
|
+
const sourcePivot = sourceReport?.pivot ?? null;
|
|
62804
|
+
const chartPivot = chart?.pivot ?? null;
|
|
62805
|
+
const kind = pivotKindOf(chartPivot ?? nextPivot ?? formPivot ?? sourcePivot);
|
|
62806
|
+
const groupRowsBy = String(input.groupRowsBy ?? "").trim() || null;
|
|
62807
|
+
const groupColumnsBy = String(input.groupColumnsBy ?? "").trim() || null;
|
|
62808
|
+
const hasFormPivotSelection = Boolean(
|
|
62809
|
+
groupRowsBy || groupColumnsBy || Array.isArray(input.aggregations) && input.aggregations.some((value) => String(value ?? "").trim())
|
|
62810
|
+
);
|
|
62811
|
+
const unexpectedPivot = !hasFormPivotSelection && (kind === "1D" || kind === "2D" || kind === "aggregation-only" || kind === "empty-object");
|
|
62812
|
+
const nanHits = [
|
|
62813
|
+
...hitsFor("useReport.table", tableRows),
|
|
62814
|
+
...hitsFor("useReport.chart.rows", chartRows),
|
|
62815
|
+
...hitsFor("useReport.chart.pivotRows", pivotRows),
|
|
62816
|
+
...hitsFor("sourceReport.rows", sourceRows),
|
|
62817
|
+
...hitsFor("sourceReport.pivotRows", sourcePivotRows),
|
|
62818
|
+
...hitsFor("chartDisplay.formattedRows", displayRows),
|
|
62819
|
+
...hitsFor("chartDisplay.doubleFormatTableRows", doubleFormatRows),
|
|
62820
|
+
...hitsFor("columnLabels", [
|
|
62821
|
+
...tableColumns.map((column) => column.label),
|
|
62822
|
+
...chartColumns.map((column) => column.label)
|
|
62823
|
+
]),
|
|
62824
|
+
...hitsFor("columnFields", [
|
|
62825
|
+
...tableColumns.map((column) => column.field),
|
|
62826
|
+
...chartColumns.map((column) => column.field)
|
|
62827
|
+
]),
|
|
62828
|
+
...pivotFieldHits(chartPivot),
|
|
62829
|
+
...pivotFieldHits(formPivot),
|
|
62830
|
+
...pivotFieldHits(sourcePivot)
|
|
62831
|
+
];
|
|
62832
|
+
return {
|
|
62833
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
62834
|
+
atMs: Date.now() - startedAt,
|
|
62835
|
+
source: input.source ?? "useReport",
|
|
62836
|
+
flow: input.flow,
|
|
62837
|
+
step: input.step,
|
|
62838
|
+
reportId: String(input.reportId ?? ""),
|
|
62839
|
+
datasources: Array.isArray(input.datasources) ? input.datasources.map((value) => String(value)) : [],
|
|
62840
|
+
chartType,
|
|
62841
|
+
chartLoading: Boolean(input.chartLoading),
|
|
62842
|
+
tableLoading: Boolean(input.tableLoading),
|
|
62843
|
+
loading: Boolean(input.loading),
|
|
62844
|
+
groupRowsBy,
|
|
62845
|
+
groupColumnsBy,
|
|
62846
|
+
aggregations: input.aggregations ?? [],
|
|
62847
|
+
formPivot,
|
|
62848
|
+
nextPivot,
|
|
62849
|
+
sourcePivot,
|
|
62850
|
+
chartPivot,
|
|
62851
|
+
pivotKind: kind,
|
|
62852
|
+
unexpectedPivot,
|
|
62853
|
+
isPivotTableChart: Boolean(input.isPivotTableChart),
|
|
62854
|
+
reportDetailSurface: reportDetailSurfaceOf(chart),
|
|
62855
|
+
tableColumnFormats: tableColumns,
|
|
62856
|
+
chartColumnFormats: chartColumns,
|
|
62857
|
+
tableRowCount: tableRows.length,
|
|
62858
|
+
chartRowCount: chartRows.length,
|
|
62859
|
+
pivotRowCount: pivotRows.length,
|
|
62860
|
+
tableSample: sampleRows(tableRows),
|
|
62861
|
+
chartRowSample: sampleRows(chartRows),
|
|
62862
|
+
pivotRowSample: sampleRows(pivotRows),
|
|
62863
|
+
chartDisplaySample: sampleRows(displayRows),
|
|
62864
|
+
doubleFormatSample: sampleRows(doubleFormatRows),
|
|
62865
|
+
formatMismatches: [
|
|
62866
|
+
...formatMismatchesFor(tableColumns, sourceRows.length ? sourceRows : tableRows),
|
|
62867
|
+
...formatMismatchesFor(chartColumns, chartRows.length ? chartRows : pivotRows),
|
|
62868
|
+
...tableRows.flatMap((row, index) => {
|
|
62869
|
+
if (!row || typeof row !== "object") return [];
|
|
62870
|
+
return tableColumns.filter(
|
|
62871
|
+
(column) => NUMBER_FORMAT_TYPES.includes(column.format) && alreadyGroupedNumberString(
|
|
62872
|
+
row[column.field]
|
|
62873
|
+
)
|
|
62874
|
+
).map(
|
|
62875
|
+
(column) => `already-formatted ${column.field} row[${index}]=${JSON.stringify(
|
|
62876
|
+
row[column.field]
|
|
62877
|
+
)}`
|
|
62878
|
+
);
|
|
62879
|
+
})
|
|
62880
|
+
],
|
|
62881
|
+
nanHits
|
|
62882
|
+
};
|
|
62883
|
+
}
|
|
62884
|
+
var lastSerializedBySource = /* @__PURE__ */ new Map();
|
|
62885
|
+
function recordUseReportNanPivotState(input) {
|
|
62886
|
+
if (!isNanPivotDebugEnabled()) return null;
|
|
62887
|
+
const snapshot = snapshotUseReportNanState(input);
|
|
62888
|
+
const key = `${snapshot.source}:${snapshot.flow ?? ""}:${snapshot.reportId}`;
|
|
62889
|
+
const serialized = JSON.stringify(jsonSafe(snapshot));
|
|
62890
|
+
if (lastSerializedBySource.get(key) === serialized) {
|
|
62891
|
+
return snapshot;
|
|
62892
|
+
}
|
|
62893
|
+
lastSerializedBySource.set(key, serialized);
|
|
62894
|
+
const log = getNanPivotLog();
|
|
62895
|
+
log.push(snapshot);
|
|
62896
|
+
globalRecord()[NAN_PIVOT_LOG_FLAG] = log;
|
|
62897
|
+
const liveHits = snapshot.nanHits.filter(
|
|
62898
|
+
(hit) => hit.surface !== "chartDisplay.doubleFormatTableRows"
|
|
62899
|
+
);
|
|
62900
|
+
const compact = {
|
|
62901
|
+
atMs: snapshot.atMs,
|
|
62902
|
+
source: snapshot.source,
|
|
62903
|
+
flow: snapshot.flow,
|
|
62904
|
+
step: snapshot.step,
|
|
62905
|
+
reportId: snapshot.reportId,
|
|
62906
|
+
datasources: snapshot.datasources,
|
|
62907
|
+
chartType: snapshot.chartType,
|
|
62908
|
+
loading: snapshot.loading,
|
|
62909
|
+
chartLoading: snapshot.chartLoading,
|
|
62910
|
+
tableLoading: snapshot.tableLoading,
|
|
62911
|
+
groupRowsBy: snapshot.groupRowsBy,
|
|
62912
|
+
groupColumnsBy: snapshot.groupColumnsBy,
|
|
62913
|
+
pivotKind: snapshot.pivotKind,
|
|
62914
|
+
unexpectedPivot: snapshot.unexpectedPivot,
|
|
62915
|
+
isPivotTableChart: snapshot.isPivotTableChart,
|
|
62916
|
+
reportDetailSurface: snapshot.reportDetailSurface,
|
|
62917
|
+
tableRowCount: snapshot.tableRowCount,
|
|
62918
|
+
chartRowCount: snapshot.chartRowCount,
|
|
62919
|
+
pivotRowCount: snapshot.pivotRowCount,
|
|
62920
|
+
formatMismatches: snapshot.formatMismatches.slice(0, 8),
|
|
62921
|
+
nanHits: snapshot.nanHits.slice(0, 12)
|
|
62922
|
+
};
|
|
62923
|
+
if (liveHits.length > 0 || snapshot.unexpectedPivot) {
|
|
62924
|
+
console.log(
|
|
62925
|
+
"[useReport][nan-pivot][hit]",
|
|
62926
|
+
JSON.stringify(
|
|
62927
|
+
jsonSafe({
|
|
62928
|
+
...compact,
|
|
62929
|
+
tableSample: snapshot.tableSample,
|
|
62930
|
+
chartRowSample: snapshot.chartRowSample,
|
|
62931
|
+
pivotRowSample: snapshot.pivotRowSample,
|
|
62932
|
+
chartDisplaySample: snapshot.chartDisplaySample,
|
|
62933
|
+
doubleFormatSample: snapshot.doubleFormatSample,
|
|
62934
|
+
formPivot: snapshot.formPivot,
|
|
62935
|
+
chartPivot: snapshot.chartPivot,
|
|
62936
|
+
sourcePivot: snapshot.sourcePivot
|
|
62937
|
+
}),
|
|
62938
|
+
null,
|
|
62939
|
+
2
|
|
62940
|
+
)
|
|
62941
|
+
);
|
|
62942
|
+
} else if (snapshot.nanHits.length > 0) {
|
|
62943
|
+
console.log(
|
|
62944
|
+
"[useReport][nan-pivot][double-format]",
|
|
62945
|
+
JSON.stringify(compact)
|
|
62946
|
+
);
|
|
62947
|
+
} else {
|
|
62948
|
+
console.log("[useReport][nan-pivot][state]", JSON.stringify(compact));
|
|
62949
|
+
}
|
|
62950
|
+
return snapshot;
|
|
62951
|
+
}
|
|
62952
|
+
|
|
62953
|
+
// src/hooks/useForm.tsx
|
|
62602
62954
|
init_reportRequestPool();
|
|
62603
62955
|
|
|
62604
62956
|
// src/hooks/useForm.queries.ts
|
|
@@ -66806,7 +67158,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66806
67158
|
pivot,
|
|
66807
67159
|
operation
|
|
66808
67160
|
}) => {
|
|
66809
|
-
const
|
|
67161
|
+
const startedAt2 = performance.now();
|
|
66810
67162
|
const snapshot = await cacheCab.getReportSnapshot(
|
|
66811
67163
|
effectiveReportId,
|
|
66812
67164
|
tenants
|
|
@@ -66825,7 +67177,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66825
67177
|
)
|
|
66826
67178
|
});
|
|
66827
67179
|
const diagnostics = globalThis.__QUILL_CACHECAB_DIAGNOSTICS__;
|
|
66828
|
-
const durationMs = performance.now() -
|
|
67180
|
+
const durationMs = performance.now() - startedAt2;
|
|
66829
67181
|
const outcome = resolution.resolved ? "hit" : "fallback";
|
|
66830
67182
|
if (Array.isArray(diagnostics)) {
|
|
66831
67183
|
diagnostics.push({
|
|
@@ -69813,11 +70165,12 @@ function useReport(reportIdArg, options = {}) {
|
|
|
69813
70165
|
registerOption(column.field, column.label, column.format);
|
|
69814
70166
|
}
|
|
69815
70167
|
for (const yAxis2 of yAxisResolved.measures) {
|
|
69816
|
-
|
|
70168
|
+
const field = String(yAxis2.field ?? "").trim();
|
|
70169
|
+
registerOption(field, field, yAxis2.format);
|
|
69817
70170
|
if (yAxis2.format) {
|
|
69818
|
-
const existing = optionsByField.get(
|
|
70171
|
+
const existing = optionsByField.get(field);
|
|
69819
70172
|
if (existing) {
|
|
69820
|
-
optionsByField.set(
|
|
70173
|
+
optionsByField.set(field, {
|
|
69821
70174
|
...existing,
|
|
69822
70175
|
format: toAxisFormat(yAxis2.format, existing.format)
|
|
69823
70176
|
});
|
|
@@ -69894,12 +70247,17 @@ function useReport(reportIdArg, options = {}) {
|
|
|
69894
70247
|
];
|
|
69895
70248
|
}, [chartAxisOptions, yAxisResolved.measures]);
|
|
69896
70249
|
const yAxisOptions = useMemo33(
|
|
69897
|
-
() => yAxisMeasures.map((measure) =>
|
|
69898
|
-
|
|
69899
|
-
|
|
69900
|
-
|
|
69901
|
-
|
|
69902
|
-
|
|
70250
|
+
() => yAxisMeasures.map((measure) => {
|
|
70251
|
+
const field = String(measure.field ?? "").trim();
|
|
70252
|
+
const catalog = chartAxisOptionByField.get(field);
|
|
70253
|
+
if (catalog) return catalog;
|
|
70254
|
+
return {
|
|
70255
|
+
value: field,
|
|
70256
|
+
label: toTitleCaseLabel(field),
|
|
70257
|
+
format: toAxisFormat(measure.format, "string")
|
|
70258
|
+
};
|
|
70259
|
+
}),
|
|
70260
|
+
[chartAxisOptionByField, yAxisMeasures]
|
|
69903
70261
|
);
|
|
69904
70262
|
const normalizedChartYAxisOptions = useMemo33(() => {
|
|
69905
70263
|
return yAxisOptions.map((option) => ({
|
|
@@ -70239,11 +70597,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
70239
70597
|
);
|
|
70240
70598
|
const isPivotTableChart = String(chartType ?? "").toLowerCase() === "table" && Boolean(pivotState);
|
|
70241
70599
|
const pivotTableColumns = useMemo33(
|
|
70242
|
-
() => isPivotTableChart ? buildPivotTableColumns(
|
|
70243
|
-
pivotState,
|
|
70244
|
-
chart,
|
|
70245
|
-
resolveTableDisplayLabel
|
|
70246
|
-
) : null,
|
|
70600
|
+
() => isPivotTableChart ? buildPivotTableColumns(pivotState, chart, resolveTableDisplayLabel) : null,
|
|
70247
70601
|
[chart, isPivotTableChart, pivotState, resolveTableDisplayLabel]
|
|
70248
70602
|
);
|
|
70249
70603
|
const chartAxes = useMemo33(() => {
|
|
@@ -70894,6 +71248,43 @@ function useReport(reportIdArg, options = {}) {
|
|
|
70894
71248
|
tableRefreshQuery.isFetching,
|
|
70895
71249
|
tableRefreshQueryEnabled
|
|
70896
71250
|
]);
|
|
71251
|
+
useEffect33(() => {
|
|
71252
|
+
if (!isNanPivotDebugEnabled()) return;
|
|
71253
|
+
recordUseReportNanPivotState({
|
|
71254
|
+
source: "useReport",
|
|
71255
|
+
reportId: effectiveReportId,
|
|
71256
|
+
datasources,
|
|
71257
|
+
chartType: resolvedChartType,
|
|
71258
|
+
chartLoading,
|
|
71259
|
+
tableLoading,
|
|
71260
|
+
loading,
|
|
71261
|
+
groupRowsBy,
|
|
71262
|
+
groupColumnsBy,
|
|
71263
|
+
aggregations: aggregationValues,
|
|
71264
|
+
formPivot: pivotState,
|
|
71265
|
+
nextPivot,
|
|
71266
|
+
sourceReport,
|
|
71267
|
+
chart: chartWithSort,
|
|
71268
|
+
table,
|
|
71269
|
+
isPivotTableChart
|
|
71270
|
+
});
|
|
71271
|
+
}, [
|
|
71272
|
+
aggregationValues,
|
|
71273
|
+
chartLoading,
|
|
71274
|
+
chartWithSort,
|
|
71275
|
+
datasources,
|
|
71276
|
+
effectiveReportId,
|
|
71277
|
+
groupColumnsBy,
|
|
71278
|
+
groupRowsBy,
|
|
71279
|
+
isPivotTableChart,
|
|
71280
|
+
loading,
|
|
71281
|
+
nextPivot,
|
|
71282
|
+
pivotState,
|
|
71283
|
+
resolvedChartType,
|
|
71284
|
+
sourceReport,
|
|
71285
|
+
table,
|
|
71286
|
+
tableLoading
|
|
71287
|
+
]);
|
|
70897
71288
|
const buildSetReportColumnsFromIds = (nextColumnIds, settingsById) => {
|
|
70898
71289
|
const normalizedNextIds = nextColumnIds.map((columnId) => String(columnId ?? "").trim()).filter(Boolean);
|
|
70899
71290
|
return normalizedNextIds.map((columnId) => {
|