@quillsql/react 2.16.76 → 2.16.78
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 +2045 -771
- package/dist/index.d.cts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.js +1836 -551
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17280,7 +17280,8 @@ async function generatePivotWithSQL({
|
|
|
17280
17280
|
getToken,
|
|
17281
17281
|
reportBuilderState,
|
|
17282
17282
|
// Add reportBuilderState parameter
|
|
17283
|
-
overwriteCache = false
|
|
17283
|
+
overwriteCache = false,
|
|
17284
|
+
abortSignal
|
|
17284
17285
|
}) {
|
|
17285
17286
|
const databaseType = client.databaseType || "postgresql";
|
|
17286
17287
|
pivot = normalizeLegacyPivotSortField(pivot);
|
|
@@ -17344,7 +17345,8 @@ async function generatePivotWithSQL({
|
|
|
17344
17345
|
overwriteCache,
|
|
17345
17346
|
dateBucket: resolvedDateBucket
|
|
17346
17347
|
},
|
|
17347
|
-
getToken
|
|
17348
|
+
getToken,
|
|
17349
|
+
abortSignal
|
|
17348
17350
|
});
|
|
17349
17351
|
if (resp.data?.success === false) {
|
|
17350
17352
|
throw resp.data.errorMessage;
|
|
@@ -17354,9 +17356,7 @@ async function generatePivotWithSQL({
|
|
|
17354
17356
|
const rowCount = resp.queries?.queryResults?.[1]?.rows?.[0]?.row_count || 0;
|
|
17355
17357
|
parseValueFromBigQueryDates(queryResponseRows, queryResponseFields);
|
|
17356
17358
|
const resultRowField = processColumnName(
|
|
17357
|
-
String(
|
|
17358
|
-
resp.data?.config?.rowField ?? pivot.rowField ?? ""
|
|
17359
|
-
)
|
|
17359
|
+
String(resp.data?.config?.rowField ?? pivot.rowField ?? "")
|
|
17360
17360
|
);
|
|
17361
17361
|
const responseRows = queryResponseRows;
|
|
17362
17362
|
const responseFields = queryResponseFields;
|
|
@@ -17522,7 +17522,8 @@ async function generatePivotTable({
|
|
|
17522
17522
|
pivotQuery,
|
|
17523
17523
|
reportBuilderState,
|
|
17524
17524
|
// Add reportBuilderState parameter
|
|
17525
|
-
overwriteCache
|
|
17525
|
+
overwriteCache,
|
|
17526
|
+
abortSignal
|
|
17526
17527
|
}) {
|
|
17527
17528
|
try {
|
|
17528
17529
|
if (report && client) {
|
|
@@ -17541,11 +17542,15 @@ async function generatePivotTable({
|
|
|
17541
17542
|
getToken,
|
|
17542
17543
|
reportBuilderState,
|
|
17543
17544
|
// Pass reportBuilderState
|
|
17544
|
-
overwriteCache
|
|
17545
|
+
overwriteCache,
|
|
17546
|
+
abortSignal
|
|
17545
17547
|
});
|
|
17546
17548
|
return pivotTable;
|
|
17547
17549
|
}
|
|
17548
17550
|
} catch (e) {
|
|
17551
|
+
if (e instanceof Error && e.name === "AbortError") {
|
|
17552
|
+
throw e;
|
|
17553
|
+
}
|
|
17549
17554
|
eventTracking?.logError?.({
|
|
17550
17555
|
type: "bug",
|
|
17551
17556
|
// TODO: determine type
|
|
@@ -19912,7 +19917,7 @@ var init_tableProcessing = __esm({
|
|
|
19912
19917
|
}
|
|
19913
19918
|
return { rows, columns, rowCount, error };
|
|
19914
19919
|
};
|
|
19915
|
-
fetchTableByState = async (reportBuilderState, client, getToken, tenants, eventTracking, dashboardName, processing, customFields, rowsOnly, rowCountOnly, reportId, draftSessionId) => {
|
|
19920
|
+
fetchTableByState = async (reportBuilderState, client, getToken, tenants, eventTracking, dashboardName, processing, customFields, rowsOnly, rowCountOnly, reportId, draftSessionId, abortSignal, filters) => {
|
|
19916
19921
|
let rows = [];
|
|
19917
19922
|
let columns = [];
|
|
19918
19923
|
let rowCount;
|
|
@@ -19925,8 +19930,7 @@ var init_tableProcessing = __esm({
|
|
|
19925
19930
|
processing,
|
|
19926
19931
|
// report-builder-query reads `additionalProcessing` (same shape as /query); keep `processing` for compatibility
|
|
19927
19932
|
additionalProcessing: processing,
|
|
19928
|
-
filters
|
|
19929
|
-
// No dashboard filters for ReportBuilder table fetching
|
|
19933
|
+
filters,
|
|
19930
19934
|
dateField: void 0,
|
|
19931
19935
|
rowsOnly,
|
|
19932
19936
|
rowCountOnly,
|
|
@@ -19945,7 +19949,8 @@ var init_tableProcessing = __esm({
|
|
|
19945
19949
|
client,
|
|
19946
19950
|
task: "report-builder-query",
|
|
19947
19951
|
metadata: requestMetadata,
|
|
19948
|
-
getToken
|
|
19952
|
+
getToken,
|
|
19953
|
+
abortSignal
|
|
19949
19954
|
});
|
|
19950
19955
|
const resp = await parseFetchResponse(
|
|
19951
19956
|
client,
|
|
@@ -19979,6 +19984,9 @@ var init_tableProcessing = __esm({
|
|
|
19979
19984
|
});
|
|
19980
19985
|
}
|
|
19981
19986
|
} catch (e) {
|
|
19987
|
+
if (e instanceof Error && e.name === "AbortError") {
|
|
19988
|
+
throw e;
|
|
19989
|
+
}
|
|
19982
19990
|
eventTracking?.logError?.({
|
|
19983
19991
|
type: "bug",
|
|
19984
19992
|
// TODO: determine type
|
|
@@ -20008,8 +20016,8 @@ var init_tableProcessing = __esm({
|
|
|
20008
20016
|
function setChangelogHandler(handler) {
|
|
20009
20017
|
changelogHandler = handler;
|
|
20010
20018
|
}
|
|
20011
|
-
function notifyChangelogs(
|
|
20012
|
-
changelogHandler?.(
|
|
20019
|
+
function notifyChangelogs(entries2) {
|
|
20020
|
+
changelogHandler?.(entries2);
|
|
20013
20021
|
}
|
|
20014
20022
|
var changelogHandler;
|
|
20015
20023
|
var init_changelogNotify = __esm({
|
|
@@ -20019,6 +20027,147 @@ var init_changelogNotify = __esm({
|
|
|
20019
20027
|
}
|
|
20020
20028
|
});
|
|
20021
20029
|
|
|
20030
|
+
// src/utils/reportRequestPool.ts
|
|
20031
|
+
function createAbortError(signal) {
|
|
20032
|
+
if (signal?.reason instanceof Error) return signal.reason;
|
|
20033
|
+
return Object.assign(new Error("The operation was aborted"), {
|
|
20034
|
+
name: "AbortError"
|
|
20035
|
+
});
|
|
20036
|
+
}
|
|
20037
|
+
function stableStringify(value) {
|
|
20038
|
+
if (value === void 0) return "undefined";
|
|
20039
|
+
if (value === null || typeof value !== "object") {
|
|
20040
|
+
return JSON.stringify(value);
|
|
20041
|
+
}
|
|
20042
|
+
if (Array.isArray(value)) {
|
|
20043
|
+
return `[${value.map(stableStringify).join(",")}]`;
|
|
20044
|
+
}
|
|
20045
|
+
const object = value;
|
|
20046
|
+
return `{${Object.keys(object).filter((key) => object[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(object[key])}`).join(",")}}`;
|
|
20047
|
+
}
|
|
20048
|
+
function normalizeAdditionalProcessing(value) {
|
|
20049
|
+
if (!value || typeof value !== "object") return value ?? null;
|
|
20050
|
+
const additionalProcessing = value;
|
|
20051
|
+
const page = additionalProcessing.page;
|
|
20052
|
+
if (!page || typeof page !== "object") return additionalProcessing;
|
|
20053
|
+
const pagination = page;
|
|
20054
|
+
return {
|
|
20055
|
+
...additionalProcessing,
|
|
20056
|
+
page: {
|
|
20057
|
+
...pagination,
|
|
20058
|
+
page: pagination.page ?? 0,
|
|
20059
|
+
rowsPerPage: pagination.rowsPerPage ?? pagination.rowsPerRequest ?? void 0
|
|
20060
|
+
}
|
|
20061
|
+
};
|
|
20062
|
+
}
|
|
20063
|
+
function createSharedRequestKey({
|
|
20064
|
+
client,
|
|
20065
|
+
task,
|
|
20066
|
+
metadata,
|
|
20067
|
+
token
|
|
20068
|
+
}) {
|
|
20069
|
+
return stableStringify({
|
|
20070
|
+
endpoint: client.queryEndpoint,
|
|
20071
|
+
clientId: client.id ?? client.clientId,
|
|
20072
|
+
headers: client.queryHeaders,
|
|
20073
|
+
withCredentials: client.withCredentials,
|
|
20074
|
+
token,
|
|
20075
|
+
task,
|
|
20076
|
+
metadata: {
|
|
20077
|
+
...metadata,
|
|
20078
|
+
draftSessionId: void 0,
|
|
20079
|
+
overwriteCache: void 0,
|
|
20080
|
+
// Initial editor requests send the saved pivot/state explicitly while
|
|
20081
|
+
// dashboard requests ask the backend to resolve the same saved values.
|
|
20082
|
+
pivot: void 0,
|
|
20083
|
+
reportBuilderState: void 0,
|
|
20084
|
+
additionalProcessing: normalizeAdditionalProcessing(
|
|
20085
|
+
metadata?.additionalProcessing
|
|
20086
|
+
)
|
|
20087
|
+
}
|
|
20088
|
+
});
|
|
20089
|
+
}
|
|
20090
|
+
function cloneResult(result) {
|
|
20091
|
+
return JSON.parse(JSON.stringify(result));
|
|
20092
|
+
}
|
|
20093
|
+
async function getOrFetchSharedRequest({
|
|
20094
|
+
key,
|
|
20095
|
+
signal,
|
|
20096
|
+
fetcher
|
|
20097
|
+
}) {
|
|
20098
|
+
if (signal?.aborted) throw createAbortError(signal);
|
|
20099
|
+
let entry = entries.get(key);
|
|
20100
|
+
if (!entry) {
|
|
20101
|
+
const controller = new AbortController();
|
|
20102
|
+
entry = {
|
|
20103
|
+
controller,
|
|
20104
|
+
subscribers: 0,
|
|
20105
|
+
settled: false,
|
|
20106
|
+
promise: Promise.resolve({})
|
|
20107
|
+
};
|
|
20108
|
+
entry.promise = fetcher(controller.signal).then(
|
|
20109
|
+
(result) => {
|
|
20110
|
+
entry.settled = true;
|
|
20111
|
+
if (result.error || result.status === "error") {
|
|
20112
|
+
if (entries.get(key) === entry) entries.delete(key);
|
|
20113
|
+
return result;
|
|
20114
|
+
}
|
|
20115
|
+
entry.expiryTimer = setTimeout(() => {
|
|
20116
|
+
if (entries.get(key) === entry) entries.delete(key);
|
|
20117
|
+
}, COMPLETED_TTL_MS);
|
|
20118
|
+
return result;
|
|
20119
|
+
},
|
|
20120
|
+
(error) => {
|
|
20121
|
+
if (entries.get(key) === entry) entries.delete(key);
|
|
20122
|
+
throw error;
|
|
20123
|
+
}
|
|
20124
|
+
);
|
|
20125
|
+
entries.set(key, entry);
|
|
20126
|
+
}
|
|
20127
|
+
clearTimeout(entry.abortTimer);
|
|
20128
|
+
entry.subscribers += 1;
|
|
20129
|
+
return new Promise((resolve, reject) => {
|
|
20130
|
+
let released = false;
|
|
20131
|
+
const release = () => {
|
|
20132
|
+
if (released) return;
|
|
20133
|
+
released = true;
|
|
20134
|
+
signal?.removeEventListener("abort", onAbort);
|
|
20135
|
+
entry.subscribers -= 1;
|
|
20136
|
+
if (entry.settled || entry.subscribers > 0) return;
|
|
20137
|
+
entry.abortTimer = setTimeout(() => {
|
|
20138
|
+
if (!entry.settled && entry.subscribers === 0) {
|
|
20139
|
+
entry.controller.abort();
|
|
20140
|
+
entries.delete(key);
|
|
20141
|
+
}
|
|
20142
|
+
}, ORPHAN_GRACE_MS);
|
|
20143
|
+
};
|
|
20144
|
+
const onAbort = () => {
|
|
20145
|
+
release();
|
|
20146
|
+
reject(createAbortError(signal));
|
|
20147
|
+
};
|
|
20148
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
20149
|
+
entry.promise.then(
|
|
20150
|
+
(result) => {
|
|
20151
|
+
release();
|
|
20152
|
+
resolve(cloneResult(result));
|
|
20153
|
+
},
|
|
20154
|
+
(error) => {
|
|
20155
|
+
release();
|
|
20156
|
+
reject(error);
|
|
20157
|
+
}
|
|
20158
|
+
);
|
|
20159
|
+
});
|
|
20160
|
+
}
|
|
20161
|
+
var ORPHAN_GRACE_MS, COMPLETED_TTL_MS, entries;
|
|
20162
|
+
var init_reportRequestPool = __esm({
|
|
20163
|
+
"src/utils/reportRequestPool.ts"() {
|
|
20164
|
+
"use strict";
|
|
20165
|
+
ORPHAN_GRACE_MS = 100;
|
|
20166
|
+
COMPLETED_TTL_MS = 15e3;
|
|
20167
|
+
entries = /* @__PURE__ */ new Map();
|
|
20168
|
+
}
|
|
20169
|
+
});
|
|
20170
|
+
|
|
20022
20171
|
// src/utils/dataFetcher.tsx
|
|
20023
20172
|
var dataFetcher_exports = {};
|
|
20024
20173
|
__export(dataFetcher_exports, {
|
|
@@ -20491,7 +20640,7 @@ async function fetchSqlQueryFromState(reportBuilderState, client, getToken, data
|
|
|
20491
20640
|
return { query: "", error: `Failed to generate query: ${error.message}` };
|
|
20492
20641
|
}
|
|
20493
20642
|
}
|
|
20494
|
-
async function fetchQueryDateRangesFromState(reportBuilderState, columns, client, getToken, databaseType, tenants, customFields, dashboardName, eventTracking) {
|
|
20643
|
+
async function fetchQueryDateRangesFromState(reportBuilderState, columns, client, getToken, databaseType, tenants, customFields, dashboardName, eventTracking, abortSignal) {
|
|
20495
20644
|
try {
|
|
20496
20645
|
const { data } = await quillFetch({
|
|
20497
20646
|
client,
|
|
@@ -20505,7 +20654,8 @@ async function fetchQueryDateRangesFromState(reportBuilderState, columns, client
|
|
|
20505
20654
|
customFields,
|
|
20506
20655
|
dashboardName
|
|
20507
20656
|
},
|
|
20508
|
-
getToken
|
|
20657
|
+
getToken,
|
|
20658
|
+
abortSignal
|
|
20509
20659
|
});
|
|
20510
20660
|
if (!data || !data.rows) {
|
|
20511
20661
|
return null;
|
|
@@ -20525,11 +20675,17 @@ async function fetchQueryDateRangesFromState(reportBuilderState, columns, client
|
|
|
20525
20675
|
);
|
|
20526
20676
|
return results;
|
|
20527
20677
|
} catch (error) {
|
|
20678
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
20679
|
+
throw error;
|
|
20680
|
+
}
|
|
20528
20681
|
return null;
|
|
20529
20682
|
}
|
|
20530
20683
|
}
|
|
20531
|
-
async function fetchRelevantInfoFromState(reportBuilderState, tables, columns, aliasedColumns, reportBuilderColumns, client, getToken, databaseType, tenants, customFields, dashboardName, eventTracking) {
|
|
20684
|
+
async function fetchRelevantInfoFromState(reportBuilderState, tables, columns, aliasedColumns, reportBuilderColumns, client, getToken, databaseType, tenants, customFields, dashboardName, eventTracking, abortSignal) {
|
|
20532
20685
|
try {
|
|
20686
|
+
if (abortSignal?.aborted) {
|
|
20687
|
+
throw new DOMException("Aborted", "AbortError");
|
|
20688
|
+
}
|
|
20533
20689
|
const result = await getRelevantInfoFromQuery({
|
|
20534
20690
|
tables,
|
|
20535
20691
|
columns,
|
|
@@ -20552,6 +20708,9 @@ async function fetchRelevantInfoFromState(reportBuilderState, tables, columns, a
|
|
|
20552
20708
|
error: result.error
|
|
20553
20709
|
};
|
|
20554
20710
|
} catch (error) {
|
|
20711
|
+
if (abortSignal?.aborted || error instanceof Error && error.name === "AbortError") {
|
|
20712
|
+
throw error;
|
|
20713
|
+
}
|
|
20555
20714
|
return { error: error.message };
|
|
20556
20715
|
}
|
|
20557
20716
|
}
|
|
@@ -20564,6 +20723,7 @@ var init_dataFetcher = __esm({
|
|
|
20564
20723
|
init_tableProcessing();
|
|
20565
20724
|
init_dates();
|
|
20566
20725
|
init_changelogNotify();
|
|
20726
|
+
init_reportRequestPool();
|
|
20567
20727
|
quillFetch = async ({
|
|
20568
20728
|
client,
|
|
20569
20729
|
task,
|
|
@@ -20572,55 +20732,67 @@ var init_dataFetcher = __esm({
|
|
|
20572
20732
|
abortSignal,
|
|
20573
20733
|
credentials = "omit",
|
|
20574
20734
|
urlParameters,
|
|
20735
|
+
shareRequest = false,
|
|
20575
20736
|
getToken
|
|
20576
20737
|
}) => {
|
|
20577
|
-
const token = await getToken();
|
|
20578
20738
|
const queryString = urlParameters ?? `task=${task}`;
|
|
20579
20739
|
const endpoint = client.queryEndpoint ? `${client.queryEndpoint}?${queryString}` : `${QUILL_SERVER}${QUILL_QUERY_ENDPOINT}?${queryString}`;
|
|
20580
|
-
|
|
20581
|
-
const
|
|
20582
|
-
|
|
20583
|
-
|
|
20584
|
-
|
|
20585
|
-
|
|
20586
|
-
|
|
20587
|
-
|
|
20588
|
-
|
|
20589
|
-
|
|
20590
|
-
|
|
20591
|
-
|
|
20592
|
-
|
|
20593
|
-
|
|
20594
|
-
|
|
20595
|
-
|
|
20596
|
-
|
|
20597
|
-
|
|
20598
|
-
|
|
20599
|
-
|
|
20600
|
-
|
|
20601
|
-
|
|
20602
|
-
|
|
20603
|
-
result =
|
|
20604
|
-
|
|
20605
|
-
|
|
20606
|
-
|
|
20607
|
-
|
|
20608
|
-
|
|
20609
|
-
|
|
20610
|
-
|
|
20611
|
-
|
|
20612
|
-
|
|
20613
|
-
|
|
20614
|
-
|
|
20615
|
-
|
|
20616
|
-
|
|
20617
|
-
|
|
20618
|
-
|
|
20619
|
-
|
|
20620
|
-
|
|
20740
|
+
const execute = async (signal, resolvedToken) => {
|
|
20741
|
+
const token2 = resolvedToken ?? await getToken();
|
|
20742
|
+
try {
|
|
20743
|
+
const response = await fetch(endpoint, {
|
|
20744
|
+
method,
|
|
20745
|
+
headers: {
|
|
20746
|
+
...token2 ? { Authorization: `Bearer ${token2}` } : {},
|
|
20747
|
+
...client.queryHeaders,
|
|
20748
|
+
"Content-Type": "application/json"
|
|
20749
|
+
},
|
|
20750
|
+
body: JSON.stringify({
|
|
20751
|
+
metadata: {
|
|
20752
|
+
task,
|
|
20753
|
+
clientId: client.id ?? client.clientId,
|
|
20754
|
+
...metadata
|
|
20755
|
+
}
|
|
20756
|
+
}),
|
|
20757
|
+
credentials: client.withCredentials ? "include" : credentials,
|
|
20758
|
+
signal
|
|
20759
|
+
});
|
|
20760
|
+
if (!response.ok) {
|
|
20761
|
+
throw new Error("API request failed");
|
|
20762
|
+
}
|
|
20763
|
+
let result = await response.json();
|
|
20764
|
+
if (result.data?.data && (result.data.queries || result.data.status || result.data.error)) {
|
|
20765
|
+
result = result.data;
|
|
20766
|
+
}
|
|
20767
|
+
const normalizedData = normalizeChangelogData(result.data);
|
|
20768
|
+
if (task !== "fetch-changelog-list" && Array.isArray(normalizedData?.changelogs)) {
|
|
20769
|
+
notifyChangelogs(normalizedData.changelogs);
|
|
20770
|
+
}
|
|
20771
|
+
return {
|
|
20772
|
+
data: normalizedData,
|
|
20773
|
+
queries: result.queries,
|
|
20774
|
+
status: result.status,
|
|
20775
|
+
error: result.error
|
|
20776
|
+
};
|
|
20777
|
+
} catch (e) {
|
|
20778
|
+
if (e instanceof Error && e.name === "AbortError") {
|
|
20779
|
+
throw e;
|
|
20780
|
+
}
|
|
20781
|
+
if (task !== "set-section-order") {
|
|
20782
|
+
console.error("Failed to fetch:", e);
|
|
20783
|
+
}
|
|
20784
|
+
return { error: "Failed to fetch data" };
|
|
20621
20785
|
}
|
|
20622
|
-
|
|
20786
|
+
};
|
|
20787
|
+
if (!shareRequest) {
|
|
20788
|
+
return execute(abortSignal);
|
|
20623
20789
|
}
|
|
20790
|
+
const token = await getToken();
|
|
20791
|
+
return getOrFetchSharedRequest({
|
|
20792
|
+
key: createSharedRequestKey({ client, task, metadata, token }),
|
|
20793
|
+
signal: abortSignal,
|
|
20794
|
+
fetcher: (signal) => execute(signal, token)
|
|
20795
|
+
});
|
|
20624
20796
|
};
|
|
20625
20797
|
parseFetchResponse = async (client, task, response, getToken, useInMemory = false) => {
|
|
20626
20798
|
try {
|
|
@@ -21929,13 +22101,15 @@ async function requestPivotTemplateTask({
|
|
|
21929
22101
|
client,
|
|
21930
22102
|
metadata,
|
|
21931
22103
|
getToken,
|
|
21932
|
-
abortSignal
|
|
22104
|
+
abortSignal,
|
|
22105
|
+
shareRequest = false
|
|
21933
22106
|
}) {
|
|
21934
22107
|
return quillFetch({
|
|
21935
22108
|
client,
|
|
21936
22109
|
task: "pivot-template",
|
|
21937
22110
|
metadata,
|
|
21938
22111
|
abortSignal,
|
|
22112
|
+
shareRequest,
|
|
21939
22113
|
getToken
|
|
21940
22114
|
});
|
|
21941
22115
|
}
|
|
@@ -22103,7 +22277,8 @@ async function fetchPivotTemplateReportForUseForm({
|
|
|
22103
22277
|
abortSignal,
|
|
22104
22278
|
baseReport,
|
|
22105
22279
|
responseSelection,
|
|
22106
|
-
draftSessionId
|
|
22280
|
+
draftSessionId,
|
|
22281
|
+
shareRequest = false
|
|
22107
22282
|
}) {
|
|
22108
22283
|
let fetchStep = "create-metadata";
|
|
22109
22284
|
try {
|
|
@@ -22125,7 +22300,8 @@ async function fetchPivotTemplateReportForUseForm({
|
|
|
22125
22300
|
client,
|
|
22126
22301
|
metadata,
|
|
22127
22302
|
getToken,
|
|
22128
|
-
abortSignal
|
|
22303
|
+
abortSignal,
|
|
22304
|
+
shareRequest
|
|
22129
22305
|
});
|
|
22130
22306
|
fetchStep = "parse-task-response";
|
|
22131
22307
|
const parsedResponse = await parsePivotTemplateTaskResponse({
|
|
@@ -22276,7 +22452,8 @@ async function fetchReport({
|
|
|
22276
22452
|
pivot,
|
|
22277
22453
|
reportBuilderState,
|
|
22278
22454
|
skipPivotFetch,
|
|
22279
|
-
draftSessionId
|
|
22455
|
+
draftSessionId,
|
|
22456
|
+
shareRequest = false
|
|
22280
22457
|
}) {
|
|
22281
22458
|
let reportInfo = void 0;
|
|
22282
22459
|
let errorMessage = void 0;
|
|
@@ -22320,6 +22497,7 @@ async function fetchReport({
|
|
|
22320
22497
|
...resolvedDateBucket ? { dateBucket: resolvedDateBucket } : {}
|
|
22321
22498
|
},
|
|
22322
22499
|
abortSignal,
|
|
22500
|
+
shareRequest,
|
|
22323
22501
|
getToken
|
|
22324
22502
|
});
|
|
22325
22503
|
const resp = await parseFetchResponse(client, task, fetchResp, getToken);
|
|
@@ -22987,7 +23165,8 @@ var fetchReportBuilderDataFromState = async ({
|
|
|
22987
23165
|
dashboardName,
|
|
22988
23166
|
getToken,
|
|
22989
23167
|
eventTracking,
|
|
22990
|
-
draftSessionId
|
|
23168
|
+
draftSessionId,
|
|
23169
|
+
abortSignal
|
|
22991
23170
|
}) => {
|
|
22992
23171
|
let newRows = [];
|
|
22993
23172
|
let newColumns = [];
|
|
@@ -23061,7 +23240,8 @@ var fetchReportBuilderDataFromState = async ({
|
|
|
23061
23240
|
skipRowCount,
|
|
23062
23241
|
rowCountOnly,
|
|
23063
23242
|
curReport?.id ? String(curReport.id).trim() : void 0,
|
|
23064
|
-
draftSessionId ? String(draftSessionId).trim() : void 0
|
|
23243
|
+
draftSessionId ? String(draftSessionId).trim() : void 0,
|
|
23244
|
+
abortSignal
|
|
23065
23245
|
);
|
|
23066
23246
|
if (tableData.error) {
|
|
23067
23247
|
throw new Error(tableData.error);
|
|
@@ -23116,7 +23296,9 @@ var fetchReportBuilderDataFromState = async ({
|
|
|
23116
23296
|
client.databaseType?.toLowerCase() || "postgresql",
|
|
23117
23297
|
tenants,
|
|
23118
23298
|
customFields,
|
|
23119
|
-
dashboardName
|
|
23299
|
+
dashboardName,
|
|
23300
|
+
void 0,
|
|
23301
|
+
abortSignal
|
|
23120
23302
|
);
|
|
23121
23303
|
const uniqueStrings = uniqueStringsByTable;
|
|
23122
23304
|
const columnUniqueValues = uniqueStringsByColumn;
|
|
@@ -23136,7 +23318,9 @@ var fetchReportBuilderDataFromState = async ({
|
|
|
23136
23318
|
client.databaseType?.toLowerCase() || "postgresql",
|
|
23137
23319
|
tenants,
|
|
23138
23320
|
customFields ?? [],
|
|
23139
|
-
dashboardName
|
|
23321
|
+
dashboardName,
|
|
23322
|
+
void 0,
|
|
23323
|
+
abortSignal
|
|
23140
23324
|
);
|
|
23141
23325
|
if (dateRanges === null) {
|
|
23142
23326
|
throw new Error("Couldn't fetch date ranges");
|
|
@@ -23186,8 +23370,9 @@ var fetchReportBuilderDataFromState = async ({
|
|
|
23186
23370
|
getToken,
|
|
23187
23371
|
pivotQuery: skipPivotColumnFetch ? curReport?.pivotQuery : void 0,
|
|
23188
23372
|
eventTracking,
|
|
23189
|
-
reportBuilderState
|
|
23373
|
+
reportBuilderState,
|
|
23190
23374
|
// Pass reportBuilderState for ReportBuilder context
|
|
23375
|
+
abortSignal
|
|
23191
23376
|
});
|
|
23192
23377
|
newPivot = pivot;
|
|
23193
23378
|
}
|
|
@@ -23213,6 +23398,9 @@ var fetchReportBuilderDataFromState = async ({
|
|
|
23213
23398
|
newRows = tableData.rows;
|
|
23214
23399
|
newColumns = tableData.columns;
|
|
23215
23400
|
} catch (e) {
|
|
23401
|
+
if (e instanceof Error && e.name === "AbortError") {
|
|
23402
|
+
throw e;
|
|
23403
|
+
}
|
|
23216
23404
|
eventTracking?.logError?.({
|
|
23217
23405
|
type: "bug",
|
|
23218
23406
|
// TODO: determine type
|
|
@@ -24166,15 +24354,226 @@ var applyFiltersInMemory = (rows, filters, options) => {
|
|
|
24166
24354
|
// src/utils/cacheCab.ts
|
|
24167
24355
|
init_inMemoryPivotEngine();
|
|
24168
24356
|
import { openDB } from "idb";
|
|
24169
|
-
import {
|
|
24357
|
+
import {
|
|
24358
|
+
endOfDay as endOfDay3,
|
|
24359
|
+
max as maxDate,
|
|
24360
|
+
subMonths as subMonths4,
|
|
24361
|
+
min as minDate,
|
|
24362
|
+
startOfDay as startOfDay4
|
|
24363
|
+
} from "date-fns";
|
|
24170
24364
|
import { utcToZonedTime as utcToZonedTime2, zonedTimeToUtc } from "date-fns-tz";
|
|
24365
|
+
|
|
24366
|
+
// src/utils/cloudCacheValidation.ts
|
|
24367
|
+
var LIMIT_CLAUSE_REGEX = /^limit\b\s+(?:all|\d+|\$\d+|:[a-zA-Z_][a-zA-Z0-9_]*|\?)/i;
|
|
24368
|
+
var SQL_CONTENT_TO_IGNORE_REGEX = /'(?:''|[^'])*'|"(?:[^"]|"")*"|`[^`]*`|\[[^\]]*\]|--[^\n]*|\/\*[\s\S]*?\*\//g;
|
|
24369
|
+
function isWordChar(char) {
|
|
24370
|
+
if (!char) {
|
|
24371
|
+
return false;
|
|
24372
|
+
}
|
|
24373
|
+
return /[A-Za-z0-9_]/.test(char);
|
|
24374
|
+
}
|
|
24375
|
+
function getFinalSqlStatement(query) {
|
|
24376
|
+
const statements = query.split(";").map((statement) => statement.trim()).filter((statement) => statement.length > 0);
|
|
24377
|
+
return statements[statements.length - 1] ?? "";
|
|
24378
|
+
}
|
|
24379
|
+
function hasTopLevelLimitClause(statement) {
|
|
24380
|
+
let depth = 0;
|
|
24381
|
+
for (let i = 0; i < statement.length; i += 1) {
|
|
24382
|
+
const char = statement[i];
|
|
24383
|
+
if (char === "(") {
|
|
24384
|
+
depth += 1;
|
|
24385
|
+
continue;
|
|
24386
|
+
}
|
|
24387
|
+
if (char === ")") {
|
|
24388
|
+
depth = Math.max(0, depth - 1);
|
|
24389
|
+
continue;
|
|
24390
|
+
}
|
|
24391
|
+
if (depth !== 0) {
|
|
24392
|
+
continue;
|
|
24393
|
+
}
|
|
24394
|
+
const previousChar = i > 0 ? statement[i - 1] : void 0;
|
|
24395
|
+
if (isWordChar(previousChar)) {
|
|
24396
|
+
continue;
|
|
24397
|
+
}
|
|
24398
|
+
if (!LIMIT_CLAUSE_REGEX.test(statement.slice(i))) {
|
|
24399
|
+
continue;
|
|
24400
|
+
}
|
|
24401
|
+
return true;
|
|
24402
|
+
}
|
|
24403
|
+
return false;
|
|
24404
|
+
}
|
|
24405
|
+
function unwrapIdentifier(identifier) {
|
|
24406
|
+
if (!identifier) {
|
|
24407
|
+
return "";
|
|
24408
|
+
}
|
|
24409
|
+
const trimmed = identifier.trim();
|
|
24410
|
+
if (trimmed.length < 2) {
|
|
24411
|
+
return trimmed;
|
|
24412
|
+
}
|
|
24413
|
+
const startsAndEndsWithDoubleQuote = trimmed.startsWith('"') && trimmed.endsWith('"');
|
|
24414
|
+
const startsAndEndsWithSingleQuote = trimmed.startsWith("'") && trimmed.endsWith("'");
|
|
24415
|
+
const startsAndEndsWithBackticks = trimmed.startsWith("`") && trimmed.endsWith("`");
|
|
24416
|
+
const startsAndEndsWithBrackets = trimmed.startsWith("[") && trimmed.endsWith("]");
|
|
24417
|
+
if (startsAndEndsWithDoubleQuote || startsAndEndsWithSingleQuote || startsAndEndsWithBackticks || startsAndEndsWithBrackets) {
|
|
24418
|
+
return trimmed.slice(1, -1);
|
|
24419
|
+
}
|
|
24420
|
+
return trimmed;
|
|
24421
|
+
}
|
|
24422
|
+
function normalizeIdentifier(identifier) {
|
|
24423
|
+
return unwrapIdentifier(identifier).toLowerCase();
|
|
24424
|
+
}
|
|
24425
|
+
function hasRowFieldWithIdentifier(row, normalizedField) {
|
|
24426
|
+
if (!row || !normalizedField) {
|
|
24427
|
+
return false;
|
|
24428
|
+
}
|
|
24429
|
+
return Object.keys(row).some(
|
|
24430
|
+
(fieldName) => normalizeIdentifier(fieldName) === normalizedField
|
|
24431
|
+
);
|
|
24432
|
+
}
|
|
24433
|
+
function reportReferencesField(report, field, table) {
|
|
24434
|
+
const normalizedField = normalizeIdentifier(field);
|
|
24435
|
+
if (!normalizedField) {
|
|
24436
|
+
return false;
|
|
24437
|
+
}
|
|
24438
|
+
const referencedColumns = report?.referencedColumns ?? {};
|
|
24439
|
+
let entries2 = Object.entries(referencedColumns);
|
|
24440
|
+
if (entries2.length === 0) {
|
|
24441
|
+
return false;
|
|
24442
|
+
}
|
|
24443
|
+
const normalizedTable = normalizeIdentifier(table);
|
|
24444
|
+
if (normalizedTable) {
|
|
24445
|
+
entries2 = entries2.filter(
|
|
24446
|
+
([tableName]) => normalizeIdentifier(tableName) === normalizedTable
|
|
24447
|
+
);
|
|
24448
|
+
}
|
|
24449
|
+
const referencedFields = entries2.flatMap(([, fields]) => fields ?? []);
|
|
24450
|
+
if (referencedFields.length === 0) {
|
|
24451
|
+
return false;
|
|
24452
|
+
}
|
|
24453
|
+
return referencedFields.some((referencedField) => {
|
|
24454
|
+
const normalizedReferencedField = normalizeIdentifier(referencedField);
|
|
24455
|
+
return normalizedReferencedField === normalizedField || normalizedReferencedField === "*";
|
|
24456
|
+
});
|
|
24457
|
+
}
|
|
24458
|
+
function isDateFieldMissingInReport(report) {
|
|
24459
|
+
if (!report?.dateField?.field || !report.dateField.table) {
|
|
24460
|
+
return false;
|
|
24461
|
+
}
|
|
24462
|
+
const dateField = report.dateField;
|
|
24463
|
+
if (!reportReferencesField(report, dateField.field, dateField.table)) {
|
|
24464
|
+
return true;
|
|
24465
|
+
}
|
|
24466
|
+
const firstRow = report.rows?.[0];
|
|
24467
|
+
if (!firstRow) {
|
|
24468
|
+
return false;
|
|
24469
|
+
}
|
|
24470
|
+
const normalizedDateField = normalizeIdentifier(dateField.field);
|
|
24471
|
+
const dateFieldExistsInFirstRow = hasRowFieldWithIdentifier(
|
|
24472
|
+
firstRow,
|
|
24473
|
+
normalizedDateField
|
|
24474
|
+
);
|
|
24475
|
+
return !dateFieldExistsInFirstRow;
|
|
24476
|
+
}
|
|
24477
|
+
function hasLimitClause(query) {
|
|
24478
|
+
if (!query) {
|
|
24479
|
+
return false;
|
|
24480
|
+
}
|
|
24481
|
+
const sanitizedQuery = query.replace(SQL_CONTENT_TO_IGNORE_REGEX, " ");
|
|
24482
|
+
const finalStatement = getFinalSqlStatement(sanitizedQuery);
|
|
24483
|
+
if (!finalStatement) {
|
|
24484
|
+
return false;
|
|
24485
|
+
}
|
|
24486
|
+
return hasTopLevelLimitClause(finalStatement);
|
|
24487
|
+
}
|
|
24488
|
+
function reportUsesLimitClause(report) {
|
|
24489
|
+
const queriesToInspect = report?.itemQuery && report.itemQuery.length > 0 ? report.itemQuery : report?.queryString ? [report.queryString] : [];
|
|
24490
|
+
return queriesToInspect.some(hasLimitClause);
|
|
24491
|
+
}
|
|
24492
|
+
function getMissingDashboardFilterFields({
|
|
24493
|
+
rows = [],
|
|
24494
|
+
dashboardFilters = []
|
|
24495
|
+
}) {
|
|
24496
|
+
const dateIndex = dashboardFilters.findIndex(
|
|
24497
|
+
(filter) => filter.filterType === "date_range"
|
|
24498
|
+
);
|
|
24499
|
+
const requiredFields = dashboardFilters.flatMap((filter, index) => {
|
|
24500
|
+
if (index === dateIndex || !filter.field) {
|
|
24501
|
+
return [];
|
|
24502
|
+
}
|
|
24503
|
+
const normalizedField = normalizeIdentifier(filter.field);
|
|
24504
|
+
if (!normalizedField) {
|
|
24505
|
+
return [];
|
|
24506
|
+
}
|
|
24507
|
+
return [
|
|
24508
|
+
{
|
|
24509
|
+
displayField: unwrapIdentifier(filter.field),
|
|
24510
|
+
normalizedField
|
|
24511
|
+
}
|
|
24512
|
+
];
|
|
24513
|
+
});
|
|
24514
|
+
const dedupedRequiredFields = requiredFields.filter(
|
|
24515
|
+
(field, index, fields) => fields.findIndex(
|
|
24516
|
+
(candidate) => candidate.normalizedField === field.normalizedField
|
|
24517
|
+
) === index
|
|
24518
|
+
);
|
|
24519
|
+
return dedupedRequiredFields.filter(
|
|
24520
|
+
({ normalizedField }) => rows.some((row) => !hasRowFieldWithIdentifier(row, normalizedField))
|
|
24521
|
+
).map(({ displayField }) => displayField);
|
|
24522
|
+
}
|
|
24523
|
+
|
|
24524
|
+
// src/utils/cacheCab.ts
|
|
24525
|
+
init_tableProcessing();
|
|
24526
|
+
|
|
24527
|
+
// src/utils/cacheCabSource.ts
|
|
24528
|
+
var stableStringify2 = (value) => {
|
|
24529
|
+
if (value === null || typeof value !== "object") {
|
|
24530
|
+
return JSON.stringify(value);
|
|
24531
|
+
}
|
|
24532
|
+
if (Array.isArray(value)) {
|
|
24533
|
+
return `[${value.map(stableStringify2).join(",")}]`;
|
|
24534
|
+
}
|
|
24535
|
+
const object = value;
|
|
24536
|
+
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify2(object[key])}`).join(",")}}`;
|
|
24537
|
+
};
|
|
24538
|
+
var createCacheCabSource = (reportBuilderState, config) => {
|
|
24539
|
+
const tableNames = [...new Set(config.referencedTables)].sort();
|
|
24540
|
+
const tables = reportBuilderState.tables;
|
|
24541
|
+
return {
|
|
24542
|
+
key: stableStringify2({
|
|
24543
|
+
version: 1,
|
|
24544
|
+
clientId: config.clientId,
|
|
24545
|
+
databaseType: config.databaseType,
|
|
24546
|
+
tenants: config.tenants ?? null,
|
|
24547
|
+
flags: config.flags ?? null,
|
|
24548
|
+
tables: tableNames,
|
|
24549
|
+
dateField: config.dateField
|
|
24550
|
+
}),
|
|
24551
|
+
dateField: config.dateField,
|
|
24552
|
+
state: {
|
|
24553
|
+
tables,
|
|
24554
|
+
columns: reportBuilderState.columns,
|
|
24555
|
+
filterStack: [],
|
|
24556
|
+
pivot: null,
|
|
24557
|
+
sort: [],
|
|
24558
|
+
limit: null
|
|
24559
|
+
}
|
|
24560
|
+
};
|
|
24561
|
+
};
|
|
24562
|
+
|
|
24563
|
+
// src/utils/cacheCab.ts
|
|
24171
24564
|
var TZ = "America/Los_Angeles";
|
|
24565
|
+
var MAX_CACHECAB_ROWS = 1e5;
|
|
24172
24566
|
var CacheCab = class {
|
|
24173
24567
|
fetchedRange = {};
|
|
24174
24568
|
cachedReportIds = [];
|
|
24175
24569
|
uncacheableReportIDs = [];
|
|
24176
24570
|
uncacheableInFlight = /* @__PURE__ */ new Map();
|
|
24571
|
+
reportMemoryCache = /* @__PURE__ */ new Map();
|
|
24572
|
+
reportLoadInFlight = /* @__PURE__ */ new Map();
|
|
24573
|
+
sourceAliases = /* @__PURE__ */ new Map();
|
|
24574
|
+
sourceFetchInFlight = /* @__PURE__ */ new Map();
|
|
24177
24575
|
storage;
|
|
24576
|
+
metaReady;
|
|
24178
24577
|
META_KEY = "cachecab:meta";
|
|
24179
24578
|
DATA_PREFIX = "cachecab:data:";
|
|
24180
24579
|
UNCACHEABLE_PREFIX = "cachecab:uncacheable:";
|
|
@@ -24182,13 +24581,38 @@ var CacheCab = class {
|
|
|
24182
24581
|
storageType = "memory"
|
|
24183
24582
|
} = {}) {
|
|
24184
24583
|
this.storage = storageType !== "idb" ? new MemoryStorage() : new IdbStorage();
|
|
24185
|
-
|
|
24584
|
+
this.metaReady = this.loadMetaFromStorage();
|
|
24186
24585
|
}
|
|
24187
|
-
async get(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, pageSize, getToken, eventTracking, forceRefresh) {
|
|
24586
|
+
async get(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, pageSize, getToken, eventTracking, forceRefresh, sourceConfig) {
|
|
24587
|
+
await this.metaReady;
|
|
24188
24588
|
if (this.isCached(reportId, tenants) && !forceRefresh) {
|
|
24189
|
-
return this.getFromCache(
|
|
24589
|
+
return this.getFromCache(
|
|
24590
|
+
reportId,
|
|
24591
|
+
dashboardFilters,
|
|
24592
|
+
customFilters,
|
|
24593
|
+
pivot,
|
|
24594
|
+
client,
|
|
24595
|
+
tenants,
|
|
24596
|
+
flags,
|
|
24597
|
+
getToken,
|
|
24598
|
+
eventTracking,
|
|
24599
|
+
sourceConfig
|
|
24600
|
+
);
|
|
24190
24601
|
} else {
|
|
24191
|
-
return this.addToCache(
|
|
24602
|
+
return this.addToCache(
|
|
24603
|
+
reportId,
|
|
24604
|
+
dashboardFilters,
|
|
24605
|
+
customFilters,
|
|
24606
|
+
pivot,
|
|
24607
|
+
client,
|
|
24608
|
+
tenants,
|
|
24609
|
+
flags,
|
|
24610
|
+
getToken,
|
|
24611
|
+
eventTracking,
|
|
24612
|
+
true,
|
|
24613
|
+
forceRefresh,
|
|
24614
|
+
sourceConfig
|
|
24615
|
+
);
|
|
24192
24616
|
}
|
|
24193
24617
|
}
|
|
24194
24618
|
isCached(reportId, tenants) {
|
|
@@ -24197,6 +24621,47 @@ var CacheCab = class {
|
|
|
24197
24621
|
isCacheable(reportId) {
|
|
24198
24622
|
return !this.uncacheableReportIDs.includes(reportId);
|
|
24199
24623
|
}
|
|
24624
|
+
/**
|
|
24625
|
+
* Returns CacheCab's raw report without fetching or applying dashboard state.
|
|
24626
|
+
* Consumers must only run report-builder operations locally when `complete`
|
|
24627
|
+
* is true; otherwise the cached rows are an unsafe sample of the report.
|
|
24628
|
+
*/
|
|
24629
|
+
async getReportSnapshot(reportId, tenants) {
|
|
24630
|
+
await this.metaReady;
|
|
24631
|
+
const cacheKey = this.getCacheKey(reportId, tenants);
|
|
24632
|
+
if (!this.cachedReportIds.includes(cacheKey)) return null;
|
|
24633
|
+
const cachedReport = await this.readCachedReport(cacheKey);
|
|
24634
|
+
if (!cachedReport) return null;
|
|
24635
|
+
try {
|
|
24636
|
+
const report = { ...cachedReport, id: reportId };
|
|
24637
|
+
const rowCount = report.rows?.length ?? 0;
|
|
24638
|
+
const hasQueryLimit = Boolean(report.reportBuilderState?.limit) || reportUsesLimitClause(report);
|
|
24639
|
+
const hitRowLimit = rowCount >= MAX_CACHECAB_ROWS;
|
|
24640
|
+
const fetchedRange = this.fetchedRange[cacheKey];
|
|
24641
|
+
const coversAllTime = fetchedRange?.allTimeDoneBefore === true;
|
|
24642
|
+
const isSourceEntry = cacheKey.startsWith("source:");
|
|
24643
|
+
return {
|
|
24644
|
+
report,
|
|
24645
|
+
complete: (coversAllTime || isSourceEntry) && !hasQueryLimit && !hitRowLimit,
|
|
24646
|
+
reason: hasQueryLimit ? "query_limit" : hitRowLimit ? "row_limit" : !coversAllTime && !isSourceEntry ? "partial_date_range" : "complete",
|
|
24647
|
+
rowCount,
|
|
24648
|
+
fetchedRange
|
|
24649
|
+
};
|
|
24650
|
+
} catch {
|
|
24651
|
+
return null;
|
|
24652
|
+
}
|
|
24653
|
+
}
|
|
24654
|
+
async evictReport(reportId, tenants) {
|
|
24655
|
+
await this.metaReady;
|
|
24656
|
+
const cacheKey = this.getCacheKey(reportId, tenants);
|
|
24657
|
+
this.cachedReportIds = this.cachedReportIds.filter(
|
|
24658
|
+
(cachedKey) => cachedKey !== cacheKey
|
|
24659
|
+
);
|
|
24660
|
+
delete this.fetchedRange[cacheKey];
|
|
24661
|
+
this.reportMemoryCache.delete(cacheKey);
|
|
24662
|
+
await this.storage.removeItem(`${this.DATA_PREFIX}${cacheKey}`);
|
|
24663
|
+
await this.persistMetaToStorage();
|
|
24664
|
+
}
|
|
24200
24665
|
async getUncacheableResult(reportId, client, tenants, flags, filters, additionalProcessing, pivot) {
|
|
24201
24666
|
const key = this.getUncacheableRequestKey(
|
|
24202
24667
|
reportId,
|
|
@@ -24242,7 +24707,10 @@ var CacheCab = class {
|
|
|
24242
24707
|
if (!forceRefresh) {
|
|
24243
24708
|
const raw = await this.storage.getItem(key);
|
|
24244
24709
|
if (raw) {
|
|
24245
|
-
return {
|
|
24710
|
+
return {
|
|
24711
|
+
report: JSON.parse(raw),
|
|
24712
|
+
fromCache: true
|
|
24713
|
+
};
|
|
24246
24714
|
}
|
|
24247
24715
|
const inFlight = this.uncacheableInFlight.get(key);
|
|
24248
24716
|
if (inFlight) {
|
|
@@ -24266,48 +24734,86 @@ var CacheCab = class {
|
|
|
24266
24734
|
this.uncacheableInFlight.delete(key);
|
|
24267
24735
|
}
|
|
24268
24736
|
}
|
|
24269
|
-
async addToCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, firstTime = true, forceRefresh = false) {
|
|
24737
|
+
async addToCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, firstTime = true, forceRefresh = false, sourceConfig) {
|
|
24270
24738
|
const tenantPart = tenants ? JSON.stringify(tenants) : "";
|
|
24271
|
-
|
|
24739
|
+
let cacheKey = this.getCacheKey(reportId, tenants);
|
|
24272
24740
|
if (firstTime) {
|
|
24273
|
-
const result = await this.fetchInitialReport({
|
|
24741
|
+
const result = await this.fetchInitialReport({
|
|
24742
|
+
reportId,
|
|
24743
|
+
client,
|
|
24744
|
+
tenants,
|
|
24745
|
+
flags,
|
|
24746
|
+
filters: dashboardFilters,
|
|
24747
|
+
getToken,
|
|
24748
|
+
eventTracking,
|
|
24749
|
+
forceRefresh,
|
|
24750
|
+
sourceConfig
|
|
24751
|
+
});
|
|
24752
|
+
cacheKey = this.getCacheKey(reportId, tenants);
|
|
24274
24753
|
try {
|
|
24275
|
-
await this.
|
|
24754
|
+
await this.writeCachedReport(cacheKey, result);
|
|
24276
24755
|
this.cachedReportIds.push(cacheKey);
|
|
24277
24756
|
await this.persistMetaToStorage();
|
|
24278
24757
|
} catch {
|
|
24279
24758
|
console.warn(`Failed to cache report: ${reportId}. Cache full?`);
|
|
24280
24759
|
}
|
|
24281
|
-
const newRows = await this.applyPivotsAndFilters(
|
|
24760
|
+
const newRows = await this.applyPivotsAndFilters(
|
|
24761
|
+
result,
|
|
24762
|
+
dashboardFilters,
|
|
24763
|
+
customFilters,
|
|
24764
|
+
pivot,
|
|
24765
|
+
tenantPart,
|
|
24766
|
+
false
|
|
24767
|
+
);
|
|
24282
24768
|
if (pivot) {
|
|
24283
24769
|
const pivotColumns = generatePivotColumnsInMemory({
|
|
24284
24770
|
pivot,
|
|
24285
24771
|
pivotRows: newRows,
|
|
24286
24772
|
sourceColumns: result.columnInternal ?? result.columns
|
|
24287
24773
|
});
|
|
24288
|
-
return {
|
|
24774
|
+
return {
|
|
24775
|
+
...result,
|
|
24776
|
+
pivotRows: newRows,
|
|
24777
|
+
pivotColumns: pivotColumns ?? result.pivotColumns,
|
|
24778
|
+
pivotRowCount: newRows.length
|
|
24779
|
+
};
|
|
24289
24780
|
}
|
|
24290
24781
|
return { ...result, rows: newRows, rowCount: newRows.length };
|
|
24291
24782
|
} else {
|
|
24292
|
-
const dbDateFilter = dashboardFilters.find(
|
|
24783
|
+
const dbDateFilter = dashboardFilters.find(
|
|
24784
|
+
(x) => x.filterType === "date_range"
|
|
24785
|
+
);
|
|
24293
24786
|
const { start: requestedStart, end: requestedEnd } = normalizePSTRanges(
|
|
24294
24787
|
dbDateFilter?.startDate ? new Date(dbDateFilter.startDate) : void 0,
|
|
24295
24788
|
dbDateFilter?.endDate ? new Date(dbDateFilter.endDate) : void 0
|
|
24296
24789
|
);
|
|
24297
24790
|
if (!requestedStart || !requestedEnd) {
|
|
24298
|
-
return this.addToCache(
|
|
24791
|
+
return this.addToCache(
|
|
24792
|
+
reportId,
|
|
24793
|
+
dashboardFilters,
|
|
24794
|
+
customFilters,
|
|
24795
|
+
pivot,
|
|
24796
|
+
client,
|
|
24797
|
+
tenants,
|
|
24798
|
+
flags,
|
|
24799
|
+
getToken,
|
|
24800
|
+
eventTracking,
|
|
24801
|
+
true,
|
|
24802
|
+
false,
|
|
24803
|
+
sourceConfig
|
|
24804
|
+
);
|
|
24299
24805
|
}
|
|
24300
24806
|
const currentRange = this.fetchedRange[cacheKey];
|
|
24301
24807
|
const rangeStart = currentRange?.start ?? requestedStart;
|
|
24302
24808
|
const rangeEnd = currentRange?.end ?? endOfDayPST(/* @__PURE__ */ new Date());
|
|
24303
|
-
const existingRaw = await this.storage.getItem(this.DATA_PREFIX + cacheKey);
|
|
24304
24809
|
let existing;
|
|
24305
24810
|
let fetchedRows = [];
|
|
24306
24811
|
try {
|
|
24307
|
-
|
|
24308
|
-
if (!
|
|
24812
|
+
const cachedReport = await this.readCachedReport(cacheKey);
|
|
24813
|
+
if (!cachedReport?.rows) {
|
|
24309
24814
|
throw new Error("Invalid Cache!");
|
|
24310
24815
|
}
|
|
24816
|
+
existing = cachedReport;
|
|
24311
24817
|
if (requestedStart < rangeStart) {
|
|
24312
24818
|
const olderReport = await this.fetchReport({
|
|
24313
24819
|
reportId,
|
|
@@ -24364,19 +24870,33 @@ var CacheCab = class {
|
|
|
24364
24870
|
const filteredNew = filterNewRows(boundaryRows, fetchedRows);
|
|
24365
24871
|
mergedRows = filteredNew.concat(existing.rows);
|
|
24366
24872
|
} else {
|
|
24367
|
-
mergedRows = filterNewRows(existing.rows, fetchedRows).concat(
|
|
24873
|
+
mergedRows = filterNewRows(existing.rows, fetchedRows).concat(
|
|
24874
|
+
existing.rows
|
|
24875
|
+
);
|
|
24368
24876
|
}
|
|
24369
24877
|
const merged = { ...existing, rows: mergedRows };
|
|
24370
|
-
await this.
|
|
24878
|
+
await this.writeCachedReport(cacheKey, merged);
|
|
24371
24879
|
await this.persistMetaToStorage();
|
|
24372
|
-
const newRows = await this.applyPivotsAndFilters(
|
|
24880
|
+
const newRows = await this.applyPivotsAndFilters(
|
|
24881
|
+
merged,
|
|
24882
|
+
dashboardFilters,
|
|
24883
|
+
customFilters,
|
|
24884
|
+
pivot,
|
|
24885
|
+
tenantPart,
|
|
24886
|
+
false
|
|
24887
|
+
);
|
|
24373
24888
|
if (pivot) {
|
|
24374
24889
|
const pivotColumns = generatePivotColumnsInMemory({
|
|
24375
24890
|
pivot,
|
|
24376
24891
|
pivotRows: newRows,
|
|
24377
24892
|
sourceColumns: merged.columnInternal ?? merged.columns
|
|
24378
24893
|
});
|
|
24379
|
-
return {
|
|
24894
|
+
return {
|
|
24895
|
+
...merged,
|
|
24896
|
+
pivotRows: newRows,
|
|
24897
|
+
pivotColumns: pivotColumns ?? merged.pivotColumns,
|
|
24898
|
+
pivotRowCount: newRows.length
|
|
24899
|
+
};
|
|
24380
24900
|
}
|
|
24381
24901
|
return { ...merged, rows: newRows, rowCount: newRows.length };
|
|
24382
24902
|
}
|
|
@@ -24384,37 +24904,88 @@ var CacheCab = class {
|
|
|
24384
24904
|
/**
|
|
24385
24905
|
* Returns cache entry (or re-queries if stale)
|
|
24386
24906
|
*/
|
|
24387
|
-
async getFromCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking) {
|
|
24388
|
-
const dateRangeFilter = dashboardFilters.find(
|
|
24907
|
+
async getFromCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, sourceConfig) {
|
|
24908
|
+
const dateRangeFilter = dashboardFilters.find(
|
|
24909
|
+
(x) => x.filterType === "date_range"
|
|
24910
|
+
);
|
|
24389
24911
|
const cacheKey = this.getCacheKey(reportId, tenants);
|
|
24390
24912
|
if (!dateRangeFilter || dateRangeFilter?.primaryRange.value === "ALL_TIME") {
|
|
24391
24913
|
const fetchInfo = this.fetchedRange[cacheKey];
|
|
24392
24914
|
if (!fetchInfo || fetchInfo?.allTimeDoneBefore === false || Date.now() - fetchInfo.fetchedAtUTCMS >= MS_IN_DAY) {
|
|
24393
|
-
return this.addToCache(
|
|
24915
|
+
return this.addToCache(
|
|
24916
|
+
reportId,
|
|
24917
|
+
dashboardFilters,
|
|
24918
|
+
customFilters,
|
|
24919
|
+
pivot,
|
|
24920
|
+
client,
|
|
24921
|
+
tenants,
|
|
24922
|
+
flags,
|
|
24923
|
+
getToken,
|
|
24924
|
+
eventTracking,
|
|
24925
|
+
true,
|
|
24926
|
+
false,
|
|
24927
|
+
sourceConfig
|
|
24928
|
+
);
|
|
24394
24929
|
}
|
|
24395
24930
|
} else if (this.weShouldReQuery(cacheKey, dateRangeFilter)) {
|
|
24396
|
-
return this.addToCache(
|
|
24931
|
+
return this.addToCache(
|
|
24932
|
+
reportId,
|
|
24933
|
+
dashboardFilters,
|
|
24934
|
+
customFilters,
|
|
24935
|
+
pivot,
|
|
24936
|
+
client,
|
|
24937
|
+
tenants,
|
|
24938
|
+
flags,
|
|
24939
|
+
getToken,
|
|
24940
|
+
eventTracking,
|
|
24941
|
+
false,
|
|
24942
|
+
false,
|
|
24943
|
+
sourceConfig
|
|
24944
|
+
);
|
|
24397
24945
|
}
|
|
24398
24946
|
try {
|
|
24399
|
-
const
|
|
24400
|
-
if (!
|
|
24947
|
+
const parsed = await this.readCachedReport(cacheKey);
|
|
24948
|
+
if (!parsed) {
|
|
24401
24949
|
throw new Error("Invalid Cache!");
|
|
24402
24950
|
}
|
|
24403
|
-
const parsed = JSON.parse(raw);
|
|
24404
24951
|
const tenantPart = tenants ? JSON.stringify(tenants) : "";
|
|
24405
|
-
const newRows = await this.applyPivotsAndFilters(
|
|
24952
|
+
const newRows = await this.applyPivotsAndFilters(
|
|
24953
|
+
parsed,
|
|
24954
|
+
dashboardFilters,
|
|
24955
|
+
customFilters,
|
|
24956
|
+
pivot,
|
|
24957
|
+
tenantPart
|
|
24958
|
+
);
|
|
24406
24959
|
if (pivot) {
|
|
24407
24960
|
const pivotColumns = generatePivotColumnsInMemory({
|
|
24408
24961
|
pivot,
|
|
24409
24962
|
pivotRows: newRows,
|
|
24410
24963
|
sourceColumns: parsed.columnInternal ?? parsed.columns
|
|
24411
24964
|
});
|
|
24412
|
-
return {
|
|
24965
|
+
return {
|
|
24966
|
+
...parsed,
|
|
24967
|
+
pivotRows: newRows,
|
|
24968
|
+
pivotColumns: pivotColumns ?? parsed.pivotColumns,
|
|
24969
|
+
pivotRowCount: newRows.length
|
|
24970
|
+
};
|
|
24413
24971
|
}
|
|
24414
24972
|
return { ...parsed, rows: newRows, rowCount: newRows.length };
|
|
24415
24973
|
} catch (err) {
|
|
24416
24974
|
console.error(err);
|
|
24417
|
-
return this.addToCache(
|
|
24975
|
+
return this.addToCache(
|
|
24976
|
+
reportId,
|
|
24977
|
+
dashboardFilters,
|
|
24978
|
+
customFilters,
|
|
24979
|
+
pivot,
|
|
24980
|
+
client,
|
|
24981
|
+
tenants,
|
|
24982
|
+
flags,
|
|
24983
|
+
getToken,
|
|
24984
|
+
eventTracking,
|
|
24985
|
+
false,
|
|
24986
|
+
false,
|
|
24987
|
+
sourceConfig
|
|
24988
|
+
);
|
|
24418
24989
|
}
|
|
24419
24990
|
}
|
|
24420
24991
|
weShouldReQuery(cacheKey, dateRangeFilter) {
|
|
@@ -24435,13 +25006,17 @@ var CacheCab = class {
|
|
|
24435
25006
|
filters = [],
|
|
24436
25007
|
getToken,
|
|
24437
25008
|
eventTracking,
|
|
24438
|
-
forceRefresh
|
|
25009
|
+
forceRefresh,
|
|
25010
|
+
sourceConfig
|
|
24439
25011
|
}) {
|
|
24440
25012
|
let start;
|
|
24441
25013
|
let end;
|
|
24442
25014
|
const dateRangeFilter = filters.find((x) => x.filterType === "date_range");
|
|
24443
25015
|
const cacheRange = dateRangeFilter?.initialCacheDateRange;
|
|
24444
|
-
if (
|
|
25016
|
+
if (sourceConfig) {
|
|
25017
|
+
start = sourceConfig.dateRange.startDate;
|
|
25018
|
+
end = sourceConfig.dateRange.endDate;
|
|
25019
|
+
} else if (cacheRange && cacheRange.startDate) {
|
|
24445
25020
|
const startDate = dateRangeFilter?.startDate;
|
|
24446
25021
|
start = startDate ? minDate([new Date(cacheRange.startDate), new Date(startDate)]) : new Date(cacheRange.startDate);
|
|
24447
25022
|
end = endOfDayPST(/* @__PURE__ */ new Date());
|
|
@@ -24462,7 +25037,8 @@ var CacheCab = class {
|
|
|
24462
25037
|
eventTracking,
|
|
24463
25038
|
start: normalized.start,
|
|
24464
25039
|
end: normalized.end,
|
|
24465
|
-
forceRefresh
|
|
25040
|
+
forceRefresh,
|
|
25041
|
+
sourceConfig
|
|
24466
25042
|
});
|
|
24467
25043
|
}
|
|
24468
25044
|
async fetchReport({
|
|
@@ -24475,7 +25051,8 @@ var CacheCab = class {
|
|
|
24475
25051
|
eventTracking,
|
|
24476
25052
|
start,
|
|
24477
25053
|
end,
|
|
24478
|
-
forceRefresh
|
|
25054
|
+
forceRefresh,
|
|
25055
|
+
sourceConfig
|
|
24479
25056
|
}) {
|
|
24480
25057
|
let reportInfo = void 0;
|
|
24481
25058
|
try {
|
|
@@ -24483,100 +25060,225 @@ var CacheCab = class {
|
|
|
24483
25060
|
const adjusted = [...filters].map((x) => {
|
|
24484
25061
|
return { ...x, options: void 0 };
|
|
24485
25062
|
});
|
|
24486
|
-
const dateFilterIndex = adjusted.findIndex(
|
|
24487
|
-
|
|
25063
|
+
const dateFilterIndex = adjusted.findIndex(
|
|
25064
|
+
(x) => x.filterType === "date_range"
|
|
25065
|
+
);
|
|
25066
|
+
const isAllTime = sourceConfig ? adjusted[dateFilterIndex]?.primaryRange?.value === "ALL_TIME" : dateFilterIndex === -1 || adjusted[dateFilterIndex].primaryRange?.value === "ALL_TIME";
|
|
24488
25067
|
if (!isAllTime) {
|
|
24489
|
-
const
|
|
24490
|
-
if (
|
|
24491
|
-
adjusted[dateFilterIndex] = {
|
|
25068
|
+
const dateFilter2 = adjusted[dateFilterIndex];
|
|
25069
|
+
if (dateFilter2 && dateFilter2.startDate && dateFilter2.endDate) {
|
|
25070
|
+
adjusted[dateFilterIndex] = {
|
|
25071
|
+
...dateFilter2,
|
|
25072
|
+
startDate: s,
|
|
25073
|
+
endDate: e
|
|
25074
|
+
};
|
|
24492
25075
|
}
|
|
24493
25076
|
}
|
|
24494
|
-
const
|
|
25077
|
+
const stateResponse = await quillFetch({
|
|
24495
25078
|
client,
|
|
24496
|
-
task: "report",
|
|
25079
|
+
task: "report-builder-state",
|
|
24497
25080
|
metadata: {
|
|
24498
25081
|
reportId,
|
|
24499
|
-
|
|
24500
|
-
databaseType: client.databaseType,
|
|
24501
|
-
filters: adjusted,
|
|
24502
|
-
additionalProcessing: { page: { rowsPerPage: 1e3, rowsPerRequest: 1e5 } },
|
|
24503
|
-
useNewNodeSql: true,
|
|
24504
|
-
tenants,
|
|
24505
|
-
flags,
|
|
24506
|
-
overwriteCache: forceRefresh ?? false
|
|
25082
|
+
tenants
|
|
24507
25083
|
},
|
|
24508
25084
|
getToken
|
|
24509
25085
|
});
|
|
24510
|
-
|
|
24511
|
-
|
|
24512
|
-
|
|
24513
|
-
|
|
24514
|
-
|
|
24515
|
-
|
|
24516
|
-
)
|
|
24517
|
-
|
|
24518
|
-
|
|
24519
|
-
|
|
24520
|
-
|
|
24521
|
-
|
|
24522
|
-
|
|
24523
|
-
|
|
24524
|
-
|
|
24525
|
-
|
|
24526
|
-
|
|
24527
|
-
|
|
24528
|
-
|
|
25086
|
+
if (stateResponse.error || stateResponse.status === "error") {
|
|
25087
|
+
throw new Error(
|
|
25088
|
+
stateResponse.error || "Could not load report builder state"
|
|
25089
|
+
);
|
|
25090
|
+
}
|
|
25091
|
+
const reportBuilderState = stateResponse.data?.reportBuilderState;
|
|
25092
|
+
if (!reportBuilderState) {
|
|
25093
|
+
throw new Error("Report builder state was not returned");
|
|
25094
|
+
}
|
|
25095
|
+
const source = sourceConfig ? createCacheCabSource(reportBuilderState, sourceConfig) : void 0;
|
|
25096
|
+
const sourceCacheKey = source ? this.bindReportToSource(reportId, tenants, source.key) : this.getCacheKey(reportId, tenants);
|
|
25097
|
+
const sourceDateFilter = source ? {
|
|
25098
|
+
filterType: "date_range",
|
|
25099
|
+
field: source.dateField.field,
|
|
25100
|
+
table: source.dateField.table,
|
|
25101
|
+
dateField: [source.dateField],
|
|
25102
|
+
label: "CacheCab date range",
|
|
25103
|
+
dashboardName: "",
|
|
25104
|
+
startDate: s,
|
|
25105
|
+
endDate: e,
|
|
25106
|
+
primaryRange: { label: "Custom", value: "CUSTOM" },
|
|
25107
|
+
preset: { label: "Custom", value: "CUSTOM" },
|
|
25108
|
+
presetOptions: [],
|
|
25109
|
+
defaultPresetRanges: [],
|
|
25110
|
+
options: void 0
|
|
25111
|
+
} : void 0;
|
|
25112
|
+
const filtersForSource = source ? isAllTime ? [] : [sourceDateFilter] : adjusted;
|
|
25113
|
+
const builderFilters = filtersForSource.map((filter) => {
|
|
25114
|
+
if ("table" in filter && filter.table) return filter;
|
|
25115
|
+
const matchingTables = [
|
|
25116
|
+
...new Set(
|
|
25117
|
+
reportBuilderState.columns.filter((column) => column.field === filter.field && column.table).map((column) => column.table)
|
|
25118
|
+
)
|
|
25119
|
+
];
|
|
25120
|
+
return matchingTables.length === 1 ? { ...filter, table: matchingTables[0] } : filter;
|
|
24529
25121
|
});
|
|
25122
|
+
const sourceState = source?.state ?? {
|
|
25123
|
+
...reportBuilderState,
|
|
25124
|
+
pivot: null
|
|
25125
|
+
};
|
|
25126
|
+
const fetchSource = async () => {
|
|
25127
|
+
const existingRange = this.fetchedRange[sourceCacheKey];
|
|
25128
|
+
const rangeCovered = existingRange && (existingRange.allTimeDoneBefore || existingRange.start <= s && existingRange.end >= e);
|
|
25129
|
+
if (source && rangeCovered && !forceRefresh) {
|
|
25130
|
+
const existing = await this.readCachedReport(sourceCacheKey);
|
|
25131
|
+
if (existing) return existing;
|
|
25132
|
+
}
|
|
25133
|
+
const tableData = await fetchTableByState(
|
|
25134
|
+
sourceState,
|
|
25135
|
+
client,
|
|
25136
|
+
getToken,
|
|
25137
|
+
tenants,
|
|
25138
|
+
eventTracking,
|
|
25139
|
+
"",
|
|
25140
|
+
{
|
|
25141
|
+
page: {
|
|
25142
|
+
page: 0,
|
|
25143
|
+
rowsPerPage: 1e3,
|
|
25144
|
+
rowsPerRequest: 1e5
|
|
25145
|
+
}
|
|
25146
|
+
},
|
|
25147
|
+
void 0,
|
|
25148
|
+
true,
|
|
25149
|
+
false,
|
|
25150
|
+
reportId,
|
|
25151
|
+
void 0,
|
|
25152
|
+
void 0,
|
|
25153
|
+
builderFilters
|
|
25154
|
+
);
|
|
25155
|
+
if (tableData.error) {
|
|
25156
|
+
throw new Error(tableData.error);
|
|
25157
|
+
}
|
|
25158
|
+
const referencedColumns = sourceState.columns.reduce((result, column) => {
|
|
25159
|
+
const table = column.table ?? "";
|
|
25160
|
+
if (!result[table]) result[table] = [];
|
|
25161
|
+
if (!result[table].includes(column.field)) {
|
|
25162
|
+
result[table].push(column.field);
|
|
25163
|
+
}
|
|
25164
|
+
return result;
|
|
25165
|
+
}, {});
|
|
25166
|
+
return {
|
|
25167
|
+
...EMPTY_INTERNAL_REPORT,
|
|
25168
|
+
id: reportId,
|
|
25169
|
+
name: reportId,
|
|
25170
|
+
rows: tableData.rows,
|
|
25171
|
+
rowCount: tableData.rows.length,
|
|
25172
|
+
columns: tableData.columns.map((column) => ({
|
|
25173
|
+
field: column.field,
|
|
25174
|
+
format: column.format,
|
|
25175
|
+
label: column.label
|
|
25176
|
+
})),
|
|
25177
|
+
columnInternal: tableData.columns,
|
|
25178
|
+
referencedTables: sourceState.tables.map((table) => table.name),
|
|
25179
|
+
referencedColumns,
|
|
25180
|
+
reportBuilderState,
|
|
25181
|
+
pivot: reportBuilderState.pivot,
|
|
25182
|
+
dateField: source?.dateField
|
|
25183
|
+
};
|
|
25184
|
+
};
|
|
25185
|
+
const existingSourceRequest = source ? this.sourceFetchInFlight.get(sourceCacheKey) : void 0;
|
|
25186
|
+
if (existingSourceRequest && !forceRefresh) {
|
|
25187
|
+
return { ...await existingSourceRequest, id: reportId };
|
|
25188
|
+
}
|
|
25189
|
+
const sourceRequest = fetchSource();
|
|
25190
|
+
if (source) this.sourceFetchInFlight.set(sourceCacheKey, sourceRequest);
|
|
25191
|
+
try {
|
|
25192
|
+
reportInfo = await sourceRequest;
|
|
25193
|
+
} finally {
|
|
25194
|
+
if (source) this.sourceFetchInFlight.delete(sourceCacheKey);
|
|
25195
|
+
}
|
|
25196
|
+
const dateFilter = builderFilters[dateFilterIndex];
|
|
25197
|
+
const dateFilterTable = dateFilter && "table" in dateFilter ? dateFilter.table : void 0;
|
|
25198
|
+
reportInfo.dateField = source?.dateField ?? (dateFilter?.field && dateFilterTable ? { field: dateFilter.field, table: dateFilterTable } : void 0);
|
|
24530
25199
|
const dateField = reportInfo.dateField?.field;
|
|
24531
25200
|
if (!isAllTime && dateField !== void 0 && reportInfo.rows.length > 0) {
|
|
24532
25201
|
const cleanedDateField = removeQuotes(dateField);
|
|
24533
|
-
const missingDateFieldCount = reportInfo.rows.some(
|
|
25202
|
+
const missingDateFieldCount = reportInfo.rows.some(
|
|
25203
|
+
(row) => row[cleanedDateField] === void 0
|
|
25204
|
+
);
|
|
24534
25205
|
if (missingDateFieldCount) {
|
|
24535
25206
|
this.uncacheableReportIDs.push(reportId);
|
|
25207
|
+
if (source) {
|
|
25208
|
+
throw new Error(
|
|
25209
|
+
`CacheCab source is missing date field ${dateField}`
|
|
25210
|
+
);
|
|
25211
|
+
}
|
|
24536
25212
|
return EMPTY_INTERNAL_REPORT;
|
|
24537
25213
|
}
|
|
24538
25214
|
}
|
|
24539
25215
|
const requiredFilterFields = adjusted.flatMap((x, idx) => {
|
|
24540
|
-
if (idx === dateFilterIndex || !x.values && !x.selectedValue)
|
|
25216
|
+
if (idx === dateFilterIndex || !x.values && !x.selectedValue)
|
|
25217
|
+
return [];
|
|
24541
25218
|
return removeQuotes(x.field);
|
|
24542
25219
|
});
|
|
24543
|
-
const missingFields = [
|
|
24544
|
-
|
|
24545
|
-
|
|
25220
|
+
const missingFields = [
|
|
25221
|
+
...new Set(
|
|
25222
|
+
requiredFilterFields.filter(
|
|
25223
|
+
(field) => reportInfo?.rows.some((row) => row[field] === void 0)
|
|
25224
|
+
)
|
|
25225
|
+
)
|
|
25226
|
+
];
|
|
24546
25227
|
if (missingFields.length > 0) {
|
|
24547
25228
|
this.uncacheableReportIDs.push(reportId);
|
|
25229
|
+
if (source) {
|
|
25230
|
+
throw new Error(
|
|
25231
|
+
`CacheCab source is missing required fields: ${missingFields.join(", ")}`
|
|
25232
|
+
);
|
|
25233
|
+
}
|
|
24548
25234
|
return EMPTY_INTERNAL_REPORT;
|
|
24549
25235
|
}
|
|
24550
25236
|
const cacheKey = this.getCacheKey(reportId, tenants);
|
|
24551
25237
|
if (isAllTime) {
|
|
24552
|
-
this.fetchedRange[cacheKey] = {
|
|
25238
|
+
this.fetchedRange[cacheKey] = {
|
|
25239
|
+
start: /* @__PURE__ */ new Date(0),
|
|
25240
|
+
end: /* @__PURE__ */ new Date(),
|
|
25241
|
+
fetchedAtUTCMS: Date.now(),
|
|
25242
|
+
allTimeDoneBefore: true
|
|
25243
|
+
};
|
|
24553
25244
|
} else {
|
|
24554
25245
|
const existing = this.fetchedRange[cacheKey];
|
|
24555
25246
|
if (existing && !forceRefresh) {
|
|
24556
25247
|
const oldStart = existing.start;
|
|
24557
25248
|
const oldEnd = existing.end;
|
|
24558
|
-
this.fetchedRange[cacheKey] = {
|
|
25249
|
+
this.fetchedRange[cacheKey] = {
|
|
25250
|
+
start: getMinDate(oldStart, s),
|
|
25251
|
+
end: getMaxDate(oldEnd, e),
|
|
25252
|
+
fetchedAtUTCMS: Date.now(),
|
|
25253
|
+
allTimeDoneBefore: false
|
|
25254
|
+
};
|
|
24559
25255
|
} else {
|
|
24560
|
-
this.fetchedRange[cacheKey] = {
|
|
25256
|
+
this.fetchedRange[cacheKey] = {
|
|
25257
|
+
start: s,
|
|
25258
|
+
end: e,
|
|
25259
|
+
fetchedAtUTCMS: Date.now(),
|
|
25260
|
+
allTimeDoneBefore: false
|
|
25261
|
+
};
|
|
24561
25262
|
}
|
|
24562
25263
|
}
|
|
24563
25264
|
} catch (error) {
|
|
24564
25265
|
console.warn(error);
|
|
24565
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
25266
|
+
if (sourceConfig || error instanceof Error && error.name === "AbortError") {
|
|
24566
25267
|
throw error;
|
|
24567
25268
|
}
|
|
24568
25269
|
}
|
|
24569
25270
|
return reportInfo || EMPTY_INTERNAL_REPORT;
|
|
24570
25271
|
}
|
|
24571
25272
|
async applyPivotsAndFilters(report, dashboardFilters, customFilters, pivot, tenantPart, useCache = true) {
|
|
24572
|
-
const
|
|
25273
|
+
const reportCacheKey = this.sourceAliases.get(report.id + tenantPart) ?? report.id + tenantPart;
|
|
25274
|
+
const datasetVersion = this.fetchedRange[reportCacheKey]?.fetchedAtUTCMS ?? 0;
|
|
24573
25275
|
const keyParts = [
|
|
24574
25276
|
report.queryString,
|
|
24575
25277
|
tenantPart,
|
|
24576
25278
|
datasetVersion,
|
|
24577
25279
|
// prevents fetching stale filters on hard refresh
|
|
24578
|
-
hashString(
|
|
24579
|
-
hashString(
|
|
25280
|
+
hashString(stableStringify3(dashboardFilters)),
|
|
25281
|
+
hashString(stableStringify3(customFilters))
|
|
24580
25282
|
];
|
|
24581
25283
|
const queryKey = this.DATA_PREFIX + keyParts.join("|");
|
|
24582
25284
|
let filtersApplied;
|
|
@@ -24590,19 +25292,30 @@ var CacheCab = class {
|
|
|
24590
25292
|
}
|
|
24591
25293
|
}
|
|
24592
25294
|
if (!filtersApplied) {
|
|
24593
|
-
const dateIndex = dashboardFilters.findIndex(
|
|
24594
|
-
|
|
24595
|
-
|
|
24596
|
-
|
|
24597
|
-
|
|
24598
|
-
|
|
24599
|
-
|
|
24600
|
-
|
|
25295
|
+
const dateIndex = dashboardFilters.findIndex(
|
|
25296
|
+
(x) => x.filterType === "date_range"
|
|
25297
|
+
);
|
|
25298
|
+
const requiredFilterFields = dashboardFilters.flatMap(
|
|
25299
|
+
(x, idx) => {
|
|
25300
|
+
if (idx === dateIndex || !x.values?.length && !x.selectedValue)
|
|
25301
|
+
return [];
|
|
25302
|
+
return removeQuotes(x.field);
|
|
25303
|
+
}
|
|
25304
|
+
);
|
|
25305
|
+
const missingFields = [
|
|
25306
|
+
...new Set(
|
|
25307
|
+
requiredFilterFields.filter(
|
|
25308
|
+
(field) => report.rows.some((row) => row[field] === void 0)
|
|
25309
|
+
)
|
|
25310
|
+
)
|
|
25311
|
+
];
|
|
24601
25312
|
if (missingFields.length > 0) {
|
|
24602
25313
|
this.uncacheableReportIDs.push(report.id);
|
|
24603
25314
|
return [];
|
|
24604
25315
|
}
|
|
24605
|
-
const dbDateFilter = dashboardFilters.find(
|
|
25316
|
+
const dbDateFilter = dashboardFilters.find(
|
|
25317
|
+
(x) => x.filterType === "date_range"
|
|
25318
|
+
);
|
|
24606
25319
|
if (report.dateField && dbDateFilter?.startDate) {
|
|
24607
25320
|
const { start: startDate, end: endDate } = normalizePSTRanges(
|
|
24608
25321
|
new Date(dbDateFilter.startDate),
|
|
@@ -24613,22 +25326,82 @@ var CacheCab = class {
|
|
|
24613
25326
|
const rowDate = new Date(x[fieldToUse]);
|
|
24614
25327
|
return startDate <= rowDate && (endDate ? rowDate <= endDate : true);
|
|
24615
25328
|
});
|
|
24616
|
-
filtersApplied = applyFiltersInMemory(dateFilteredRows, [], {
|
|
25329
|
+
filtersApplied = applyFiltersInMemory(dateFilteredRows, [], {
|
|
25330
|
+
dashboardFilters,
|
|
25331
|
+
customFilters
|
|
25332
|
+
});
|
|
24617
25333
|
} else {
|
|
24618
|
-
filtersApplied = applyFiltersInMemory(report.rows, [], {
|
|
25334
|
+
filtersApplied = applyFiltersInMemory(report.rows, [], {
|
|
25335
|
+
dashboardFilters,
|
|
25336
|
+
customFilters
|
|
25337
|
+
});
|
|
24619
25338
|
}
|
|
24620
25339
|
}
|
|
24621
25340
|
try {
|
|
24622
25341
|
await this.storage.setItem(queryKey, JSON.stringify(filtersApplied));
|
|
24623
25342
|
} catch {
|
|
24624
25343
|
}
|
|
24625
|
-
const withPivot = applyPivotInMemory(
|
|
25344
|
+
const withPivot = applyPivotInMemory(
|
|
25345
|
+
filtersApplied,
|
|
25346
|
+
pivot,
|
|
25347
|
+
dashboardFilters.concat(customFilters)
|
|
25348
|
+
);
|
|
24626
25349
|
return withPivot;
|
|
24627
25350
|
}
|
|
25351
|
+
/**
|
|
25352
|
+
* Reads and parses a persisted report at most once per CacheCab instance.
|
|
25353
|
+
* Concurrent callers share the same storage read and JSON.parse operation.
|
|
25354
|
+
*/
|
|
25355
|
+
async readCachedReport(cacheKey) {
|
|
25356
|
+
const cached = this.reportMemoryCache.get(cacheKey);
|
|
25357
|
+
if (cached) return cached;
|
|
25358
|
+
const existingLoad = this.reportLoadInFlight.get(cacheKey);
|
|
25359
|
+
if (existingLoad) return existingLoad;
|
|
25360
|
+
const load = (async () => {
|
|
25361
|
+
const raw = await this.storage.getItem(`${this.DATA_PREFIX}${cacheKey}`);
|
|
25362
|
+
if (!raw) return null;
|
|
25363
|
+
try {
|
|
25364
|
+
const report = JSON.parse(raw);
|
|
25365
|
+
this.reportMemoryCache.set(cacheKey, report);
|
|
25366
|
+
return report;
|
|
25367
|
+
} catch {
|
|
25368
|
+
return null;
|
|
25369
|
+
}
|
|
25370
|
+
})();
|
|
25371
|
+
this.reportLoadInFlight.set(cacheKey, load);
|
|
25372
|
+
try {
|
|
25373
|
+
return await load;
|
|
25374
|
+
} finally {
|
|
25375
|
+
this.reportLoadInFlight.delete(cacheKey);
|
|
25376
|
+
}
|
|
25377
|
+
}
|
|
25378
|
+
/**
|
|
25379
|
+
* Persists a report and updates the parsed in-memory copy atomically from
|
|
25380
|
+
* CacheCab's perspective.
|
|
25381
|
+
*/
|
|
25382
|
+
async writeCachedReport(cacheKey, report) {
|
|
25383
|
+
await this.storage.setItem(
|
|
25384
|
+
`${this.DATA_PREFIX}${cacheKey}`,
|
|
25385
|
+
JSON.stringify(report)
|
|
25386
|
+
);
|
|
25387
|
+
this.reportMemoryCache.set(cacheKey, report);
|
|
25388
|
+
}
|
|
24628
25389
|
getCacheKey(reportId, tenants) {
|
|
24629
|
-
const
|
|
25390
|
+
const aliasKey = this.getReportAliasKey(reportId, tenants);
|
|
25391
|
+
return this.sourceAliases.get(aliasKey) ?? aliasKey;
|
|
25392
|
+
}
|
|
25393
|
+
getReportAliasKey(reportId, tenants) {
|
|
25394
|
+
const tenantPart = tenants ? stableStringify3(tenants) : "";
|
|
24630
25395
|
return reportId + tenantPart;
|
|
24631
25396
|
}
|
|
25397
|
+
bindReportToSource(reportId, tenants, sourceKey) {
|
|
25398
|
+
const cacheKey = `source:${hashString(sourceKey)}`;
|
|
25399
|
+
this.sourceAliases.set(
|
|
25400
|
+
this.getReportAliasKey(reportId, tenants),
|
|
25401
|
+
cacheKey
|
|
25402
|
+
);
|
|
25403
|
+
return cacheKey;
|
|
25404
|
+
}
|
|
24632
25405
|
getUncacheableRequestKey(reportId, client, tenants, flags, filters, additionalProcessing, pivot) {
|
|
24633
25406
|
const canonicalFilters = filters.map(
|
|
24634
25407
|
(f) => canonicalizeFilterForUncacheableKey(f)
|
|
@@ -24637,11 +25410,13 @@ var CacheCab = class {
|
|
|
24637
25410
|
reportId,
|
|
24638
25411
|
client.id,
|
|
24639
25412
|
client.databaseType,
|
|
24640
|
-
hashString(
|
|
24641
|
-
hashString(
|
|
24642
|
-
hashString(
|
|
24643
|
-
hashString(
|
|
24644
|
-
|
|
25413
|
+
hashString(stableStringify3(canonicalizeForKey(tenants ?? null))),
|
|
25414
|
+
hashString(stableStringify3(canonicalizeForKey(flags ?? null))),
|
|
25415
|
+
hashString(stableStringify3(canonicalFilters)),
|
|
25416
|
+
hashString(
|
|
25417
|
+
stableStringify3(canonicalizeForKey(additionalProcessing ?? null))
|
|
25418
|
+
),
|
|
25419
|
+
hashString(stableStringify3(canonicalizeForKey(pivot ?? null)))
|
|
24645
25420
|
];
|
|
24646
25421
|
return this.UNCACHEABLE_PREFIX + keyParts.join("|");
|
|
24647
25422
|
}
|
|
@@ -24652,6 +25427,9 @@ var CacheCab = class {
|
|
|
24652
25427
|
const parsed = JSON.parse(meta);
|
|
24653
25428
|
this.cachedReportIds = parsed.cached || [];
|
|
24654
25429
|
this.uncacheableReportIDs = parsed.cannotBeCached;
|
|
25430
|
+
this.sourceAliases = new Map(
|
|
25431
|
+
Object.entries(parsed.sourceAliases ?? {})
|
|
25432
|
+
);
|
|
24655
25433
|
this.fetchedRange = Object.fromEntries(
|
|
24656
25434
|
Object.entries(parsed.fetchedRange || {}).map(([id, range]) => [
|
|
24657
25435
|
id,
|
|
@@ -24674,7 +25452,8 @@ var CacheCab = class {
|
|
|
24674
25452
|
JSON.stringify({
|
|
24675
25453
|
fetchedRange: serializableRange,
|
|
24676
25454
|
cached: this.cachedReportIds,
|
|
24677
|
-
cannotBeCached: this.uncacheableReportIDs
|
|
25455
|
+
cannotBeCached: this.uncacheableReportIDs,
|
|
25456
|
+
sourceAliases: Object.fromEntries(this.sourceAliases)
|
|
24678
25457
|
})
|
|
24679
25458
|
);
|
|
24680
25459
|
}
|
|
@@ -24687,6 +25466,9 @@ var MemoryStorage = class {
|
|
|
24687
25466
|
async setItem(key, value) {
|
|
24688
25467
|
this.store.set(key, value);
|
|
24689
25468
|
}
|
|
25469
|
+
async removeItem(key) {
|
|
25470
|
+
this.store.delete(key);
|
|
25471
|
+
}
|
|
24690
25472
|
};
|
|
24691
25473
|
var DB_NAME = "quill.cachecab";
|
|
24692
25474
|
var STORE_NAME = "kv";
|
|
@@ -24709,6 +25491,10 @@ var IdbStorage = class {
|
|
|
24709
25491
|
const db = await this.dbPromise;
|
|
24710
25492
|
await db.put(STORE_NAME, value, key);
|
|
24711
25493
|
}
|
|
25494
|
+
async removeItem(key) {
|
|
25495
|
+
const db = await this.dbPromise;
|
|
25496
|
+
await db.delete(STORE_NAME, key);
|
|
25497
|
+
}
|
|
24712
25498
|
};
|
|
24713
25499
|
function removeQuotes(str) {
|
|
24714
25500
|
return str.replace(/^['"]|['"]$/g, "");
|
|
@@ -24732,7 +25518,7 @@ function hashString(str) {
|
|
|
24732
25518
|
}
|
|
24733
25519
|
function filterNewRows(existingRows, newRows) {
|
|
24734
25520
|
const seen = /* @__PURE__ */ new Set();
|
|
24735
|
-
const getKey = (row) =>
|
|
25521
|
+
const getKey = (row) => stableStringify3(row);
|
|
24736
25522
|
existingRows.forEach((row) => seen.add(getKey(row)));
|
|
24737
25523
|
return newRows.filter((row) => {
|
|
24738
25524
|
const k = getKey(row);
|
|
@@ -24741,13 +25527,13 @@ function filterNewRows(existingRows, newRows) {
|
|
|
24741
25527
|
return true;
|
|
24742
25528
|
});
|
|
24743
25529
|
}
|
|
24744
|
-
function
|
|
25530
|
+
function stableStringify3(obj) {
|
|
24745
25531
|
if (obj === null || typeof obj !== "object") return JSON.stringify(obj);
|
|
24746
25532
|
if (Array.isArray(obj)) {
|
|
24747
|
-
return `[${obj.map(
|
|
25533
|
+
return `[${obj.map(stableStringify3).join(",")}]`;
|
|
24748
25534
|
}
|
|
24749
25535
|
const keys = Object.keys(obj).sort();
|
|
24750
|
-
return `{${keys.map((k) => JSON.stringify(k) + ":" +
|
|
25536
|
+
return `{${keys.map((k) => JSON.stringify(k) + ":" + stableStringify3(obj[k])).join(",")}}`;
|
|
24751
25537
|
}
|
|
24752
25538
|
function canonicalizeForKey(value) {
|
|
24753
25539
|
if (value instanceof Date) {
|
|
@@ -26903,6 +27689,7 @@ import jsPDF from "jspdf";
|
|
|
26903
27689
|
|
|
26904
27690
|
// src/hooks/useDashboard.ts
|
|
26905
27691
|
import { useContext, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
27692
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
26906
27693
|
init_dateRangePickerUtils();
|
|
26907
27694
|
init_Filter();
|
|
26908
27695
|
init_filterProcessing();
|
|
@@ -26946,10 +27733,11 @@ function isDashboardPivotTable(report) {
|
|
|
26946
27733
|
return String(report?.chartType ?? "").toLowerCase() === "table" && Boolean(report?.pivot);
|
|
26947
27734
|
}
|
|
26948
27735
|
function getDashboardReportProcessing(report, serverPagination) {
|
|
26949
|
-
return
|
|
27736
|
+
return report.pivot ? {} : serverPagination;
|
|
26950
27737
|
}
|
|
26951
27738
|
|
|
26952
27739
|
// src/hooks/useDashboard.ts
|
|
27740
|
+
var DEFAULT_DASHBOARD_REPORT_STALE_TIME_MS = 5 * 60 * 1e3;
|
|
26953
27741
|
var useDashboardInternal = (dashboardName, customFilters) => {
|
|
26954
27742
|
const [dashboard] = useContext(DashboardContext);
|
|
26955
27743
|
const {
|
|
@@ -27644,12 +28432,15 @@ var useDashboard = (dashboardName, config) => {
|
|
|
27644
28432
|
const fetchedInitialReports = useRef2(false);
|
|
27645
28433
|
const backfilledDashboards = useRef2(false);
|
|
27646
28434
|
const [client] = useContext(ClientContext);
|
|
28435
|
+
const queryClient = useQueryClient();
|
|
28436
|
+
const reportStaleTimeMs = config?.reportStaleTimeMs ?? DEFAULT_DASHBOARD_REPORT_STALE_TIME_MS;
|
|
27647
28437
|
const { tenants, flags } = useContext(TenantContext);
|
|
27648
28438
|
const { getToken } = useContext(FetchContext);
|
|
27649
28439
|
const { customReportFilters, customFiltersLoaded, setCustomFiltersLoaded } = useContext(ReportFiltersContext);
|
|
27650
28440
|
const { eventTracking } = useContext(EventTrackingContext);
|
|
27651
28441
|
const { getCacheCab } = useContext(CacheCabContext);
|
|
27652
28442
|
const reportRequestIds = useRef2({});
|
|
28443
|
+
const reportFetchAbortController = useRef2(null);
|
|
27653
28444
|
const lastDashboardName = useRef2(null);
|
|
27654
28445
|
const pendingNameChangeReload = useRef2(false);
|
|
27655
28446
|
const [loadedDashes, setLoadedDashes] = useState2([]);
|
|
@@ -27659,6 +28450,12 @@ var useDashboard = (dashboardName, config) => {
|
|
|
27659
28450
|
() => getCacheCab(config?.cacheType),
|
|
27660
28451
|
[getCacheCab, config?.cacheType]
|
|
27661
28452
|
);
|
|
28453
|
+
useEffect2(() => {
|
|
28454
|
+
return () => {
|
|
28455
|
+
reportFetchAbortController.current?.abort();
|
|
28456
|
+
reportFetchAbortController.current = null;
|
|
28457
|
+
};
|
|
28458
|
+
}, [dashboardName]);
|
|
27662
28459
|
useEffect2(() => {
|
|
27663
28460
|
const nameChanged = dashboardName !== lastDashboardName.current;
|
|
27664
28461
|
if (nameChanged) {
|
|
@@ -27846,8 +28643,52 @@ var useDashboard = (dashboardName, config) => {
|
|
|
27846
28643
|
if (!cacheEnabled) return;
|
|
27847
28644
|
fetchReports([], dashboardFilters ?? [], config?.pageSize, true);
|
|
27848
28645
|
};
|
|
28646
|
+
const primeReportSource = async (reportId) => {
|
|
28647
|
+
const reportInfo = allReportsById[reportId];
|
|
28648
|
+
if (!reportInfo || !client) {
|
|
28649
|
+
throw new Error(`Could not prime CacheCab for report ${reportId}`);
|
|
28650
|
+
}
|
|
28651
|
+
const dashboardDateFilter = dashboardFilters?.find(
|
|
28652
|
+
(filter) => filter.filterType === "date_range" /* Date */ && filter.startDate && filter.endDate
|
|
28653
|
+
);
|
|
28654
|
+
const dateRange = config?.cacheDateRange ?? (dashboardDateFilter?.startDate && dashboardDateFilter.endDate ? {
|
|
28655
|
+
startDate: new Date(dashboardDateFilter.startDate),
|
|
28656
|
+
endDate: new Date(dashboardDateFilter.endDate)
|
|
28657
|
+
} : void 0);
|
|
28658
|
+
if (!dateRange) {
|
|
28659
|
+
throw new Error(
|
|
28660
|
+
`CacheCab source for report ${reportId} requires a date range`
|
|
28661
|
+
);
|
|
28662
|
+
}
|
|
28663
|
+
await getCacheCab("memory").get(
|
|
28664
|
+
reportId,
|
|
28665
|
+
dashboardFilters ?? [],
|
|
28666
|
+
customReportFilters[reportId] ?? [],
|
|
28667
|
+
null,
|
|
28668
|
+
client,
|
|
28669
|
+
tenants,
|
|
28670
|
+
flags,
|
|
28671
|
+
void 0,
|
|
28672
|
+
getToken,
|
|
28673
|
+
eventTracking,
|
|
28674
|
+
false,
|
|
28675
|
+
{
|
|
28676
|
+
referencedTables: reportInfo.referencedTables ?? [],
|
|
28677
|
+
dateField: reportInfo.dateField,
|
|
28678
|
+
clientId: client.id ?? client.clientId ?? "",
|
|
28679
|
+
databaseType: client.databaseType,
|
|
28680
|
+
tenants,
|
|
28681
|
+
flags,
|
|
28682
|
+
dateRange
|
|
28683
|
+
}
|
|
28684
|
+
);
|
|
28685
|
+
};
|
|
27849
28686
|
const fetchReports = async (customFilters, dashboardFilters2, pageSize, forceCacheToRefresh = false) => {
|
|
27850
28687
|
if (!client || !sections) return;
|
|
28688
|
+
reportFetchAbortController.current?.abort();
|
|
28689
|
+
const abortController = new AbortController();
|
|
28690
|
+
reportFetchAbortController.current = abortController;
|
|
28691
|
+
const abortSignal = abortController.signal;
|
|
27851
28692
|
const allReports = Object.values(sections).flat();
|
|
27852
28693
|
const fetchStartTime = Date.now();
|
|
27853
28694
|
let totalCached = 0;
|
|
@@ -27916,6 +28757,12 @@ var useDashboard = (dashboardName, config) => {
|
|
|
27916
28757
|
eventTracking,
|
|
27917
28758
|
forceCacheToRefresh
|
|
27918
28759
|
);
|
|
28760
|
+
const cachedReport = {
|
|
28761
|
+
...reportInfo,
|
|
28762
|
+
...report2,
|
|
28763
|
+
id: reportId,
|
|
28764
|
+
pivot: reportInfo.pivot ?? report2.pivot
|
|
28765
|
+
};
|
|
27919
28766
|
if (reportRequestIds.current[reportId] !== requestId) {
|
|
27920
28767
|
return null;
|
|
27921
28768
|
}
|
|
@@ -27924,7 +28771,7 @@ var useDashboard = (dashboardName, config) => {
|
|
|
27924
28771
|
type: "UPDATE_REPORT",
|
|
27925
28772
|
id: reportId,
|
|
27926
28773
|
data: {
|
|
27927
|
-
...
|
|
28774
|
+
...cachedReport,
|
|
27928
28775
|
pagination,
|
|
27929
28776
|
triggerReload: false
|
|
27930
28777
|
}
|
|
@@ -27935,7 +28782,7 @@ var useDashboard = (dashboardName, config) => {
|
|
|
27935
28782
|
data: false
|
|
27936
28783
|
});
|
|
27937
28784
|
totalCached += 1;
|
|
27938
|
-
return
|
|
28785
|
+
return cachedReport;
|
|
27939
28786
|
}
|
|
27940
28787
|
}
|
|
27941
28788
|
if (cacheEnabled && !cacheCab.isCacheable(reportId)) {
|
|
@@ -27958,6 +28805,7 @@ var useDashboard = (dashboardName, config) => {
|
|
|
27958
28805
|
filters: allFilters,
|
|
27959
28806
|
getToken,
|
|
27960
28807
|
eventTracking,
|
|
28808
|
+
abortSignal,
|
|
27961
28809
|
usePivotTask,
|
|
27962
28810
|
overwriteCache: forceCacheToRefresh
|
|
27963
28811
|
});
|
|
@@ -27997,6 +28845,7 @@ var useDashboard = (dashboardName, config) => {
|
|
|
27997
28845
|
tenants,
|
|
27998
28846
|
filters: allFilters,
|
|
27999
28847
|
getToken,
|
|
28848
|
+
abortSignal,
|
|
28000
28849
|
additionalProcessing,
|
|
28001
28850
|
overwriteCache: forceCacheToRefresh
|
|
28002
28851
|
}).then(({ rows, rowCount, columns, fields }) => {
|
|
@@ -28049,7 +28898,32 @@ var useDashboard = (dashboardName, config) => {
|
|
|
28049
28898
|
return null;
|
|
28050
28899
|
}
|
|
28051
28900
|
}
|
|
28052
|
-
const
|
|
28901
|
+
const requestFilters = allFilters.map(
|
|
28902
|
+
(filter) => Object.fromEntries(
|
|
28903
|
+
Object.entries(filter).filter(([key]) => key !== "options")
|
|
28904
|
+
)
|
|
28905
|
+
);
|
|
28906
|
+
const queryKey = [
|
|
28907
|
+
"quill",
|
|
28908
|
+
"dashboard-report",
|
|
28909
|
+
reportId,
|
|
28910
|
+
{
|
|
28911
|
+
dashboardName,
|
|
28912
|
+
task: usePivotTask ? "pivot-template" : "report",
|
|
28913
|
+
client: {
|
|
28914
|
+
id: client.id ?? client.clientId,
|
|
28915
|
+
databaseType: client.databaseType,
|
|
28916
|
+
queryEndpoint: client.queryEndpoint,
|
|
28917
|
+
queryHeaders: client.queryHeaders,
|
|
28918
|
+
withCredentials: client.withCredentials
|
|
28919
|
+
},
|
|
28920
|
+
tenants,
|
|
28921
|
+
flags,
|
|
28922
|
+
filters: requestFilters,
|
|
28923
|
+
additionalProcessing: reportAdditionalProcessing
|
|
28924
|
+
}
|
|
28925
|
+
];
|
|
28926
|
+
const fetchDashboardReport = () => fetchReport({
|
|
28053
28927
|
reportId,
|
|
28054
28928
|
client,
|
|
28055
28929
|
tenants,
|
|
@@ -28058,10 +28932,23 @@ var useDashboard = (dashboardName, config) => {
|
|
|
28058
28932
|
filters: allFilters,
|
|
28059
28933
|
getToken,
|
|
28060
28934
|
eventTracking,
|
|
28935
|
+
abortSignal,
|
|
28061
28936
|
usePivotTask,
|
|
28062
|
-
overwriteCache: forceCacheToRefresh
|
|
28063
|
-
|
|
28937
|
+
overwriteCache: forceCacheToRefresh,
|
|
28938
|
+
shareRequest: !forceCacheToRefresh
|
|
28064
28939
|
});
|
|
28940
|
+
const result = forceCacheToRefresh ? await fetchDashboardReport() : await queryClient.fetchQuery({
|
|
28941
|
+
queryKey,
|
|
28942
|
+
queryFn: fetchDashboardReport,
|
|
28943
|
+
staleTime: reportStaleTimeMs,
|
|
28944
|
+
gcTime: Math.max(reportStaleTimeMs * 2, 10 * 60 * 1e3)
|
|
28945
|
+
});
|
|
28946
|
+
if (result.error) {
|
|
28947
|
+
queryClient.removeQueries({ queryKey, exact: true });
|
|
28948
|
+
} else if (forceCacheToRefresh) {
|
|
28949
|
+
queryClient.setQueryData(queryKey, result);
|
|
28950
|
+
}
|
|
28951
|
+
const { report, error } = result;
|
|
28065
28952
|
if (reportRequestIds.current[reportId] !== requestId) {
|
|
28066
28953
|
return null;
|
|
28067
28954
|
}
|
|
@@ -28093,6 +28980,7 @@ var useDashboard = (dashboardName, config) => {
|
|
|
28093
28980
|
tenants,
|
|
28094
28981
|
filters: allFilters,
|
|
28095
28982
|
getToken,
|
|
28983
|
+
abortSignal,
|
|
28096
28984
|
additionalProcessing,
|
|
28097
28985
|
overwriteCache: forceCacheToRefresh
|
|
28098
28986
|
}).then(({ rows, rowCount, columns, fields }) => {
|
|
@@ -28126,7 +29014,11 @@ var useDashboard = (dashboardName, config) => {
|
|
|
28126
29014
|
}
|
|
28127
29015
|
return report;
|
|
28128
29016
|
})
|
|
28129
|
-
)
|
|
29017
|
+
).catch((error) => {
|
|
29018
|
+
if (!(error instanceof Error) || error.name !== "AbortError") {
|
|
29019
|
+
throw error;
|
|
29020
|
+
}
|
|
29021
|
+
});
|
|
28130
29022
|
if (!loadedDashes.includes(dashboardName) || !cacheEnabled || forceCacheToRefresh) {
|
|
28131
29023
|
setLoadedDashes(
|
|
28132
29024
|
(prev) => prev.includes(dashboardName) ? prev : [...prev, dashboardName]
|
|
@@ -28147,6 +29039,7 @@ var useDashboard = (dashboardName, config) => {
|
|
|
28147
29039
|
applyFilters,
|
|
28148
29040
|
lastUpdated,
|
|
28149
29041
|
forceCacheRefresh,
|
|
29042
|
+
primeReportSource,
|
|
28150
29043
|
reload
|
|
28151
29044
|
};
|
|
28152
29045
|
};
|
|
@@ -36840,164 +37733,6 @@ function DashboardFilter2({
|
|
|
36840
37733
|
// src/Chart.tsx
|
|
36841
37734
|
init_paginationProcessing();
|
|
36842
37735
|
|
|
36843
|
-
// src/utils/cloudCacheValidation.ts
|
|
36844
|
-
var LIMIT_CLAUSE_REGEX = /^limit\b\s+(?:all|\d+|\$\d+|:[a-zA-Z_][a-zA-Z0-9_]*|\?)/i;
|
|
36845
|
-
var SQL_CONTENT_TO_IGNORE_REGEX = /'(?:''|[^'])*'|"(?:[^"]|"")*"|`[^`]*`|\[[^\]]*\]|--[^\n]*|\/\*[\s\S]*?\*\//g;
|
|
36846
|
-
function isWordChar(char) {
|
|
36847
|
-
if (!char) {
|
|
36848
|
-
return false;
|
|
36849
|
-
}
|
|
36850
|
-
return /[A-Za-z0-9_]/.test(char);
|
|
36851
|
-
}
|
|
36852
|
-
function getFinalSqlStatement(query) {
|
|
36853
|
-
const statements = query.split(";").map((statement) => statement.trim()).filter((statement) => statement.length > 0);
|
|
36854
|
-
return statements[statements.length - 1] ?? "";
|
|
36855
|
-
}
|
|
36856
|
-
function hasTopLevelLimitClause(statement) {
|
|
36857
|
-
let depth = 0;
|
|
36858
|
-
for (let i = 0; i < statement.length; i += 1) {
|
|
36859
|
-
const char = statement[i];
|
|
36860
|
-
if (char === "(") {
|
|
36861
|
-
depth += 1;
|
|
36862
|
-
continue;
|
|
36863
|
-
}
|
|
36864
|
-
if (char === ")") {
|
|
36865
|
-
depth = Math.max(0, depth - 1);
|
|
36866
|
-
continue;
|
|
36867
|
-
}
|
|
36868
|
-
if (depth !== 0) {
|
|
36869
|
-
continue;
|
|
36870
|
-
}
|
|
36871
|
-
const previousChar = i > 0 ? statement[i - 1] : void 0;
|
|
36872
|
-
if (isWordChar(previousChar)) {
|
|
36873
|
-
continue;
|
|
36874
|
-
}
|
|
36875
|
-
if (!LIMIT_CLAUSE_REGEX.test(statement.slice(i))) {
|
|
36876
|
-
continue;
|
|
36877
|
-
}
|
|
36878
|
-
return true;
|
|
36879
|
-
}
|
|
36880
|
-
return false;
|
|
36881
|
-
}
|
|
36882
|
-
function unwrapIdentifier(identifier) {
|
|
36883
|
-
if (!identifier) {
|
|
36884
|
-
return "";
|
|
36885
|
-
}
|
|
36886
|
-
const trimmed = identifier.trim();
|
|
36887
|
-
if (trimmed.length < 2) {
|
|
36888
|
-
return trimmed;
|
|
36889
|
-
}
|
|
36890
|
-
const startsAndEndsWithDoubleQuote = trimmed.startsWith('"') && trimmed.endsWith('"');
|
|
36891
|
-
const startsAndEndsWithSingleQuote = trimmed.startsWith("'") && trimmed.endsWith("'");
|
|
36892
|
-
const startsAndEndsWithBackticks = trimmed.startsWith("`") && trimmed.endsWith("`");
|
|
36893
|
-
const startsAndEndsWithBrackets = trimmed.startsWith("[") && trimmed.endsWith("]");
|
|
36894
|
-
if (startsAndEndsWithDoubleQuote || startsAndEndsWithSingleQuote || startsAndEndsWithBackticks || startsAndEndsWithBrackets) {
|
|
36895
|
-
return trimmed.slice(1, -1);
|
|
36896
|
-
}
|
|
36897
|
-
return trimmed;
|
|
36898
|
-
}
|
|
36899
|
-
function normalizeIdentifier(identifier) {
|
|
36900
|
-
return unwrapIdentifier(identifier).toLowerCase();
|
|
36901
|
-
}
|
|
36902
|
-
function hasRowFieldWithIdentifier(row, normalizedField) {
|
|
36903
|
-
if (!row || !normalizedField) {
|
|
36904
|
-
return false;
|
|
36905
|
-
}
|
|
36906
|
-
return Object.keys(row).some(
|
|
36907
|
-
(fieldName) => normalizeIdentifier(fieldName) === normalizedField
|
|
36908
|
-
);
|
|
36909
|
-
}
|
|
36910
|
-
function reportReferencesField(report, field, table) {
|
|
36911
|
-
const normalizedField = normalizeIdentifier(field);
|
|
36912
|
-
if (!normalizedField) {
|
|
36913
|
-
return false;
|
|
36914
|
-
}
|
|
36915
|
-
const referencedColumns = report?.referencedColumns ?? {};
|
|
36916
|
-
let entries = Object.entries(referencedColumns);
|
|
36917
|
-
if (entries.length === 0) {
|
|
36918
|
-
return false;
|
|
36919
|
-
}
|
|
36920
|
-
const normalizedTable = normalizeIdentifier(table);
|
|
36921
|
-
if (normalizedTable) {
|
|
36922
|
-
entries = entries.filter(
|
|
36923
|
-
([tableName]) => normalizeIdentifier(tableName) === normalizedTable
|
|
36924
|
-
);
|
|
36925
|
-
}
|
|
36926
|
-
const referencedFields = entries.flatMap(([, fields]) => fields ?? []);
|
|
36927
|
-
if (referencedFields.length === 0) {
|
|
36928
|
-
return false;
|
|
36929
|
-
}
|
|
36930
|
-
return referencedFields.some((referencedField) => {
|
|
36931
|
-
const normalizedReferencedField = normalizeIdentifier(referencedField);
|
|
36932
|
-
return normalizedReferencedField === normalizedField || normalizedReferencedField === "*";
|
|
36933
|
-
});
|
|
36934
|
-
}
|
|
36935
|
-
function isDateFieldMissingInReport(report) {
|
|
36936
|
-
if (!report?.dateField?.field || !report.dateField.table) {
|
|
36937
|
-
return false;
|
|
36938
|
-
}
|
|
36939
|
-
const dateField = report.dateField;
|
|
36940
|
-
if (!reportReferencesField(report, dateField.field, dateField.table)) {
|
|
36941
|
-
return true;
|
|
36942
|
-
}
|
|
36943
|
-
const firstRow = report.rows?.[0];
|
|
36944
|
-
if (!firstRow) {
|
|
36945
|
-
return false;
|
|
36946
|
-
}
|
|
36947
|
-
const normalizedDateField = normalizeIdentifier(dateField.field);
|
|
36948
|
-
const dateFieldExistsInFirstRow = hasRowFieldWithIdentifier(
|
|
36949
|
-
firstRow,
|
|
36950
|
-
normalizedDateField
|
|
36951
|
-
);
|
|
36952
|
-
return !dateFieldExistsInFirstRow;
|
|
36953
|
-
}
|
|
36954
|
-
function hasLimitClause(query) {
|
|
36955
|
-
if (!query) {
|
|
36956
|
-
return false;
|
|
36957
|
-
}
|
|
36958
|
-
const sanitizedQuery = query.replace(SQL_CONTENT_TO_IGNORE_REGEX, " ");
|
|
36959
|
-
const finalStatement = getFinalSqlStatement(sanitizedQuery);
|
|
36960
|
-
if (!finalStatement) {
|
|
36961
|
-
return false;
|
|
36962
|
-
}
|
|
36963
|
-
return hasTopLevelLimitClause(finalStatement);
|
|
36964
|
-
}
|
|
36965
|
-
function reportUsesLimitClause(report) {
|
|
36966
|
-
const queriesToInspect = report?.itemQuery && report.itemQuery.length > 0 ? report.itemQuery : report?.queryString ? [report.queryString] : [];
|
|
36967
|
-
return queriesToInspect.some(hasLimitClause);
|
|
36968
|
-
}
|
|
36969
|
-
function getMissingDashboardFilterFields({
|
|
36970
|
-
rows = [],
|
|
36971
|
-
dashboardFilters = []
|
|
36972
|
-
}) {
|
|
36973
|
-
const dateIndex = dashboardFilters.findIndex(
|
|
36974
|
-
(filter) => filter.filterType === "date_range"
|
|
36975
|
-
);
|
|
36976
|
-
const requiredFields = dashboardFilters.flatMap((filter, index) => {
|
|
36977
|
-
if (index === dateIndex || !filter.field) {
|
|
36978
|
-
return [];
|
|
36979
|
-
}
|
|
36980
|
-
const normalizedField = normalizeIdentifier(filter.field);
|
|
36981
|
-
if (!normalizedField) {
|
|
36982
|
-
return [];
|
|
36983
|
-
}
|
|
36984
|
-
return [
|
|
36985
|
-
{
|
|
36986
|
-
displayField: unwrapIdentifier(filter.field),
|
|
36987
|
-
normalizedField
|
|
36988
|
-
}
|
|
36989
|
-
];
|
|
36990
|
-
});
|
|
36991
|
-
const dedupedRequiredFields = requiredFields.filter(
|
|
36992
|
-
(field, index, fields) => fields.findIndex(
|
|
36993
|
-
(candidate) => candidate.normalizedField === field.normalizedField
|
|
36994
|
-
) === index
|
|
36995
|
-
);
|
|
36996
|
-
return dedupedRequiredFields.filter(
|
|
36997
|
-
({ normalizedField }) => rows.some((row) => !hasRowFieldWithIdentifier(row, normalizedField))
|
|
36998
|
-
).map(({ displayField }) => displayField);
|
|
36999
|
-
}
|
|
37000
|
-
|
|
37001
37736
|
// src/components/Dashboard/MetricComponent.tsx
|
|
37002
37737
|
init_dateRangePickerUtils();
|
|
37003
37738
|
import { useContext as useContext12 } from "react";
|
|
@@ -43707,7 +44442,7 @@ function StaticChart(props) {
|
|
|
43707
44442
|
pageLoading,
|
|
43708
44443
|
nextPage,
|
|
43709
44444
|
prevPage,
|
|
43710
|
-
sortRows:
|
|
44445
|
+
sortRows: sortRows3
|
|
43711
44446
|
} = useDashboardReportInternal(reportId);
|
|
43712
44447
|
const baseStyle = report?.chartType && CHART_TYPE_STYLES[report.chartType] ? CHART_TYPE_STYLES[report.chartType] : DEFAULT_STYLE;
|
|
43713
44448
|
const mergedStyle = className ? { ...containerStyle ?? {} } : { ...baseStyle, ...containerStyle ?? {} };
|
|
@@ -43727,7 +44462,7 @@ function StaticChart(props) {
|
|
|
43727
44462
|
}
|
|
43728
44463
|
};
|
|
43729
44464
|
const onSortChange = (sort) => {
|
|
43730
|
-
|
|
44465
|
+
sortRows3({
|
|
43731
44466
|
field: sort.field,
|
|
43732
44467
|
direction: sort.direction
|
|
43733
44468
|
});
|
|
@@ -45154,7 +45889,7 @@ var PivotModal = ({
|
|
|
45154
45889
|
setPivotRowField,
|
|
45155
45890
|
pivotColumnField,
|
|
45156
45891
|
setPivotColumnField,
|
|
45157
|
-
pivotAggregations,
|
|
45892
|
+
pivotAggregations: pivotAggregations2,
|
|
45158
45893
|
setPivotAggregations,
|
|
45159
45894
|
pivotSort,
|
|
45160
45895
|
setPivotSort,
|
|
@@ -45271,18 +46006,18 @@ var PivotModal = ({
|
|
|
45271
46006
|
columnField: pivotColumnField,
|
|
45272
46007
|
columnFieldType: columnTypes[pivotColumnField ?? ""],
|
|
45273
46008
|
dateBucket: pivotDateBucket,
|
|
45274
|
-
aggregations:
|
|
46009
|
+
aggregations: pivotAggregations2?.map((p) => ({
|
|
45275
46010
|
valueField: p.valueField,
|
|
45276
46011
|
valueFieldType: columnTypes[p.valueField ?? ""],
|
|
45277
46012
|
valueField2: p.valueField2,
|
|
45278
46013
|
valueField2Type: columnTypes[p.valueField2 ?? ""],
|
|
45279
46014
|
aggregationType: p.aggregationType
|
|
45280
46015
|
})),
|
|
45281
|
-
valueField:
|
|
45282
|
-
valueFieldType: columnTypes[
|
|
45283
|
-
valueField2:
|
|
45284
|
-
valueField2Type: columnTypes[
|
|
45285
|
-
aggregationType:
|
|
46016
|
+
valueField: pivotAggregations2?.[0]?.valueField,
|
|
46017
|
+
valueFieldType: columnTypes[pivotAggregations2?.[0]?.valueField ?? ""],
|
|
46018
|
+
valueField2: pivotAggregations2?.[0]?.valueField2,
|
|
46019
|
+
valueField2Type: columnTypes[pivotAggregations2?.[0]?.valueField2 ?? ""],
|
|
46020
|
+
aggregationType: pivotAggregations2?.[0]?.aggregationType
|
|
45286
46021
|
});
|
|
45287
46022
|
const getResolvedDateBucket = (pivot) => resolvePivotDateBucket({
|
|
45288
46023
|
pivot,
|
|
@@ -45398,7 +46133,7 @@ var PivotModal = ({
|
|
|
45398
46133
|
}, [showUpdatePivot, isOpen]);
|
|
45399
46134
|
useEffect21(() => {
|
|
45400
46135
|
const fetchPivotData = async () => {
|
|
45401
|
-
if (pivotRowField && data && columns &&
|
|
46136
|
+
if (pivotRowField && data && columns && pivotAggregations2?.every((p) => p?.valueField && p?.aggregationType)) {
|
|
45402
46137
|
const pivot = buildCurrentPivot();
|
|
45403
46138
|
try {
|
|
45404
46139
|
const { rows, columns: columns2 } = await generatePivotTable({
|
|
@@ -45621,17 +46356,17 @@ var PivotModal = ({
|
|
|
45621
46356
|
};
|
|
45622
46357
|
const onCommitPivot = () => {
|
|
45623
46358
|
const errors2 = [];
|
|
45624
|
-
if ((
|
|
46359
|
+
if ((pivotAggregations2?.length ?? 0) === 0) {
|
|
45625
46360
|
errors2.push("You must have at least one aggregation");
|
|
45626
46361
|
}
|
|
45627
|
-
if (
|
|
46362
|
+
if (pivotAggregations2.some(
|
|
45628
46363
|
(p) => !p.valueField && p.aggregationType !== "count" && p.aggregationType !== "percentage"
|
|
45629
46364
|
)) {
|
|
45630
46365
|
errors2.push(
|
|
45631
46366
|
"Value field cannot be empty when aggregation is not 'count' or 'percentage'"
|
|
45632
46367
|
);
|
|
45633
46368
|
}
|
|
45634
|
-
if (
|
|
46369
|
+
if (pivotAggregations2.some((p) => !p.aggregationType)) {
|
|
45635
46370
|
errors2.push("Aggregation cannot be empty");
|
|
45636
46371
|
}
|
|
45637
46372
|
if (pivotRowField && !columnsToShow[pivotRowField]) {
|
|
@@ -45643,7 +46378,7 @@ var PivotModal = ({
|
|
|
45643
46378
|
if (showLimitInput && limitInput && !Number.isInteger(Number(limitInput))) {
|
|
45644
46379
|
errors2.push("Limit must be an integer");
|
|
45645
46380
|
}
|
|
45646
|
-
if (errors2.length === 0 &&
|
|
46381
|
+
if (errors2.length === 0 && pivotAggregations2?.every(
|
|
45647
46382
|
(p) => p.aggregationType && (p.valueField || p.aggregationType === "count" || p.aggregationType === "percentage")
|
|
45648
46383
|
)) {
|
|
45649
46384
|
const sort = showSortInput && !!sortFieldInput && !!sortDirectionInput;
|
|
@@ -45987,7 +46722,7 @@ var PivotModal = ({
|
|
|
45987
46722
|
setPivotColumnField(void 0);
|
|
45988
46723
|
setPivotDateBucket(void 0);
|
|
45989
46724
|
setPivotAggregations(
|
|
45990
|
-
|
|
46725
|
+
pivotAggregations2.map((agg) => {
|
|
45991
46726
|
return {
|
|
45992
46727
|
...agg,
|
|
45993
46728
|
aggregationType: agg.aggregationType === "percentage" ? void 0 : agg.aggregationType
|
|
@@ -46007,9 +46742,9 @@ var PivotModal = ({
|
|
|
46007
46742
|
if (!value && agg.valueField === agg.valueField2) {
|
|
46008
46743
|
agg.valueField2 = void 0;
|
|
46009
46744
|
setPivotAggregations([
|
|
46010
|
-
...
|
|
46011
|
-
{ ...
|
|
46012
|
-
...
|
|
46745
|
+
...pivotAggregations2.slice(0, index),
|
|
46746
|
+
{ ...pivotAggregations2[index], valueField2: void 0 },
|
|
46747
|
+
...pivotAggregations2.slice(index + 1)
|
|
46013
46748
|
]);
|
|
46014
46749
|
}
|
|
46015
46750
|
});
|
|
@@ -46430,7 +47165,7 @@ var PivotModal = ({
|
|
|
46430
47165
|
/* @__PURE__ */ jsx66("div", { style: { width: 200 }, children: /* @__PURE__ */ jsx66(SubheaderComponent, { label: "Aggregation Type" }) }),
|
|
46431
47166
|
/* @__PURE__ */ jsx66("div", { style: { width: 200 }, children: /* @__PURE__ */ jsx66(SubheaderComponent, { label: "Value Field" }) })
|
|
46432
47167
|
] }),
|
|
46433
|
-
|
|
47168
|
+
pivotAggregations2?.map((agg, index) => /* @__PURE__ */ jsxs47(PivotRowContainer, { children: [
|
|
46434
47169
|
/* @__PURE__ */ jsx66(
|
|
46435
47170
|
SelectComponent,
|
|
46436
47171
|
{
|
|
@@ -46438,12 +47173,12 @@ var PivotModal = ({
|
|
|
46438
47173
|
value: agg.aggregationType ?? "",
|
|
46439
47174
|
onChange: (e) => {
|
|
46440
47175
|
const newAgg = [
|
|
46441
|
-
...
|
|
47176
|
+
...pivotAggregations2.slice(0, index),
|
|
46442
47177
|
{
|
|
46443
47178
|
...agg,
|
|
46444
47179
|
aggregationType: e.target.value === "" ? void 0 : e.target.value
|
|
46445
47180
|
},
|
|
46446
|
-
...
|
|
47181
|
+
...pivotAggregations2.slice(index + 1)
|
|
46447
47182
|
];
|
|
46448
47183
|
pivotFieldChange("aggregations", newAgg);
|
|
46449
47184
|
setPivotAggregations(newAgg);
|
|
@@ -46470,12 +47205,12 @@ var PivotModal = ({
|
|
|
46470
47205
|
value: agg.valueField ?? "",
|
|
46471
47206
|
onChange: (e) => {
|
|
46472
47207
|
const newAgg = [
|
|
46473
|
-
...
|
|
47208
|
+
...pivotAggregations2.slice(0, index),
|
|
46474
47209
|
{
|
|
46475
47210
|
...agg,
|
|
46476
47211
|
valueField: e.target.value === "" ? void 0 : e.target.value
|
|
46477
47212
|
},
|
|
46478
|
-
...
|
|
47213
|
+
...pivotAggregations2.slice(index + 1)
|
|
46479
47214
|
];
|
|
46480
47215
|
pivotFieldChange("aggregations", newAgg);
|
|
46481
47216
|
setPivotAggregations(newAgg);
|
|
@@ -46503,8 +47238,8 @@ var PivotModal = ({
|
|
|
46503
47238
|
{
|
|
46504
47239
|
onClick: () => {
|
|
46505
47240
|
setPivotAggregations([
|
|
46506
|
-
...
|
|
46507
|
-
...
|
|
47241
|
+
...pivotAggregations2.slice(0, index),
|
|
47242
|
+
...pivotAggregations2.slice(index + 1)
|
|
46508
47243
|
]);
|
|
46509
47244
|
}
|
|
46510
47245
|
}
|
|
@@ -46531,7 +47266,7 @@ var PivotModal = ({
|
|
|
46531
47266
|
label: "Add Aggregation",
|
|
46532
47267
|
onClick: () => {
|
|
46533
47268
|
setPivotAggregations([
|
|
46534
|
-
...
|
|
47269
|
+
...pivotAggregations2,
|
|
46535
47270
|
{
|
|
46536
47271
|
aggregationType: void 0,
|
|
46537
47272
|
valueField: void 0,
|
|
@@ -46765,7 +47500,7 @@ var PivotModal = ({
|
|
|
46765
47500
|
label: "Save",
|
|
46766
47501
|
disabled: showSortInput && (!sortFieldInput || !(samplePivotTable?.columns ?? []).some(
|
|
46767
47502
|
(c) => c.field === sortFieldInput
|
|
46768
|
-
) || !sortDirectionInput) || !(
|
|
47503
|
+
) || !sortDirectionInput) || !(pivotAggregations2?.length > 0) || pivotAggregations2.some(
|
|
46769
47504
|
(agg) => !agg.aggregationType || !agg.valueField && agg.aggregationType !== "count" && (agg.aggregationType !== "percentage" || !pivotRowField || pivotColumnField)
|
|
46770
47505
|
)
|
|
46771
47506
|
}
|
|
@@ -48747,7 +49482,7 @@ function ChartBuilder({
|
|
|
48747
49482
|
const [pivotColumnField, setPivotColumnField] = useState31(
|
|
48748
49483
|
report?.pivot?.columnField
|
|
48749
49484
|
);
|
|
48750
|
-
const [
|
|
49485
|
+
const [pivotAggregations2, setPivotAggregations] = useState31(
|
|
48751
49486
|
report?.pivot?.aggregations ?? [
|
|
48752
49487
|
{
|
|
48753
49488
|
valueField: report?.pivot?.valueField,
|
|
@@ -50558,7 +51293,7 @@ function ChartBuilder({
|
|
|
50558
51293
|
setPivotRowField,
|
|
50559
51294
|
pivotColumnField,
|
|
50560
51295
|
setPivotColumnField,
|
|
50561
|
-
pivotAggregations,
|
|
51296
|
+
pivotAggregations: pivotAggregations2,
|
|
50562
51297
|
pivotSort,
|
|
50563
51298
|
setPivotSort,
|
|
50564
51299
|
pivotLimit,
|
|
@@ -54203,7 +54938,7 @@ var useReportBuilderInternal = ({
|
|
|
54203
54938
|
const [pivotColumnField, setPivotColumnField] = useState34(
|
|
54204
54939
|
void 0
|
|
54205
54940
|
);
|
|
54206
|
-
const [
|
|
54941
|
+
const [pivotAggregations2, setPivotAggregations] = useState34([]);
|
|
54207
54942
|
const [pivotDateBucket, setPivotDateBucket] = useState34(void 0);
|
|
54208
54943
|
const [pivotLimit, setPivotLimit] = useState34(void 0);
|
|
54209
54944
|
const [pivotSort, setPivotSort] = useState34(void 0);
|
|
@@ -54531,7 +55266,7 @@ var useReportBuilderInternal = ({
|
|
|
54531
55266
|
if (changeField === "" || changeField === void 0) {
|
|
54532
55267
|
setPivotColumnField(void 0);
|
|
54533
55268
|
setPivotAggregations(
|
|
54534
|
-
|
|
55269
|
+
pivotAggregations2.map((agg) => ({
|
|
54535
55270
|
...agg,
|
|
54536
55271
|
aggregationType: agg.aggregationType === "percentage" ? void 0 : agg.aggregationType
|
|
54537
55272
|
}))
|
|
@@ -55447,7 +56182,7 @@ var useReportBuilderInternal = ({
|
|
|
55447
56182
|
pivotData,
|
|
55448
56183
|
pivotRowField,
|
|
55449
56184
|
pivotColumnField,
|
|
55450
|
-
pivotAggregations,
|
|
56185
|
+
pivotAggregations: pivotAggregations2,
|
|
55451
56186
|
pivotLimit,
|
|
55452
56187
|
pivotSort,
|
|
55453
56188
|
pivotDateBucket,
|
|
@@ -56588,7 +57323,7 @@ function PivotForm({
|
|
|
56588
57323
|
setPivotRowField,
|
|
56589
57324
|
pivotColumnField,
|
|
56590
57325
|
setPivotColumnField,
|
|
56591
|
-
pivotAggregations,
|
|
57326
|
+
pivotAggregations: pivotAggregations2,
|
|
56592
57327
|
setPivotAggregations,
|
|
56593
57328
|
pivotLimit,
|
|
56594
57329
|
setPivotLimit,
|
|
@@ -56697,7 +57432,7 @@ function PivotForm({
|
|
|
56697
57432
|
gap: 24
|
|
56698
57433
|
},
|
|
56699
57434
|
children: [
|
|
56700
|
-
|
|
57435
|
+
pivotAggregations2.map((pivotAggregation, index) => /* @__PURE__ */ jsxs56(
|
|
56701
57436
|
"div",
|
|
56702
57437
|
{
|
|
56703
57438
|
style: {
|
|
@@ -56724,12 +57459,12 @@ function PivotForm({
|
|
|
56724
57459
|
value: pivotAggregation.aggregationType,
|
|
56725
57460
|
onChange: (e) => {
|
|
56726
57461
|
setPivotAggregations([
|
|
56727
|
-
...
|
|
57462
|
+
...pivotAggregations2.slice(0, index),
|
|
56728
57463
|
{
|
|
56729
|
-
...
|
|
57464
|
+
...pivotAggregations2[index],
|
|
56730
57465
|
aggregationType: e.target.value === "" ? void 0 : e.target.value
|
|
56731
57466
|
},
|
|
56732
|
-
...
|
|
57467
|
+
...pivotAggregations2.slice(index + 1)
|
|
56733
57468
|
]);
|
|
56734
57469
|
},
|
|
56735
57470
|
options: [
|
|
@@ -56755,12 +57490,12 @@ function PivotForm({
|
|
|
56755
57490
|
value: pivotAggregation.valueField,
|
|
56756
57491
|
onChange: (e) => {
|
|
56757
57492
|
setPivotAggregations([
|
|
56758
|
-
...
|
|
57493
|
+
...pivotAggregations2.slice(0, index),
|
|
56759
57494
|
{
|
|
56760
|
-
...
|
|
57495
|
+
...pivotAggregations2[index],
|
|
56761
57496
|
valueField: e.target.value === "" ? void 0 : e.target.value
|
|
56762
57497
|
},
|
|
56763
|
-
...
|
|
57498
|
+
...pivotAggregations2.slice(index + 1)
|
|
56764
57499
|
]);
|
|
56765
57500
|
},
|
|
56766
57501
|
isLoading: uniqueValuesIsLoading,
|
|
@@ -56783,8 +57518,8 @@ function PivotForm({
|
|
|
56783
57518
|
{
|
|
56784
57519
|
onClick: () => {
|
|
56785
57520
|
setPivotAggregations([
|
|
56786
|
-
...
|
|
56787
|
-
...
|
|
57521
|
+
...pivotAggregations2.slice(0, index),
|
|
57522
|
+
...pivotAggregations2.slice(index + 1)
|
|
56788
57523
|
]);
|
|
56789
57524
|
}
|
|
56790
57525
|
}
|
|
@@ -56798,7 +57533,7 @@ function PivotForm({
|
|
|
56798
57533
|
{
|
|
56799
57534
|
onClick: () => {
|
|
56800
57535
|
setPivotAggregations([
|
|
56801
|
-
...
|
|
57536
|
+
...pivotAggregations2,
|
|
56802
57537
|
{
|
|
56803
57538
|
valueField: void 0,
|
|
56804
57539
|
aggregationType: void 0
|
|
@@ -58844,7 +59579,7 @@ function ChartEditor({
|
|
|
58844
59579
|
}
|
|
58845
59580
|
|
|
58846
59581
|
// src/Chat.tsx
|
|
58847
|
-
import { useContext as useContext37, useEffect as
|
|
59582
|
+
import { useContext as useContext37, useEffect as useEffect33, useRef as useRef25, useState as useState43 } from "react";
|
|
58848
59583
|
|
|
58849
59584
|
// src/ChatChartCard.tsx
|
|
58850
59585
|
import { useMemo as useMemo34 } from "react";
|
|
@@ -58855,14 +59590,19 @@ init_ReportBuilder();
|
|
|
58855
59590
|
import {
|
|
58856
59591
|
useCallback as useCallback5,
|
|
58857
59592
|
useContext as useContext36,
|
|
58858
|
-
useEffect as
|
|
59593
|
+
useEffect as useEffect32,
|
|
58859
59594
|
useLayoutEffect as useLayoutEffect4,
|
|
58860
59595
|
useMemo as useMemo33,
|
|
58861
59596
|
useReducer as useReducer2,
|
|
58862
59597
|
useRef as useRef24,
|
|
58863
|
-
useState as
|
|
59598
|
+
useState as useState42
|
|
58864
59599
|
} from "react";
|
|
58865
|
-
import {
|
|
59600
|
+
import {
|
|
59601
|
+
keepPreviousData,
|
|
59602
|
+
useMutation,
|
|
59603
|
+
useQuery,
|
|
59604
|
+
useQueryClient as useQueryClient2
|
|
59605
|
+
} from "@tanstack/react-query";
|
|
58866
59606
|
init_util();
|
|
58867
59607
|
init_columnType();
|
|
58868
59608
|
init_columnProcessing();
|
|
@@ -60046,6 +60786,20 @@ function useFormReducer(state, action) {
|
|
|
60046
60786
|
}
|
|
60047
60787
|
}
|
|
60048
60788
|
|
|
60789
|
+
// src/hooks/useForm.refreshDebounce.ts
|
|
60790
|
+
import { useEffect as useEffect31, useState as useState41 } from "react";
|
|
60791
|
+
var REPORT_REFRESH_DEBOUNCE_MS = 200;
|
|
60792
|
+
function useDebouncedRefreshInput(value, delayMs = REPORT_REFRESH_DEBOUNCE_MS) {
|
|
60793
|
+
const [debouncedValue, setDebouncedValue] = useState41(value);
|
|
60794
|
+
useEffect31(() => {
|
|
60795
|
+
const timeout = setTimeout(() => {
|
|
60796
|
+
setDebouncedValue(value);
|
|
60797
|
+
}, delayMs);
|
|
60798
|
+
return () => clearTimeout(timeout);
|
|
60799
|
+
}, [delayMs, value]);
|
|
60800
|
+
return debouncedValue;
|
|
60801
|
+
}
|
|
60802
|
+
|
|
60049
60803
|
// src/utils/pivotDateBuckets.ts
|
|
60050
60804
|
import {
|
|
60051
60805
|
eachDayOfInterval as eachDayOfInterval3,
|
|
@@ -60077,10 +60831,252 @@ function buildPivotDateBucketStarts(range, bucket) {
|
|
|
60077
60831
|
);
|
|
60078
60832
|
}
|
|
60079
60833
|
|
|
60834
|
+
// src/utils/cacheCabReportResolver.ts
|
|
60835
|
+
init_inMemoryPivotEngine();
|
|
60836
|
+
var availableRowKeys = (report) => {
|
|
60837
|
+
const keys = /* @__PURE__ */ new Set();
|
|
60838
|
+
for (const row of report.rows?.slice(0, 10) ?? []) {
|
|
60839
|
+
Object.keys(row).forEach((key) => keys.add(key));
|
|
60840
|
+
}
|
|
60841
|
+
for (const column of report.columnInternal ?? []) {
|
|
60842
|
+
if (column.field) keys.add(column.field);
|
|
60843
|
+
}
|
|
60844
|
+
for (const column of report.reportBuilderState?.columns ?? []) {
|
|
60845
|
+
if (column.field) keys.add(column.field);
|
|
60846
|
+
if (column.alias) keys.add(column.alias);
|
|
60847
|
+
}
|
|
60848
|
+
return keys;
|
|
60849
|
+
};
|
|
60850
|
+
var createFieldResolver = (report) => {
|
|
60851
|
+
const keys = availableRowKeys(report);
|
|
60852
|
+
return (field, table) => {
|
|
60853
|
+
const matchingColumns = (report.reportBuilderState?.columns ?? []).filter(
|
|
60854
|
+
(column) => column.field === field && (!table || !column.table || column.table === table)
|
|
60855
|
+
);
|
|
60856
|
+
const candidates = [
|
|
60857
|
+
...matchingColumns.map((column) => column.alias).filter(Boolean),
|
|
60858
|
+
field,
|
|
60859
|
+
table ? `${table}.${field}` : void 0,
|
|
60860
|
+
table ? `${table}__${field}` : void 0,
|
|
60861
|
+
table ? `${table}_${field}` : void 0
|
|
60862
|
+
].filter((candidate) => Boolean(candidate));
|
|
60863
|
+
return candidates.find((candidate) => keys.has(candidate));
|
|
60864
|
+
};
|
|
60865
|
+
};
|
|
60866
|
+
var pivotAggregations = (pivot) => pivot.aggregations ?? (pivot.aggregationType ? [
|
|
60867
|
+
{
|
|
60868
|
+
aggregationType: pivot.aggregationType,
|
|
60869
|
+
valueField: pivot.valueField,
|
|
60870
|
+
valueField2: pivot.valueField2,
|
|
60871
|
+
valueFieldType: pivot.valueFieldType,
|
|
60872
|
+
valueField2Type: pivot.valueField2Type
|
|
60873
|
+
}
|
|
60874
|
+
] : []);
|
|
60875
|
+
var resolvePivot = (pivot, resolveField) => {
|
|
60876
|
+
const rowField = pivot.rowField ? resolveField(pivot.rowField, pivot.rowFieldTable) : void 0;
|
|
60877
|
+
const columnField = pivot.columnField ? resolveField(pivot.columnField, pivot.columnFieldTable) : void 0;
|
|
60878
|
+
if (pivot.rowField && !rowField || pivot.columnField && !columnField) {
|
|
60879
|
+
return null;
|
|
60880
|
+
}
|
|
60881
|
+
const aggregations = pivotAggregations(pivot).map((aggregation) => ({
|
|
60882
|
+
...aggregation,
|
|
60883
|
+
valueField: aggregation.valueField ? resolveField(aggregation.valueField, aggregation.valueFieldTable) : void 0,
|
|
60884
|
+
valueField2: aggregation.valueField2 ? resolveField(aggregation.valueField2, aggregation.valueFieldTable) : void 0
|
|
60885
|
+
}));
|
|
60886
|
+
if (aggregations.some(
|
|
60887
|
+
(aggregation, index) => pivotAggregations(pivot)[index]?.valueField && !aggregation.valueField || pivotAggregations(pivot)[index]?.valueField2 && !aggregation.valueField2
|
|
60888
|
+
)) {
|
|
60889
|
+
return null;
|
|
60890
|
+
}
|
|
60891
|
+
return {
|
|
60892
|
+
...pivot,
|
|
60893
|
+
rowField,
|
|
60894
|
+
columnField,
|
|
60895
|
+
aggregations,
|
|
60896
|
+
aggregationType: void 0,
|
|
60897
|
+
valueField: void 0,
|
|
60898
|
+
valueField2: void 0,
|
|
60899
|
+
valueFieldType: void 0,
|
|
60900
|
+
valueField2Type: void 0
|
|
60901
|
+
};
|
|
60902
|
+
};
|
|
60903
|
+
var sortRows2 = (rows, state, resolveField) => {
|
|
60904
|
+
if (!state.sort.length) return rows;
|
|
60905
|
+
return [...rows].sort((left, right) => {
|
|
60906
|
+
for (const sort of state.sort) {
|
|
60907
|
+
const key = resolveField(sort.field);
|
|
60908
|
+
if (!key) continue;
|
|
60909
|
+
const a = left[key];
|
|
60910
|
+
const b = right[key];
|
|
60911
|
+
if (a === b) continue;
|
|
60912
|
+
const comparison = a == null ? -1 : b == null ? 1 : a < b ? -1 : 1;
|
|
60913
|
+
return sort.direction.toLowerCase() === "desc" ? -comparison : comparison;
|
|
60914
|
+
}
|
|
60915
|
+
return 0;
|
|
60916
|
+
});
|
|
60917
|
+
};
|
|
60918
|
+
var buildUniqueValues = (report, resolveField) => {
|
|
60919
|
+
const result = {};
|
|
60920
|
+
const stringColumns = (report.columnInternal ?? []).filter(
|
|
60921
|
+
(column) => column.jsType === "string" || /char|text|string|uuid/i.test(column.fieldType ?? "")
|
|
60922
|
+
);
|
|
60923
|
+
for (const column of stringColumns) {
|
|
60924
|
+
const table = column.table ?? "";
|
|
60925
|
+
const key = resolveField(column.field, column.table);
|
|
60926
|
+
if (!key) continue;
|
|
60927
|
+
const values = /* @__PURE__ */ new Set();
|
|
60928
|
+
for (const row of report.rows ?? []) {
|
|
60929
|
+
const value = row[key];
|
|
60930
|
+
if (value !== null && value !== void 0) values.add(String(value));
|
|
60931
|
+
}
|
|
60932
|
+
result[table] ??= {};
|
|
60933
|
+
result[table][column.field] = [...values].sort();
|
|
60934
|
+
}
|
|
60935
|
+
return result;
|
|
60936
|
+
};
|
|
60937
|
+
function resolveReportFromCacheCab({
|
|
60938
|
+
snapshot,
|
|
60939
|
+
reportBuilderState,
|
|
60940
|
+
filters,
|
|
60941
|
+
pivot = reportBuilderState?.pivot ?? null,
|
|
60942
|
+
operation = "table",
|
|
60943
|
+
rowLimit
|
|
60944
|
+
}) {
|
|
60945
|
+
if (!snapshot) return { resolved: false, reason: "cache_miss" };
|
|
60946
|
+
if (!snapshot.complete) {
|
|
60947
|
+
return {
|
|
60948
|
+
resolved: false,
|
|
60949
|
+
reason: "incomplete_cache",
|
|
60950
|
+
details: { snapshotReason: snapshot.reason }
|
|
60951
|
+
};
|
|
60952
|
+
}
|
|
60953
|
+
const state = reportBuilderState ?? snapshot.report.reportBuilderState;
|
|
60954
|
+
if (!state) return { resolved: false, reason: "missing_builder_state" };
|
|
60955
|
+
const resolveField = createFieldResolver(snapshot.report);
|
|
60956
|
+
const missingFields = [];
|
|
60957
|
+
state.columns.forEach((column) => {
|
|
60958
|
+
if (!resolveField(column.field, column.table)) {
|
|
60959
|
+
missingFields.push({
|
|
60960
|
+
role: "column",
|
|
60961
|
+
field: column.field,
|
|
60962
|
+
table: column.table
|
|
60963
|
+
});
|
|
60964
|
+
}
|
|
60965
|
+
});
|
|
60966
|
+
filters.forEach((filter) => {
|
|
60967
|
+
if (filter.field && !resolveField(filter.field, filter.table)) {
|
|
60968
|
+
missingFields.push({
|
|
60969
|
+
role: "filter",
|
|
60970
|
+
field: filter.field,
|
|
60971
|
+
table: filter.table
|
|
60972
|
+
});
|
|
60973
|
+
}
|
|
60974
|
+
});
|
|
60975
|
+
if (pivot?.rowField && !resolveField(pivot.rowField, pivot.rowFieldTable)) {
|
|
60976
|
+
missingFields.push({
|
|
60977
|
+
role: "pivot-row",
|
|
60978
|
+
field: pivot.rowField,
|
|
60979
|
+
table: pivot.rowFieldTable
|
|
60980
|
+
});
|
|
60981
|
+
}
|
|
60982
|
+
if (pivot?.columnField && !resolveField(pivot.columnField, pivot.columnFieldTable)) {
|
|
60983
|
+
missingFields.push({
|
|
60984
|
+
role: "pivot-column",
|
|
60985
|
+
field: pivot.columnField,
|
|
60986
|
+
table: pivot.columnFieldTable
|
|
60987
|
+
});
|
|
60988
|
+
}
|
|
60989
|
+
if (pivot) {
|
|
60990
|
+
pivotAggregations(pivot).forEach((aggregation) => {
|
|
60991
|
+
[
|
|
60992
|
+
[aggregation.valueField, aggregation.valueFieldTable],
|
|
60993
|
+
[aggregation.valueField2, aggregation.valueFieldTable]
|
|
60994
|
+
].forEach(([field, table]) => {
|
|
60995
|
+
if (field && !resolveField(field, table)) {
|
|
60996
|
+
missingFields.push({
|
|
60997
|
+
role: "aggregation",
|
|
60998
|
+
field,
|
|
60999
|
+
table
|
|
61000
|
+
});
|
|
61001
|
+
}
|
|
61002
|
+
});
|
|
61003
|
+
});
|
|
61004
|
+
}
|
|
61005
|
+
const resolvedPivot = pivot ? resolvePivot(pivot, resolveField) : null;
|
|
61006
|
+
if (missingFields.length > 0 || pivot && !resolvedPivot) {
|
|
61007
|
+
return {
|
|
61008
|
+
resolved: false,
|
|
61009
|
+
reason: "missing_field",
|
|
61010
|
+
details: { missingFields }
|
|
61011
|
+
};
|
|
61012
|
+
}
|
|
61013
|
+
const filteredRows = applyFiltersInMemory(
|
|
61014
|
+
snapshot.report.rows ?? [],
|
|
61015
|
+
filters,
|
|
61016
|
+
{
|
|
61017
|
+
columns: snapshot.report.columnInternal,
|
|
61018
|
+
fieldKeyResolver: resolveField
|
|
61019
|
+
}
|
|
61020
|
+
);
|
|
61021
|
+
const sortedRows = operation === "unique-values" ? [] : sortRows2(filteredRows, state, resolveField);
|
|
61022
|
+
const effectiveRowLimit = Math.min(
|
|
61023
|
+
state.limit?.value ?? Number.MAX_SAFE_INTEGER,
|
|
61024
|
+
rowLimit ?? Number.MAX_SAFE_INTEGER
|
|
61025
|
+
);
|
|
61026
|
+
const limitedRows = sortedRows.length > effectiveRowLimit ? sortedRows.slice(0, effectiveRowLimit) : sortedRows;
|
|
61027
|
+
const pivotRows = resolvedPivot ? applyPivotInMemory(filteredRows, resolvedPivot, filters) : void 0;
|
|
61028
|
+
const pivotColumns = resolvedPivot ? generatePivotColumnsInMemory({
|
|
61029
|
+
pivot: resolvedPivot,
|
|
61030
|
+
pivotRows: pivotRows ?? [],
|
|
61031
|
+
sourceColumns: snapshot.report.columnInternal
|
|
61032
|
+
}) : void 0;
|
|
61033
|
+
const requestedRowField = pivot?.rowField;
|
|
61034
|
+
const resolvedRowField = resolvedPivot?.rowField;
|
|
61035
|
+
const normalizedPivotRows = requestedRowField && resolvedRowField && requestedRowField !== resolvedRowField ? pivotRows?.map((row) => ({
|
|
61036
|
+
...row,
|
|
61037
|
+
[requestedRowField]: row[resolvedRowField]
|
|
61038
|
+
})) : pivotRows;
|
|
61039
|
+
const normalizedPivotColumns = pivotColumns?.map(
|
|
61040
|
+
(column) => requestedRowField && resolvedRowField && column.field === resolvedRowField ? { ...column, field: requestedRowField } : column
|
|
61041
|
+
);
|
|
61042
|
+
return {
|
|
61043
|
+
resolved: true,
|
|
61044
|
+
report: {
|
|
61045
|
+
...snapshot.report,
|
|
61046
|
+
rows: limitedRows,
|
|
61047
|
+
rowCount: filteredRows.length,
|
|
61048
|
+
reportBuilderState: { ...state, pivot },
|
|
61049
|
+
pivot,
|
|
61050
|
+
pivotRows: normalizedPivotRows,
|
|
61051
|
+
pivotColumns: normalizedPivotColumns,
|
|
61052
|
+
pivotRowCount: normalizedPivotRows?.length,
|
|
61053
|
+
pivotResultRowField: requestedRowField,
|
|
61054
|
+
pivotResultSourceRowField: requestedRowField,
|
|
61055
|
+
...operation === "unique-values" ? {
|
|
61056
|
+
uniqueStringsByTable: buildUniqueValues(
|
|
61057
|
+
snapshot.report,
|
|
61058
|
+
resolveField
|
|
61059
|
+
)
|
|
61060
|
+
} : {},
|
|
61061
|
+
filtersApplied: filters
|
|
61062
|
+
}
|
|
61063
|
+
};
|
|
61064
|
+
}
|
|
61065
|
+
|
|
60080
61066
|
// src/hooks/useForm.queries.ts
|
|
60081
61067
|
var QUERY_KEY_UNDEFINED = "__undefined__";
|
|
60082
61068
|
var QUERY_KEY_FUNCTION = "__function__";
|
|
60083
61069
|
var QUERY_KEY_BIGINT = "__bigint__";
|
|
61070
|
+
function createFilterUniqueValuesReportBuilderState(source, columns) {
|
|
61071
|
+
return {
|
|
61072
|
+
tables: source.tables,
|
|
61073
|
+
columns,
|
|
61074
|
+
filterStack: [],
|
|
61075
|
+
pivot: null,
|
|
61076
|
+
sort: [],
|
|
61077
|
+
limit: null
|
|
61078
|
+
};
|
|
61079
|
+
}
|
|
60084
61080
|
function stableSerializeForQueryKey(value) {
|
|
60085
61081
|
try {
|
|
60086
61082
|
return JSON.stringify(value, (_key, nestedValue) => {
|
|
@@ -60141,6 +61137,7 @@ function createUseFormPivotTableDataRefreshQueryKey(input) {
|
|
|
60141
61137
|
"pivot-table-data-refresh",
|
|
60142
61138
|
input.reportId,
|
|
60143
61139
|
input.reportBuilderStateHash,
|
|
61140
|
+
input.pageSize,
|
|
60144
61141
|
input.tenantHash,
|
|
60145
61142
|
input.clientHash
|
|
60146
61143
|
];
|
|
@@ -60167,13 +61164,36 @@ function createUseFormReportNameQueryKey(input) {
|
|
|
60167
61164
|
];
|
|
60168
61165
|
}
|
|
60169
61166
|
function createUseFormQueryFn(loader) {
|
|
60170
|
-
return
|
|
61167
|
+
return ({ signal }) => loader(signal);
|
|
60171
61168
|
}
|
|
60172
61169
|
|
|
60173
61170
|
// src/hooks/useForm.pagination.ts
|
|
60174
61171
|
var DEFAULT_PAGE_INDEX = 0;
|
|
60175
61172
|
var DEFAULT_PAGE_SIZE = 10;
|
|
60176
|
-
var DEFAULT_USE_REPORT_ROWS_PER_REQUEST = DEFAULT_PAGE_SIZE
|
|
61173
|
+
var DEFAULT_USE_REPORT_ROWS_PER_REQUEST = DEFAULT_PAGE_SIZE;
|
|
61174
|
+
var isBareIdentifier = (value) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(value);
|
|
61175
|
+
function getStablePaginationSort({
|
|
61176
|
+
columns,
|
|
61177
|
+
sort
|
|
61178
|
+
}) {
|
|
61179
|
+
const outputColumns = (columns ?? []).map((column) => {
|
|
61180
|
+
const field2 = String(column.field ?? "").trim();
|
|
61181
|
+
const alias = String(column.alias ?? "").trim();
|
|
61182
|
+
const outputField = isBareIdentifier(alias) ? alias : isBareIdentifier(field2) ? field2 : "";
|
|
61183
|
+
return { field: field2, alias, outputField };
|
|
61184
|
+
}).filter((column) => column.outputField);
|
|
61185
|
+
const requestedSort = sort?.[0];
|
|
61186
|
+
const requestedField = String(requestedSort?.field ?? "").trim();
|
|
61187
|
+
const matchedColumn = requestedField ? outputColumns.find(
|
|
61188
|
+
(column) => column.field === requestedField || column.alias === requestedField
|
|
61189
|
+
) : void 0;
|
|
61190
|
+
const field = matchedColumn?.outputField ?? outputColumns[0]?.outputField;
|
|
61191
|
+
if (!field) return void 0;
|
|
61192
|
+
return {
|
|
61193
|
+
field,
|
|
61194
|
+
direction: String(requestedSort?.direction ?? "ASC").toUpperCase() === "DESC" ? "DESC" : "ASC"
|
|
61195
|
+
};
|
|
61196
|
+
}
|
|
60177
61197
|
function getDefaultPaginationState() {
|
|
60178
61198
|
return { pageIndex: DEFAULT_PAGE_INDEX, pageSize: DEFAULT_PAGE_SIZE };
|
|
60179
61199
|
}
|
|
@@ -60323,11 +61343,11 @@ var isMultiValueOperator = (operator) => {
|
|
|
60323
61343
|
};
|
|
60324
61344
|
var collectSelectedStringMultiselectValuesByField = (group) => {
|
|
60325
61345
|
const out = /* @__PURE__ */ new Map();
|
|
60326
|
-
const visit = (
|
|
60327
|
-
if (!
|
|
61346
|
+
const visit = (entries2) => {
|
|
61347
|
+
if (!entries2) {
|
|
60328
61348
|
return;
|
|
60329
61349
|
}
|
|
60330
|
-
for (const entry of
|
|
61350
|
+
for (const entry of entries2) {
|
|
60331
61351
|
if (!entry || typeof entry === "string") {
|
|
60332
61352
|
continue;
|
|
60333
61353
|
}
|
|
@@ -60525,11 +61545,11 @@ var cloneQueryBuilderRuleGroup = (group) => JSON.parse(JSON.stringify(group));
|
|
|
60525
61545
|
var canonicalizeMultiselectStringRulesToOptionValues = (group, optionsByField, configByName) => {
|
|
60526
61546
|
const next = cloneQueryBuilderRuleGroup(group);
|
|
60527
61547
|
let changed = false;
|
|
60528
|
-
const visit = (
|
|
60529
|
-
if (!
|
|
61548
|
+
const visit = (entries2) => {
|
|
61549
|
+
if (!entries2) {
|
|
60530
61550
|
return;
|
|
60531
61551
|
}
|
|
60532
|
-
for (const entry of
|
|
61552
|
+
for (const entry of entries2) {
|
|
60533
61553
|
if (!entry || typeof entry === "string") {
|
|
60534
61554
|
continue;
|
|
60535
61555
|
}
|
|
@@ -62894,15 +63914,17 @@ async function loadViaInMemoryEngines({
|
|
|
62894
63914
|
pivot,
|
|
62895
63915
|
reportBuilderState,
|
|
62896
63916
|
allowReportTaskBootstrap = false,
|
|
62897
|
-
draftSessionId
|
|
63917
|
+
draftSessionId,
|
|
63918
|
+
shareInitialRequest = false,
|
|
63919
|
+
abortSignal
|
|
62898
63920
|
}) {
|
|
62899
63921
|
const requestedTask = allowReportTaskBootstrap ? "report" : "item";
|
|
62900
|
-
const additionalProcessing =
|
|
63922
|
+
const additionalProcessing = {
|
|
62901
63923
|
page: {
|
|
62902
63924
|
...DEFAULT_PAGINATION,
|
|
62903
63925
|
rowsPerRequest: DEFAULT_USE_REPORT_ROWS_PER_REQUEST
|
|
62904
63926
|
}
|
|
62905
|
-
}
|
|
63927
|
+
};
|
|
62906
63928
|
const { report, error } = await fetchReport({
|
|
62907
63929
|
reportId,
|
|
62908
63930
|
client,
|
|
@@ -62916,7 +63938,9 @@ async function loadViaInMemoryEngines({
|
|
|
62916
63938
|
usePivotTask: false,
|
|
62917
63939
|
pivot,
|
|
62918
63940
|
reportBuilderState,
|
|
62919
|
-
draftSessionId
|
|
63941
|
+
draftSessionId,
|
|
63942
|
+
shareRequest: shareInitialRequest,
|
|
63943
|
+
abortSignal
|
|
62920
63944
|
});
|
|
62921
63945
|
if (error || !report) {
|
|
62922
63946
|
return { report: null, error };
|
|
@@ -62982,7 +64006,9 @@ async function loadViaPivotTemplate({
|
|
|
62982
64006
|
reportBuilderState,
|
|
62983
64007
|
baseReport,
|
|
62984
64008
|
schema,
|
|
62985
|
-
draftSessionId
|
|
64009
|
+
draftSessionId,
|
|
64010
|
+
shareInitialRequest = false,
|
|
64011
|
+
abortSignal
|
|
62986
64012
|
}) {
|
|
62987
64013
|
const pivotForTemplate = enrichPivotRowFieldTypeForTemplate(
|
|
62988
64014
|
pivot,
|
|
@@ -63002,6 +64028,8 @@ async function loadViaPivotTemplate({
|
|
|
63002
64028
|
reportBuilderState,
|
|
63003
64029
|
baseReport,
|
|
63004
64030
|
draftSessionId,
|
|
64031
|
+
shareRequest: shareInitialRequest,
|
|
64032
|
+
abortSignal,
|
|
63005
64033
|
responseSelection: baseReport ? {
|
|
63006
64034
|
includeRows: false,
|
|
63007
64035
|
includeColumns: false,
|
|
@@ -63020,7 +64048,8 @@ async function fetchReportBuilderStateByReportId({
|
|
|
63020
64048
|
client,
|
|
63021
64049
|
getToken,
|
|
63022
64050
|
draftSessionId,
|
|
63023
|
-
tenants
|
|
64051
|
+
tenants,
|
|
64052
|
+
abortSignal
|
|
63024
64053
|
}) {
|
|
63025
64054
|
try {
|
|
63026
64055
|
const { data, error, status } = await quillFetch({
|
|
@@ -63031,7 +64060,8 @@ async function fetchReportBuilderStateByReportId({
|
|
|
63031
64060
|
tenants,
|
|
63032
64061
|
...draftSessionId ? { draftSessionId: String(draftSessionId).trim() } : {}
|
|
63033
64062
|
},
|
|
63034
|
-
getToken
|
|
64063
|
+
getToken,
|
|
64064
|
+
abortSignal
|
|
63035
64065
|
});
|
|
63036
64066
|
if (error || status === "error") {
|
|
63037
64067
|
return null;
|
|
@@ -63043,6 +64073,9 @@ async function fetchReportBuilderStateByReportId({
|
|
|
63043
64073
|
const parsedState = state;
|
|
63044
64074
|
return parsedState;
|
|
63045
64075
|
} catch (error) {
|
|
64076
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
64077
|
+
throw error;
|
|
64078
|
+
}
|
|
63046
64079
|
return null;
|
|
63047
64080
|
}
|
|
63048
64081
|
}
|
|
@@ -63104,7 +64137,8 @@ async function fetchUniqueValuesFromTables({
|
|
|
63104
64137
|
customFields,
|
|
63105
64138
|
tenants,
|
|
63106
64139
|
dashboardName,
|
|
63107
|
-
getToken
|
|
64140
|
+
getToken,
|
|
64141
|
+
abortSignal
|
|
63108
64142
|
}) {
|
|
63109
64143
|
const normalizedTables = Array.from(
|
|
63110
64144
|
new Set(
|
|
@@ -63121,6 +64155,9 @@ async function fetchUniqueValuesFromTables({
|
|
|
63121
64155
|
}
|
|
63122
64156
|
const fetchResults = await Promise.all(
|
|
63123
64157
|
normalizedTables.map(async (tableName) => {
|
|
64158
|
+
if (abortSignal?.aborted) {
|
|
64159
|
+
throw new DOMException("Aborted", "AbortError");
|
|
64160
|
+
}
|
|
63124
64161
|
const tableColumns = stringColumnsByTable.filter((column) => {
|
|
63125
64162
|
return String(column.table ?? "").trim() === tableName;
|
|
63126
64163
|
});
|
|
@@ -63153,7 +64190,8 @@ async function fetchUniqueValuesFromTables({
|
|
|
63153
64190
|
client,
|
|
63154
64191
|
task: "report-builder-unique-values",
|
|
63155
64192
|
metadata: requestMetadata,
|
|
63156
|
-
getToken
|
|
64193
|
+
getToken,
|
|
64194
|
+
abortSignal
|
|
63157
64195
|
});
|
|
63158
64196
|
const responseData = fetchResult?.data;
|
|
63159
64197
|
const responseRows = Array.isArray(responseData?.rows) && responseData.rows || Array.isArray(fetchResult?.queries?.queryResults?.[0]?.rows) && fetchResult.queries.queryResults[0].rows || [];
|
|
@@ -63216,7 +64254,9 @@ async function loadPivotTemplateInParallelWithReportTask({
|
|
|
63216
64254
|
customFields,
|
|
63217
64255
|
dashboardName,
|
|
63218
64256
|
pivotRefreshOnly = false,
|
|
63219
|
-
draftSessionId
|
|
64257
|
+
draftSessionId,
|
|
64258
|
+
shareInitialRequest = false,
|
|
64259
|
+
abortSignal
|
|
63220
64260
|
}) {
|
|
63221
64261
|
if (pivotRefreshOnly) {
|
|
63222
64262
|
const pivotOnlyResult = await loadViaPivotTemplate({
|
|
@@ -63230,7 +64270,9 @@ async function loadPivotTemplateInParallelWithReportTask({
|
|
|
63230
64270
|
reportBuilderState,
|
|
63231
64271
|
baseReport,
|
|
63232
64272
|
schema,
|
|
63233
|
-
draftSessionId
|
|
64273
|
+
draftSessionId,
|
|
64274
|
+
shareInitialRequest,
|
|
64275
|
+
abortSignal
|
|
63234
64276
|
});
|
|
63235
64277
|
return pivotOnlyResult;
|
|
63236
64278
|
}
|
|
@@ -63245,7 +64287,9 @@ async function loadPivotTemplateInParallelWithReportTask({
|
|
|
63245
64287
|
pivot,
|
|
63246
64288
|
reportBuilderState,
|
|
63247
64289
|
allowReportTaskBootstrap: true,
|
|
63248
|
-
draftSessionId
|
|
64290
|
+
draftSessionId,
|
|
64291
|
+
shareInitialRequest,
|
|
64292
|
+
abortSignal
|
|
63249
64293
|
}),
|
|
63250
64294
|
loadViaPivotTemplate({
|
|
63251
64295
|
reportId,
|
|
@@ -63258,14 +64302,17 @@ async function loadPivotTemplateInParallelWithReportTask({
|
|
|
63258
64302
|
reportBuilderState,
|
|
63259
64303
|
baseReport,
|
|
63260
64304
|
schema,
|
|
63261
|
-
draftSessionId
|
|
64305
|
+
draftSessionId,
|
|
64306
|
+
shareInitialRequest,
|
|
64307
|
+
abortSignal
|
|
63262
64308
|
}),
|
|
63263
64309
|
fetchReportBuilderStateByReportId({
|
|
63264
64310
|
reportId,
|
|
63265
64311
|
client,
|
|
63266
64312
|
getToken,
|
|
63267
64313
|
draftSessionId,
|
|
63268
|
-
tenants
|
|
64314
|
+
tenants,
|
|
64315
|
+
abortSignal
|
|
63269
64316
|
})
|
|
63270
64317
|
]);
|
|
63271
64318
|
const withFetchedReportBuilderState = (result) => applyFetchedReportBuilderState(result, fetchedReportBuilderState);
|
|
@@ -63300,7 +64347,8 @@ async function loadPivotTemplateInParallelWithReportTask({
|
|
|
63300
64347
|
customFields,
|
|
63301
64348
|
dashboardName: String(dashboardName ?? "").trim(),
|
|
63302
64349
|
report: baseReport,
|
|
63303
|
-
draftSessionId
|
|
64350
|
+
draftSessionId,
|
|
64351
|
+
abortSignal
|
|
63304
64352
|
});
|
|
63305
64353
|
if (reportBuilderStateFallbackResult.report && !reportBuilderStateFallbackResult.error) {
|
|
63306
64354
|
return withFetchedReportBuilderState(reportBuilderStateFallbackResult);
|
|
@@ -63330,7 +64378,8 @@ async function loadViaReportBuilderState({
|
|
|
63330
64378
|
pagination,
|
|
63331
64379
|
paginationSort,
|
|
63332
64380
|
rowsOnly,
|
|
63333
|
-
rowCountOnly
|
|
64381
|
+
rowCountOnly,
|
|
64382
|
+
abortSignal
|
|
63334
64383
|
}) {
|
|
63335
64384
|
const baseReport = {
|
|
63336
64385
|
...EMPTY_INTERNAL_REPORT,
|
|
@@ -63369,7 +64418,8 @@ async function loadViaReportBuilderState({
|
|
|
63369
64418
|
dashboardName,
|
|
63370
64419
|
getToken,
|
|
63371
64420
|
eventTracking: null,
|
|
63372
|
-
draftSessionId
|
|
64421
|
+
draftSessionId,
|
|
64422
|
+
abortSignal
|
|
63373
64423
|
});
|
|
63374
64424
|
if (!reportBuilderInfo) {
|
|
63375
64425
|
return {
|
|
@@ -63450,7 +64500,9 @@ async function loadReportForUseForm({
|
|
|
63450
64500
|
dashboardName,
|
|
63451
64501
|
useInMemoryEngines,
|
|
63452
64502
|
draftSessionId,
|
|
63453
|
-
|
|
64503
|
+
shareInitialRequest = false,
|
|
64504
|
+
rowsOnly = false,
|
|
64505
|
+
abortSignal
|
|
63454
64506
|
}) {
|
|
63455
64507
|
const effectivePivot = pivot ?? initialReportBuilderState?.pivot ?? void 0;
|
|
63456
64508
|
const hasPivot = Boolean(effectivePivot);
|
|
@@ -63473,7 +64525,9 @@ async function loadReportForUseForm({
|
|
|
63473
64525
|
customFields,
|
|
63474
64526
|
dashboardName,
|
|
63475
64527
|
pivotRefreshOnly: includeReportBuilderStateInPivotTask,
|
|
63476
|
-
draftSessionId
|
|
64528
|
+
draftSessionId,
|
|
64529
|
+
shareInitialRequest,
|
|
64530
|
+
abortSignal
|
|
63477
64531
|
});
|
|
63478
64532
|
const pivotRows = pivotResult.report?.pivotRows;
|
|
63479
64533
|
const rowField = pivotResult.report?.pivotResultRowField ?? effectivePivot?.rowField;
|
|
@@ -63496,7 +64550,8 @@ async function loadReportForUseForm({
|
|
|
63496
64550
|
customFields,
|
|
63497
64551
|
dashboardName,
|
|
63498
64552
|
report: baseReport ?? void 0,
|
|
63499
|
-
draftSessionId
|
|
64553
|
+
draftSessionId,
|
|
64554
|
+
abortSignal
|
|
63500
64555
|
});
|
|
63501
64556
|
const rbPivotRows = rbResult.report?.pivotRows;
|
|
63502
64557
|
const rbEmpty = !Array.isArray(rbPivotRows) || rbPivotRows.length === 0;
|
|
@@ -63521,7 +64576,9 @@ async function loadReportForUseForm({
|
|
|
63521
64576
|
schema,
|
|
63522
64577
|
customFields,
|
|
63523
64578
|
dashboardName,
|
|
63524
|
-
draftSessionId
|
|
64579
|
+
draftSessionId,
|
|
64580
|
+
shareInitialRequest,
|
|
64581
|
+
abortSignal
|
|
63525
64582
|
});
|
|
63526
64583
|
const normalizedBootstrapResult = bootstrapResult.report?.pivot == null ? stripPivotFromResult(bootstrapResult) : bootstrapResult;
|
|
63527
64584
|
return normalizedBootstrapResult;
|
|
@@ -63535,7 +64592,9 @@ async function loadReportForUseForm({
|
|
|
63535
64592
|
tenants,
|
|
63536
64593
|
flags,
|
|
63537
64594
|
allowReportTaskBootstrap: shouldUseReportTaskForReload,
|
|
63538
|
-
draftSessionId
|
|
64595
|
+
draftSessionId,
|
|
64596
|
+
shareInitialRequest,
|
|
64597
|
+
abortSignal
|
|
63539
64598
|
});
|
|
63540
64599
|
}
|
|
63541
64600
|
return loadViaReportBuilderState({
|
|
@@ -63549,7 +64608,8 @@ async function loadReportForUseForm({
|
|
|
63549
64608
|
dashboardName,
|
|
63550
64609
|
report: baseReport,
|
|
63551
64610
|
draftSessionId,
|
|
63552
|
-
rowsOnly
|
|
64611
|
+
rowsOnly,
|
|
64612
|
+
abortSignal
|
|
63553
64613
|
});
|
|
63554
64614
|
}
|
|
63555
64615
|
function generateDraftSessionId() {
|
|
@@ -63557,10 +64617,10 @@ function generateDraftSessionId() {
|
|
|
63557
64617
|
}
|
|
63558
64618
|
function useReport(reportIdArg, options = {}) {
|
|
63559
64619
|
const propReportId = String(reportIdArg ?? "").trim();
|
|
63560
|
-
const [createdReportBootstrap, setCreatedReportBootstrap] =
|
|
64620
|
+
const [createdReportBootstrap, setCreatedReportBootstrap] = useState42(null);
|
|
63561
64621
|
const effectiveReportId = propReportId || createdReportBootstrap?.reportId || "";
|
|
63562
64622
|
const { eventTracking } = useContext36(EventTrackingContext);
|
|
63563
|
-
const [draftSessionId, setDraftSessionId] =
|
|
64623
|
+
const [draftSessionId, setDraftSessionId] = useState42(generateDraftSessionId);
|
|
63564
64624
|
const useInMemoryEngines = options.useInMemoryEngines ?? false;
|
|
63565
64625
|
const dateBucketMode = options.dateBucketMode ?? "dynamic";
|
|
63566
64626
|
const restrictFieldOptionsToSelectedDatasources = options.restrictFieldOptionsToSelectedDatasources ?? true;
|
|
@@ -63574,16 +64634,10 @@ function useReport(reportIdArg, options = {}) {
|
|
|
63574
64634
|
...getDefaultPaginationState(),
|
|
63575
64635
|
...options.initialState?.pagination ?? {}
|
|
63576
64636
|
});
|
|
63577
|
-
const [internalPagination, setInternalPagination] =
|
|
64637
|
+
const [internalPagination, setInternalPagination] = useState42(
|
|
63578
64638
|
initialPaginationRef.current
|
|
63579
64639
|
);
|
|
63580
|
-
const [paginationInteracted, setPaginationInteracted] = useState41(
|
|
63581
|
-
() => Boolean(
|
|
63582
|
-
options.state?.pagination || options.initialState?.pagination || options.onPaginationChange
|
|
63583
|
-
)
|
|
63584
|
-
);
|
|
63585
64640
|
const pagination = controlledPagination ?? internalPagination;
|
|
63586
|
-
const paginationActive = paginationInteracted || Boolean(controlledPagination);
|
|
63587
64641
|
const paginationRef = useRef24(pagination);
|
|
63588
64642
|
paginationRef.current = pagination;
|
|
63589
64643
|
const onPaginationChangeRef = useRef24(options.onPaginationChange);
|
|
@@ -63594,10 +64648,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
63594
64648
|
autoResetPageIndexRef.current = options.autoResetPageIndex ?? true;
|
|
63595
64649
|
const paginationPageCountRef = useRef24(-1);
|
|
63596
64650
|
const applyPaginationUpdate = useCallback5(
|
|
63597
|
-
(updater
|
|
63598
|
-
if (activate) {
|
|
63599
|
-
setPaginationInteracted(true);
|
|
63600
|
-
}
|
|
64651
|
+
(updater) => {
|
|
63601
64652
|
onPaginationChangeRef.current?.(updater);
|
|
63602
64653
|
if (!controlledPaginationRef.current) {
|
|
63603
64654
|
setInternalPagination((old) => functionalUpdate(updater, old));
|
|
@@ -63676,13 +64727,13 @@ function useReport(reportIdArg, options = {}) {
|
|
|
63676
64727
|
dateBucketSetViaSetReportRef.current = false;
|
|
63677
64728
|
aggregationStateSetViaSetReportRef.current = false;
|
|
63678
64729
|
}
|
|
63679
|
-
const [chartPivotHydrationEpoch, setChartPivotHydrationEpoch] =
|
|
64730
|
+
const [chartPivotHydrationEpoch, setChartPivotHydrationEpoch] = useState42(0);
|
|
63680
64731
|
const [
|
|
63681
64732
|
expandReportBuilderColumnsForFlatTable,
|
|
63682
64733
|
setExpandReportBuilderColumnsForFlatTable
|
|
63683
|
-
] =
|
|
64734
|
+
] = useState42(false);
|
|
63684
64735
|
const prevPivotStateForColumnExpansionRef = useRef24(null);
|
|
63685
|
-
const [sourceReport, setSourceReport] =
|
|
64736
|
+
const [sourceReport, setSourceReport] = useState42(
|
|
63686
64737
|
null
|
|
63687
64738
|
);
|
|
63688
64739
|
const prevSourceReportIdForPivotHydrationRef = useRef24(null);
|
|
@@ -63697,18 +64748,21 @@ function useReport(reportIdArg, options = {}) {
|
|
|
63697
64748
|
lastPivotHydrateCompletedSourceIdRef.current = null;
|
|
63698
64749
|
}
|
|
63699
64750
|
}
|
|
63700
|
-
const [preserveSchemaWideOptions, setPreserveSchemaWideOptions] =
|
|
63701
|
-
const [initialSchemaScopedTableNames, setInitialSchemaScopedTableNames] =
|
|
63702
|
-
const [tableColumnsEditedSignature, setTableColumnsEditedSignature] =
|
|
63703
|
-
|
|
64751
|
+
const [preserveSchemaWideOptions, setPreserveSchemaWideOptions] = useState42(false);
|
|
64752
|
+
const [initialSchemaScopedTableNames, setInitialSchemaScopedTableNames] = useState42(null);
|
|
64753
|
+
const [tableColumnsEditedSignature, setTableColumnsEditedSignature] = useState42(null);
|
|
64754
|
+
useEffect32(() => {
|
|
63704
64755
|
setTableColumnsEditedSignature(null);
|
|
63705
64756
|
}, [effectiveReportId]);
|
|
63706
|
-
const [chartAxisEdits, setChartAxisEdits] =
|
|
63707
|
-
const [chartVisibilityOverrides, setChartVisibilityOverrides] =
|
|
64757
|
+
const [chartAxisEdits, setChartAxisEdits] = useState42({});
|
|
64758
|
+
const [chartVisibilityOverrides, setChartVisibilityOverrides] = useState42({});
|
|
63708
64759
|
const [client] = useContext36(ClientContext);
|
|
64760
|
+
const queryClient = useQueryClient2();
|
|
63709
64761
|
const [schemaData] = useContext36(SchemaDataContext);
|
|
63710
64762
|
const { tenants, flags } = useContext36(TenantContext);
|
|
63711
64763
|
const { getToken } = useContext36(FetchContext);
|
|
64764
|
+
const { getCacheCab } = useContext36(CacheCabContext);
|
|
64765
|
+
const cacheCab = useMemo33(() => getCacheCab(), [getCacheCab]);
|
|
63712
64766
|
const clientDefaultDashboardName = String(
|
|
63713
64767
|
client?.defaultDashboard?.name ?? ""
|
|
63714
64768
|
).trim();
|
|
@@ -63824,16 +64878,17 @@ function useReport(reportIdArg, options = {}) {
|
|
|
63824
64878
|
filterStackRef.current = filterStack;
|
|
63825
64879
|
const resolvedGroupRowsBy = decodePivotGroupOptionValue(groupRowsBy);
|
|
63826
64880
|
const resolvedGroupColumnsBy = decodePivotGroupOptionValue(groupColumnsBy);
|
|
63827
|
-
|
|
64881
|
+
useEffect32(() => {
|
|
63828
64882
|
if (propReportId) {
|
|
63829
64883
|
setCreatedReportBootstrap(null);
|
|
63830
64884
|
}
|
|
63831
64885
|
}, [propReportId]);
|
|
63832
|
-
|
|
64886
|
+
useEffect32(() => {
|
|
63833
64887
|
setChartAxisEdits({});
|
|
63834
64888
|
setChartVisibilityOverrides({});
|
|
63835
64889
|
}, [effectiveReportId]);
|
|
63836
64890
|
const bootstrapReportTaskUsedForReportIdRef = useRef24(null);
|
|
64891
|
+
const sharedInitialRequestUsedForReportIdRef = useRef24(null);
|
|
63837
64892
|
const schemaScopeInitializedForReportIdRef = useRef24(null);
|
|
63838
64893
|
const initializeSchemaScopeForReport = (report) => {
|
|
63839
64894
|
if (!report) return;
|
|
@@ -63855,6 +64910,55 @@ function useReport(reportIdArg, options = {}) {
|
|
|
63855
64910
|
() => customFiltersFromFilterStack(filterStack),
|
|
63856
64911
|
[filterStack]
|
|
63857
64912
|
);
|
|
64913
|
+
const forceIncompleteCacheCabForParity = process.env.NODE_ENV === "test" && process.env.QUILL_FORCE_INCOMPLETE_CACHECAB_FOR_PARITY === "true";
|
|
64914
|
+
const resolveCachedReport = useCallback5(
|
|
64915
|
+
async ({
|
|
64916
|
+
reportBuilderState,
|
|
64917
|
+
filters,
|
|
64918
|
+
pivot,
|
|
64919
|
+
operation
|
|
64920
|
+
}) => {
|
|
64921
|
+
const startedAt = performance.now();
|
|
64922
|
+
const snapshot = await cacheCab.getReportSnapshot(
|
|
64923
|
+
effectiveReportId,
|
|
64924
|
+
tenants
|
|
64925
|
+
);
|
|
64926
|
+
const state = reportBuilderState ?? snapshot?.report.reportBuilderState;
|
|
64927
|
+
const resolution = resolveReportFromCacheCab({
|
|
64928
|
+
snapshot: snapshot && forceIncompleteCacheCabForParity ? { ...snapshot, complete: true, reason: "complete" } : snapshot,
|
|
64929
|
+
reportBuilderState: state,
|
|
64930
|
+
filters: filters ?? customFiltersFromFilterStack(state?.filterStack ?? []),
|
|
64931
|
+
pivot,
|
|
64932
|
+
operation,
|
|
64933
|
+
rowLimit: operation === "unique-values" ? void 0 : Math.max(
|
|
64934
|
+
DEFAULT_USE_REPORT_ROWS_PER_REQUEST,
|
|
64935
|
+
pagination.pageSize
|
|
64936
|
+
)
|
|
64937
|
+
});
|
|
64938
|
+
const diagnostics = globalThis.__QUILL_CACHECAB_DIAGNOSTICS__;
|
|
64939
|
+
if (Array.isArray(diagnostics)) {
|
|
64940
|
+
diagnostics.push({
|
|
64941
|
+
reportId: effectiveReportId,
|
|
64942
|
+
operation,
|
|
64943
|
+
outcome: resolution.resolved ? "hit" : "fallback",
|
|
64944
|
+
reason: resolution.resolved ? "complete" : resolution.reason,
|
|
64945
|
+
details: resolution.resolved ? void 0 : resolution.details,
|
|
64946
|
+
snapshotReason: snapshot?.reason ?? "cache_miss",
|
|
64947
|
+
forcedIncompleteSnapshot: Boolean(snapshot) && !snapshot?.complete && forceIncompleteCacheCabForParity,
|
|
64948
|
+
rowCount: snapshot?.rowCount ?? 0,
|
|
64949
|
+
durationMs: performance.now() - startedAt
|
|
64950
|
+
});
|
|
64951
|
+
}
|
|
64952
|
+
return resolution.resolved ? resolution.report : null;
|
|
64953
|
+
},
|
|
64954
|
+
[
|
|
64955
|
+
cacheCab,
|
|
64956
|
+
effectiveReportId,
|
|
64957
|
+
forceIncompleteCacheCabForParity,
|
|
64958
|
+
pagination.pageSize,
|
|
64959
|
+
tenants
|
|
64960
|
+
]
|
|
64961
|
+
);
|
|
63858
64962
|
const reloadKey = useMemo33(() => 0, []);
|
|
63859
64963
|
const schemaForReportBuilderState = useMemo33(() => {
|
|
63860
64964
|
if (schemaData.schemaWithCustomFields?.length) {
|
|
@@ -63928,7 +65032,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
63928
65032
|
restrictFieldOptionsToSelectedDatasources,
|
|
63929
65033
|
selectedBaseTableNamesForFieldOptions
|
|
63930
65034
|
]);
|
|
63931
|
-
|
|
65035
|
+
useEffect32(() => {
|
|
63932
65036
|
if (reportOverride) return;
|
|
63933
65037
|
if (propReportId) return;
|
|
63934
65038
|
if (createdReportBootstrap) return;
|
|
@@ -64278,15 +65382,11 @@ function useReport(reportIdArg, options = {}) {
|
|
|
64278
65382
|
return null;
|
|
64279
65383
|
}
|
|
64280
65384
|
return {
|
|
64281
|
-
|
|
64282
|
-
|
|
64283
|
-
|
|
64284
|
-
|
|
64285
|
-
|
|
64286
|
-
// change, in-progress rules refetch unique values and the engine often
|
|
64287
|
-
// returns empty columns (no rows / invalid stack), clearing all multiselects.
|
|
64288
|
-
filterStack: []
|
|
64289
|
-
},
|
|
65385
|
+
// Distinct string options must not depend on presentation or live filters.
|
|
65386
|
+
reportBuilderState: createFilterUniqueValuesReportBuilderState(
|
|
65387
|
+
sourceReportBuilderState,
|
|
65388
|
+
columnsForUniqueValues
|
|
65389
|
+
),
|
|
64290
65390
|
stringColumns: stringColumns2,
|
|
64291
65391
|
stringColumnsByTable: columnsForUniqueValues,
|
|
64292
65392
|
dashboardName
|
|
@@ -64390,11 +65490,36 @@ function useReport(reportIdArg, options = {}) {
|
|
|
64390
65490
|
databaseType: client?.databaseType
|
|
64391
65491
|
})
|
|
64392
65492
|
],
|
|
64393
|
-
queryFn: createUseFormQueryFn(async () => {
|
|
65493
|
+
queryFn: createUseFormQueryFn(async (signal) => {
|
|
64394
65494
|
try {
|
|
64395
65495
|
if (!client || !filterUniqueValuesRequest) {
|
|
64396
65496
|
return { uniqueValuesByColumn: {} };
|
|
64397
65497
|
}
|
|
65498
|
+
const cachedReport = await resolveCachedReport({
|
|
65499
|
+
reportBuilderState: filterUniqueValuesRequest.reportBuilderState,
|
|
65500
|
+
filters: [],
|
|
65501
|
+
pivot: null,
|
|
65502
|
+
operation: "unique-values"
|
|
65503
|
+
});
|
|
65504
|
+
if (cachedReport?.uniqueStringsByTable) {
|
|
65505
|
+
const localValues = {};
|
|
65506
|
+
let hasEveryColumn = true;
|
|
65507
|
+
for (const column of filterUniqueValuesRequest.stringColumnsByTable) {
|
|
65508
|
+
const table2 = String(column.table ?? "").trim();
|
|
65509
|
+
const field = String(column.field ?? "").trim();
|
|
65510
|
+
const values = cachedReport.uniqueStringsByTable[table2]?.[field] ?? cachedReport.uniqueStringsByTable[""]?.[field];
|
|
65511
|
+
if (!values) {
|
|
65512
|
+
hasEveryColumn = false;
|
|
65513
|
+
break;
|
|
65514
|
+
}
|
|
65515
|
+
localValues[field] = values;
|
|
65516
|
+
const alias = String(column.alias ?? "").trim();
|
|
65517
|
+
if (alias) localValues[alias] = values;
|
|
65518
|
+
}
|
|
65519
|
+
if (hasEveryColumn) {
|
|
65520
|
+
return { uniqueValuesByColumn: localValues };
|
|
65521
|
+
}
|
|
65522
|
+
}
|
|
64398
65523
|
const tablesForUniqueValues = filterUniqueValuesRequest.reportBuilderState?.tables?.map(
|
|
64399
65524
|
(table2) => String(table2?.name ?? "").trim()
|
|
64400
65525
|
) ?? filterUniqueValuesRequest.stringColumnsByTable.map((column) => String(column.table ?? "").trim()).filter(Boolean);
|
|
@@ -64407,7 +65532,8 @@ function useReport(reportIdArg, options = {}) {
|
|
|
64407
65532
|
customFields: schemaData.customFields ?? void 0,
|
|
64408
65533
|
tenants,
|
|
64409
65534
|
dashboardName: filterUniqueValuesRequest.dashboardName,
|
|
64410
|
-
getToken
|
|
65535
|
+
getToken,
|
|
65536
|
+
abortSignal: signal
|
|
64411
65537
|
});
|
|
64412
65538
|
const aliasToField = {};
|
|
64413
65539
|
for (const column of filterUniqueValuesRequest.stringColumnsByTable) {
|
|
@@ -64439,12 +65565,18 @@ function useReport(reportIdArg, options = {}) {
|
|
|
64439
65565
|
}
|
|
64440
65566
|
});
|
|
64441
65567
|
return { uniqueValuesByColumn: normalizedUniqueValuesByColumn };
|
|
64442
|
-
} catch {
|
|
65568
|
+
} catch (error) {
|
|
65569
|
+
if (signal.aborted || error instanceof Error && error.name === "AbortError") {
|
|
65570
|
+
throw error;
|
|
65571
|
+
}
|
|
64443
65572
|
return { uniqueValuesByColumn: {} };
|
|
64444
65573
|
}
|
|
64445
65574
|
}),
|
|
64446
65575
|
enabled: filterUniqueValuesEnabled,
|
|
64447
|
-
retry: false
|
|
65576
|
+
retry: false,
|
|
65577
|
+
staleTime: 5 * 6e4,
|
|
65578
|
+
gcTime: 15 * 6e4,
|
|
65579
|
+
placeholderData: keepPreviousData
|
|
64448
65580
|
});
|
|
64449
65581
|
const backendUniqueValuesByFieldName = useMemo33(() => {
|
|
64450
65582
|
const valuesByField = /* @__PURE__ */ new Map();
|
|
@@ -64824,14 +65956,15 @@ function useReport(reportIdArg, options = {}) {
|
|
|
64824
65956
|
() => stableSerializeForQueryKey(reloadKey),
|
|
64825
65957
|
[reloadKey]
|
|
64826
65958
|
);
|
|
64827
|
-
|
|
65959
|
+
useEffect32(() => {
|
|
64828
65960
|
if (!reportOverride) return;
|
|
64829
65961
|
initializeSchemaScopeForReport(reportOverride);
|
|
64830
65962
|
setSourceReport(reportOverride);
|
|
64831
65963
|
}, [reportOverride, propReportId]);
|
|
64832
|
-
|
|
65964
|
+
useEffect32(() => {
|
|
64833
65965
|
schemaScopeInitializedForReportIdRef.current = null;
|
|
64834
65966
|
bootstrapReportTaskUsedForReportIdRef.current = null;
|
|
65967
|
+
sharedInitialRequestUsedForReportIdRef.current = null;
|
|
64835
65968
|
setPreserveSchemaWideOptions(false);
|
|
64836
65969
|
setInitialSchemaScopedTableNames(null);
|
|
64837
65970
|
if (!reportOverride) {
|
|
@@ -64885,7 +66018,33 @@ function useReport(reportIdArg, options = {}) {
|
|
|
64885
66018
|
flagHash,
|
|
64886
66019
|
clientHash
|
|
64887
66020
|
}),
|
|
64888
|
-
queryFn: createUseFormQueryFn(async () => {
|
|
66021
|
+
queryFn: createUseFormQueryFn(async (signal) => {
|
|
66022
|
+
let cachedReportBuilderState = initialReportBuilderStateForLoad ?? void 0;
|
|
66023
|
+
if (!cachedReportBuilderState) {
|
|
66024
|
+
const snapshot = await cacheCab.getReportSnapshot(
|
|
66025
|
+
effectiveReportId,
|
|
66026
|
+
tenants
|
|
66027
|
+
);
|
|
66028
|
+
if (snapshot?.complete || snapshot && forceIncompleteCacheCabForParity) {
|
|
66029
|
+
cachedReportBuilderState = await fetchReportBuilderStateByReportId({
|
|
66030
|
+
reportId: effectiveReportId,
|
|
66031
|
+
client,
|
|
66032
|
+
getToken,
|
|
66033
|
+
draftSessionId: draftSessionId || void 0,
|
|
66034
|
+
tenants,
|
|
66035
|
+
abortSignal: signal
|
|
66036
|
+
}) ?? void 0;
|
|
66037
|
+
}
|
|
66038
|
+
}
|
|
66039
|
+
const cachedReport = await resolveCachedReport({
|
|
66040
|
+
reportBuilderState: cachedReportBuilderState,
|
|
66041
|
+
filters: cachedReportBuilderState ? customFiltersFromFilterStack(cachedReportBuilderState.filterStack) : void 0,
|
|
66042
|
+
pivot: cachedReportBuilderState?.pivot,
|
|
66043
|
+
operation: "initial"
|
|
66044
|
+
});
|
|
66045
|
+
if (cachedReport) {
|
|
66046
|
+
return { report: cachedReport };
|
|
66047
|
+
}
|
|
64889
66048
|
const allowReportTaskBootstrap = !initialReportBuilderStateForLoad && bootstrapReportTaskUsedForReportIdRef.current !== effectiveReportId;
|
|
64890
66049
|
const loadTargetId = String(effectiveReportId ?? "").trim();
|
|
64891
66050
|
const sourceReportIdentity = String(
|
|
@@ -64893,9 +66052,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
64893
66052
|
).trim();
|
|
64894
66053
|
const formFiltersBelongToLoadTarget = Boolean(loadTargetId) && sourceReportIdentity === loadTargetId;
|
|
64895
66054
|
const internalFiltersForLoad = useInMemoryEngines || !formFiltersBelongToLoadTarget ? [] : internalFilters;
|
|
64896
|
-
|
|
64897
|
-
bootstrapReportTaskUsedForReportIdRef.current = effectiveReportId;
|
|
64898
|
-
}
|
|
66055
|
+
const shareInitialRequest = sharedInitialRequestUsedForReportIdRef.current !== effectiveReportId;
|
|
64899
66056
|
const loadResult = await loadReportForUseForm({
|
|
64900
66057
|
reportId: effectiveReportId,
|
|
64901
66058
|
initialReportBuilderState: initialReportBuilderStateForLoad,
|
|
@@ -64911,8 +66068,18 @@ function useReport(reportIdArg, options = {}) {
|
|
|
64911
66068
|
dashboardName: resolvedSourceDashboardName,
|
|
64912
66069
|
useInMemoryEngines,
|
|
64913
66070
|
draftSessionId: draftSessionId || void 0,
|
|
64914
|
-
|
|
66071
|
+
shareInitialRequest,
|
|
66072
|
+
rowsOnly: isCreatedReportBootstrapLoad,
|
|
66073
|
+
abortSignal: signal
|
|
64915
66074
|
});
|
|
66075
|
+
if (loadResult.report && !loadResult.error) {
|
|
66076
|
+
if (allowReportTaskBootstrap) {
|
|
66077
|
+
bootstrapReportTaskUsedForReportIdRef.current = effectiveReportId;
|
|
66078
|
+
}
|
|
66079
|
+
if (shareInitialRequest) {
|
|
66080
|
+
sharedInitialRequestUsedForReportIdRef.current = effectiveReportId;
|
|
66081
|
+
}
|
|
66082
|
+
}
|
|
64916
66083
|
return loadResult;
|
|
64917
66084
|
}),
|
|
64918
66085
|
enabled: Boolean(effectiveReportId) && Boolean(client) && !reportOverride,
|
|
@@ -64924,7 +66091,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
64924
66091
|
reportId: reportNameQueryReportId,
|
|
64925
66092
|
clientHash
|
|
64926
66093
|
}),
|
|
64927
|
-
queryFn: createUseFormQueryFn(async () => {
|
|
66094
|
+
queryFn: createUseFormQueryFn(async (signal) => {
|
|
64928
66095
|
if (!client) {
|
|
64929
66096
|
return { name: null };
|
|
64930
66097
|
}
|
|
@@ -64932,7 +66099,8 @@ function useReport(reportIdArg, options = {}) {
|
|
|
64932
66099
|
reportId: reportNameQueryReportId,
|
|
64933
66100
|
client,
|
|
64934
66101
|
getToken,
|
|
64935
|
-
tenants
|
|
66102
|
+
tenants,
|
|
66103
|
+
abortSignal: signal
|
|
64936
66104
|
});
|
|
64937
66105
|
}),
|
|
64938
66106
|
enabled: Boolean(reportNameQueryReportId) && Boolean(client),
|
|
@@ -64945,13 +66113,13 @@ function useReport(reportIdArg, options = {}) {
|
|
|
64945
66113
|
const reportTitleFromTask = String(reportNameQuery.data?.name ?? "").trim();
|
|
64946
66114
|
const resolvedReportName = reportNameQueryReportId && sourceReportIdForTitle === reportNameQueryReportId && sourceReportNameForTitle ? sourceReportNameForTitle : reportTitleFromTask || sourceReportNameForTitle || "";
|
|
64947
66115
|
const displayReportName = formReportName !== void 0 ? formReportName : resolvedReportName;
|
|
64948
|
-
|
|
66116
|
+
useEffect32(() => {
|
|
64949
66117
|
if (reportOverride) return;
|
|
64950
66118
|
const report = initialLoadQuery.data?.report ?? null;
|
|
64951
66119
|
initializeSchemaScopeForReport(report);
|
|
64952
66120
|
setSourceReport(report);
|
|
64953
66121
|
}, [initialLoadQuery.data, reportOverride, effectiveReportId]);
|
|
64954
|
-
|
|
66122
|
+
useEffect32(() => {
|
|
64955
66123
|
if (!sourceReport) {
|
|
64956
66124
|
return;
|
|
64957
66125
|
}
|
|
@@ -65019,14 +66187,14 @@ function useReport(reportIdArg, options = {}) {
|
|
|
65019
66187
|
}) || void 0
|
|
65020
66188
|
) : shouldApplyPivotAggregationsFromSource ? [] : prev.aggregationTablesByIndex;
|
|
65021
66189
|
const sourceRowGroupOption = encodePivotGroupOptionValue(
|
|
65022
|
-
resolveColumnTableFromReportMetadata(
|
|
66190
|
+
String(sourceReport.pivot?.rowFieldTable ?? "").trim() || resolveColumnTableFromReportMetadata(
|
|
65023
66191
|
sourceReport,
|
|
65024
66192
|
sourceReport.pivot?.rowField ?? ""
|
|
65025
66193
|
),
|
|
65026
66194
|
sourceReport.pivot?.rowField ?? ""
|
|
65027
66195
|
) || sourceReport.pivot?.rowField;
|
|
65028
66196
|
const sourceColumnGroupOption = encodePivotGroupOptionValue(
|
|
65029
|
-
resolveColumnTableFromReportMetadata(
|
|
66197
|
+
String(sourceReport.pivot?.columnFieldTable ?? "").trim() || resolveColumnTableFromReportMetadata(
|
|
65030
66198
|
sourceReport,
|
|
65031
66199
|
sourceReport.pivot?.columnField ?? ""
|
|
65032
66200
|
),
|
|
@@ -65177,7 +66345,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
65177
66345
|
chartPivotHydrationEpoch
|
|
65178
66346
|
]);
|
|
65179
66347
|
const hasDatePivotRow = Boolean(String(pivotState?.rowField ?? "").trim()) && isDateType(String(pivotState?.rowFieldType ?? ""));
|
|
65180
|
-
|
|
66348
|
+
useEffect32(() => {
|
|
65181
66349
|
const previous = prevPivotStateForColumnExpansionRef.current;
|
|
65182
66350
|
if (previous && !pivotState) {
|
|
65183
66351
|
setExpandReportBuilderColumnsForFlatTable(true);
|
|
@@ -65442,7 +66610,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
65442
66610
|
queryColumns,
|
|
65443
66611
|
sourceReport
|
|
65444
66612
|
]);
|
|
65445
|
-
|
|
66613
|
+
useEffect32(() => {
|
|
65446
66614
|
if (!Array.isArray(filterStack) || filterStack.length === 0) {
|
|
65447
66615
|
return;
|
|
65448
66616
|
}
|
|
@@ -65546,7 +66714,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
65546
66714
|
[effectiveReportBuilderState]
|
|
65547
66715
|
);
|
|
65548
66716
|
const prevPaginationResetStateHashRef = useRef24(null);
|
|
65549
|
-
|
|
66717
|
+
useEffect32(() => {
|
|
65550
66718
|
const prevHash = prevPaginationResetStateHashRef.current;
|
|
65551
66719
|
prevPaginationResetStateHashRef.current = effectiveReportBuilderStateHash;
|
|
65552
66720
|
if (prevHash === null || prevHash === effectiveReportBuilderStateHash) {
|
|
@@ -65558,9 +66726,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
65558
66726
|
if (paginationRef.current.pageIndex === 0) {
|
|
65559
66727
|
return;
|
|
65560
66728
|
}
|
|
65561
|
-
applyPaginationUpdate((old) => ({ ...old, pageIndex: 0 })
|
|
65562
|
-
activate: false
|
|
65563
|
-
});
|
|
66729
|
+
applyPaginationUpdate((old) => ({ ...old, pageIndex: 0 }));
|
|
65564
66730
|
}, [applyPaginationUpdate, effectiveReportBuilderStateHash]);
|
|
65565
66731
|
const pivotTableDataReportBuilderState = useMemo33(() => {
|
|
65566
66732
|
if (!effectiveReportBuilderState?.pivot) {
|
|
@@ -65622,22 +66788,60 @@ function useReport(reportIdArg, options = {}) {
|
|
|
65622
66788
|
filterStack
|
|
65623
66789
|
]);
|
|
65624
66790
|
const shouldForceTableRefreshFromFilters = !useInMemoryEngines && !pivotState;
|
|
65625
|
-
const
|
|
66791
|
+
const immediateTableRefreshInput = useMemo33(
|
|
66792
|
+
() => ({
|
|
66793
|
+
version: tableRefreshVersion,
|
|
66794
|
+
reportBuilderStateHash: effectiveReportBuilderStateHash,
|
|
66795
|
+
reportBuilderState: effectiveReportBuilderState,
|
|
66796
|
+
shouldRefresh: refreshDecision.shouldRefresh || shouldForceTableRefreshFromFilters && !shouldSkipRedundantFlatTableReportBuilderQuery
|
|
66797
|
+
}),
|
|
66798
|
+
[
|
|
66799
|
+
effectiveReportBuilderState,
|
|
66800
|
+
effectiveReportBuilderStateHash,
|
|
66801
|
+
refreshDecision.shouldRefresh,
|
|
66802
|
+
shouldForceTableRefreshFromFilters,
|
|
66803
|
+
shouldSkipRedundantFlatTableReportBuilderQuery,
|
|
66804
|
+
tableRefreshVersion
|
|
66805
|
+
]
|
|
66806
|
+
);
|
|
66807
|
+
const debouncedTableRefreshInput = useDebouncedRefreshInput(
|
|
66808
|
+
immediateTableRefreshInput
|
|
66809
|
+
);
|
|
66810
|
+
const disableTableRefreshDebounceForDiagnostics = process.env.NODE_ENV === "test" && process.env.QUILL_DISABLE_REPORT_REFRESH_DEBOUNCE === "true";
|
|
66811
|
+
const tableRefreshInput = disableTableRefreshDebounceForDiagnostics ? immediateTableRefreshInput : debouncedTableRefreshInput;
|
|
66812
|
+
const tableRefreshInputIsCurrent = tableRefreshInput.version === tableRefreshVersion && tableRefreshInput.reportBuilderStateHash === effectiveReportBuilderStateHash;
|
|
66813
|
+
const completedTableRefreshRef = useRef24(null);
|
|
66814
|
+
if (completedTableRefreshRef.current?.reportId !== effectiveReportId) {
|
|
66815
|
+
completedTableRefreshRef.current = null;
|
|
66816
|
+
}
|
|
66817
|
+
const tableRefreshInputAlreadyCompleted = !disableTableRefreshDebounceForDiagnostics && completedTableRefreshRef.current?.reportId === effectiveReportId && completedTableRefreshRef.current.version >= tableRefreshInput.version;
|
|
66818
|
+
const tableRefreshQueryEnabled = !reportOverride && tableRefreshInputIsCurrent && !tableRefreshInputAlreadyCompleted && tableRefreshInput.version > 0 && Boolean(sourceReport) && Boolean(client) && Boolean(tableRefreshInput.reportBuilderState) && !pendingPivotRefresh && sourceReportMatchesEffectiveReportId && tableRefreshInput.shouldRefresh;
|
|
65626
66819
|
const tableRefreshQuery = useQuery({
|
|
65627
66820
|
queryKey: createUseFormTableRefreshQueryKey({
|
|
65628
66821
|
reportId: effectiveReportId,
|
|
65629
|
-
tableRefreshVersion,
|
|
65630
|
-
reportBuilderStateHash:
|
|
66822
|
+
tableRefreshVersion: tableRefreshInput.version,
|
|
66823
|
+
reportBuilderStateHash: tableRefreshInput.reportBuilderStateHash,
|
|
65631
66824
|
tenantHash,
|
|
65632
66825
|
clientHash
|
|
65633
66826
|
}),
|
|
65634
|
-
queryFn: createUseFormQueryFn(async () => {
|
|
65635
|
-
if (!
|
|
66827
|
+
queryFn: createUseFormQueryFn(async (signal) => {
|
|
66828
|
+
if (!tableRefreshInput.reportBuilderState || !sourceReport || !client) {
|
|
65636
66829
|
return { report: null, error: "Missing table refresh prerequisites" };
|
|
65637
66830
|
}
|
|
66831
|
+
const cachedReport = await resolveCachedReport({
|
|
66832
|
+
reportBuilderState: tableRefreshInput.reportBuilderState,
|
|
66833
|
+
filters: customFiltersFromFilterStack(
|
|
66834
|
+
tableRefreshInput.reportBuilderState.filterStack
|
|
66835
|
+
),
|
|
66836
|
+
pivot: null,
|
|
66837
|
+
operation: "table"
|
|
66838
|
+
});
|
|
66839
|
+
if (cachedReport) {
|
|
66840
|
+
return { report: cachedReport };
|
|
66841
|
+
}
|
|
65638
66842
|
return loadViaReportBuilderState({
|
|
65639
66843
|
reportId: effectiveReportId,
|
|
65640
|
-
reportBuilderState:
|
|
66844
|
+
reportBuilderState: tableRefreshInput.reportBuilderState,
|
|
65641
66845
|
client,
|
|
65642
66846
|
getToken,
|
|
65643
66847
|
tenants,
|
|
@@ -65645,7 +66849,8 @@ function useReport(reportIdArg, options = {}) {
|
|
|
65645
66849
|
customFields: schemaData.customFields,
|
|
65646
66850
|
dashboardName: resolvedSourceDashboardName,
|
|
65647
66851
|
report: sourceReport,
|
|
65648
|
-
draftSessionId: draftSessionId || void 0
|
|
66852
|
+
draftSessionId: draftSessionId || void 0,
|
|
66853
|
+
abortSignal: signal
|
|
65649
66854
|
});
|
|
65650
66855
|
}),
|
|
65651
66856
|
enabled: tableRefreshQueryEnabled,
|
|
@@ -65660,7 +66865,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
65660
66865
|
tenantHash,
|
|
65661
66866
|
clientHash
|
|
65662
66867
|
],
|
|
65663
|
-
queryFn: createUseFormQueryFn(async () => {
|
|
66868
|
+
queryFn: createUseFormQueryFn(async (signal) => {
|
|
65664
66869
|
if (!createdBootstrapForInitialLoad || !initialReportBuilderStateForLoad || !client) {
|
|
65665
66870
|
return { report: null, error: "Missing bootstrap count prerequisites" };
|
|
65666
66871
|
}
|
|
@@ -65675,19 +66880,29 @@ function useReport(reportIdArg, options = {}) {
|
|
|
65675
66880
|
dashboardName: resolvedSourceDashboardName,
|
|
65676
66881
|
report: createdBootstrapForInitialLoad.report,
|
|
65677
66882
|
draftSessionId: draftSessionId || void 0,
|
|
65678
|
-
rowCountOnly: true
|
|
66883
|
+
rowCountOnly: true,
|
|
66884
|
+
abortSignal: signal
|
|
65679
66885
|
});
|
|
65680
66886
|
}),
|
|
65681
66887
|
enabled: isCreatedReportBootstrapLoad && Boolean(client) && !reportOverride,
|
|
65682
66888
|
retry: false
|
|
65683
66889
|
});
|
|
65684
|
-
|
|
66890
|
+
useEffect32(() => {
|
|
65685
66891
|
if (!tableRefreshQueryEnabled) return;
|
|
65686
66892
|
const report = tableRefreshQuery.data?.report;
|
|
65687
66893
|
if (tableRefreshQuery.data?.error || !report) return;
|
|
66894
|
+
completedTableRefreshRef.current = {
|
|
66895
|
+
reportId: effectiveReportId,
|
|
66896
|
+
version: tableRefreshInput.version
|
|
66897
|
+
};
|
|
65688
66898
|
setSourceReport(report);
|
|
65689
|
-
}, [
|
|
65690
|
-
|
|
66899
|
+
}, [
|
|
66900
|
+
effectiveReportId,
|
|
66901
|
+
tableRefreshInput.version,
|
|
66902
|
+
tableRefreshQuery.data,
|
|
66903
|
+
tableRefreshQueryEnabled
|
|
66904
|
+
]);
|
|
66905
|
+
useEffect32(() => {
|
|
65691
66906
|
const countReport = createdBootstrapRowCountQuery.data?.report;
|
|
65692
66907
|
if (createdBootstrapRowCountQuery.data?.error || !countReport) return;
|
|
65693
66908
|
setSourceReport((currentReport) => {
|
|
@@ -65707,7 +66922,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
65707
66922
|
return getChartTypeOptions2({ pivot: pivotState });
|
|
65708
66923
|
}, [pivotState]);
|
|
65709
66924
|
const resolvedChartType = chartTypes.find((option) => option.value === chartType)?.value ?? chartTypes.find((option) => option.value === sourceReport?.chartType)?.value ?? chartTypes.find((option) => option.value === DEFAULT_CHART_TYPE)?.value ?? chartTypes[0]?.value ?? DEFAULT_CHART_TYPE;
|
|
65710
|
-
|
|
66925
|
+
useEffect32(() => {
|
|
65711
66926
|
if (!sourceReport) {
|
|
65712
66927
|
return;
|
|
65713
66928
|
}
|
|
@@ -66202,7 +67417,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66202
67417
|
);
|
|
66203
67418
|
return hasSamePivot && sourceFilterStackHash === filterStackHash;
|
|
66204
67419
|
}, [filterStackHash, nextPivot, sourceReport]);
|
|
66205
|
-
|
|
67420
|
+
useEffect32(() => {
|
|
66206
67421
|
if (!pendingPivotRefresh) return;
|
|
66207
67422
|
if (!nextPivot) {
|
|
66208
67423
|
if (!sourceReport) {
|
|
@@ -66261,10 +67476,19 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66261
67476
|
flagHash,
|
|
66262
67477
|
clientHash
|
|
66263
67478
|
}),
|
|
66264
|
-
queryFn: createUseFormQueryFn(async () => {
|
|
67479
|
+
queryFn: createUseFormQueryFn(async (signal) => {
|
|
66265
67480
|
if (!effectiveReportBuilderState || !nextPivot || !sourceReport || !client) {
|
|
66266
67481
|
return { report: null, error: "Missing pivot refresh prerequisites" };
|
|
66267
67482
|
}
|
|
67483
|
+
const cachedReport = await resolveCachedReport({
|
|
67484
|
+
reportBuilderState: effectiveReportBuilderState,
|
|
67485
|
+
filters: customFilters,
|
|
67486
|
+
pivot: nextPivot,
|
|
67487
|
+
operation: "pivot"
|
|
67488
|
+
});
|
|
67489
|
+
if (cachedReport) {
|
|
67490
|
+
return { report: cachedReport };
|
|
67491
|
+
}
|
|
66268
67492
|
const pivotRefreshBaseReport = {
|
|
66269
67493
|
...sourceReport,
|
|
66270
67494
|
reportBuilderState: effectiveReportBuilderState
|
|
@@ -66284,7 +67508,8 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66284
67508
|
customFields: schemaData.customFields,
|
|
66285
67509
|
dashboardName: resolvedSourceDashboardName,
|
|
66286
67510
|
useInMemoryEngines,
|
|
66287
|
-
draftSessionId: draftSessionId || void 0
|
|
67511
|
+
draftSessionId: draftSessionId || void 0,
|
|
67512
|
+
abortSignal: signal
|
|
66288
67513
|
});
|
|
66289
67514
|
return pivotRefreshResult;
|
|
66290
67515
|
}),
|
|
@@ -66295,16 +67520,28 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66295
67520
|
queryKey: createUseFormPivotTableDataRefreshQueryKey({
|
|
66296
67521
|
reportId: effectiveReportId,
|
|
66297
67522
|
reportBuilderStateHash: pivotTableDataReportBuilderStateHash,
|
|
67523
|
+
pageSize: pagination.pageSize,
|
|
66298
67524
|
tenantHash,
|
|
66299
67525
|
clientHash
|
|
66300
67526
|
}),
|
|
66301
|
-
queryFn: createUseFormQueryFn(async () => {
|
|
67527
|
+
queryFn: createUseFormQueryFn(async (signal) => {
|
|
66302
67528
|
if (!pivotTableDataReportBuilderState || !sourceReport || !client) {
|
|
66303
67529
|
return {
|
|
66304
67530
|
report: null,
|
|
66305
67531
|
error: "Missing pivot table-data refresh prerequisites"
|
|
66306
67532
|
};
|
|
66307
67533
|
}
|
|
67534
|
+
const cachedReport = await resolveCachedReport({
|
|
67535
|
+
reportBuilderState: pivotTableDataReportBuilderState,
|
|
67536
|
+
filters: customFiltersFromFilterStack(
|
|
67537
|
+
pivotTableDataReportBuilderState.filterStack
|
|
67538
|
+
),
|
|
67539
|
+
pivot: null,
|
|
67540
|
+
operation: "pivot-table"
|
|
67541
|
+
});
|
|
67542
|
+
if (cachedReport) {
|
|
67543
|
+
return { report: cachedReport };
|
|
67544
|
+
}
|
|
66308
67545
|
const tableDataResult = await loadViaReportBuilderState({
|
|
66309
67546
|
reportId: effectiveReportId,
|
|
66310
67547
|
reportBuilderState: pivotTableDataReportBuilderState,
|
|
@@ -66315,7 +67552,12 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66315
67552
|
customFields: schemaData.customFields,
|
|
66316
67553
|
dashboardName: resolvedSourceDashboardName,
|
|
66317
67554
|
report: sourceReport,
|
|
66318
|
-
draftSessionId: draftSessionId || void 0
|
|
67555
|
+
draftSessionId: draftSessionId || void 0,
|
|
67556
|
+
pagination: {
|
|
67557
|
+
pageIndex: 0,
|
|
67558
|
+
pageSize: pagination.pageSize
|
|
67559
|
+
},
|
|
67560
|
+
abortSignal: signal
|
|
66319
67561
|
});
|
|
66320
67562
|
return tableDataResult;
|
|
66321
67563
|
}),
|
|
@@ -66324,28 +67566,20 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66324
67566
|
});
|
|
66325
67567
|
const tablePageReportBuilderState = pivotTableDataReportBuilderState ?? effectiveReportBuilderState;
|
|
66326
67568
|
const tablePageReportBuilderStateHash = pivotTableDataReportBuilderState ? pivotTableDataReportBuilderStateHash : effectiveReportBuilderStateHash;
|
|
66327
|
-
const tablePaginationSort = useMemo33(
|
|
66328
|
-
|
|
66329
|
-
|
|
66330
|
-
|
|
66331
|
-
|
|
66332
|
-
|
|
66333
|
-
|
|
66334
|
-
(column) => String(column?.field ?? "").trim() === field
|
|
66335
|
-
);
|
|
66336
|
-
if (!isOutputColumn) {
|
|
66337
|
-
return void 0;
|
|
66338
|
-
}
|
|
66339
|
-
const direction = String(sortEntry?.direction ?? "ASC").toUpperCase() === "DESC" ? "DESC" : "ASC";
|
|
66340
|
-
return { field, direction };
|
|
66341
|
-
}, [tablePageReportBuilderState]);
|
|
67569
|
+
const tablePaginationSort = useMemo33(
|
|
67570
|
+
() => getStablePaginationSort({
|
|
67571
|
+
columns: tablePageReportBuilderState?.columns,
|
|
67572
|
+
sort: tablePageReportBuilderState?.sort
|
|
67573
|
+
}),
|
|
67574
|
+
[tablePageReportBuilderState]
|
|
67575
|
+
);
|
|
66342
67576
|
const baseWindowRowsLength = Array.isArray(sourceReport?.rows) ? sourceReport.rows.length : 0;
|
|
66343
67577
|
const sourceReportRowCount = typeof sourceReport?.rowCount === "number" ? sourceReport.rowCount : void 0;
|
|
66344
67578
|
const trustedSourceRowCount = sourceReportRowCount !== void 0 && (sourceReportRowCount > 0 || baseWindowRowsLength === 0) && sourceReportRowCount >= baseWindowRowsLength ? sourceReportRowCount : void 0;
|
|
66345
67579
|
const paginationRangeStart = pagination.pageIndex * pagination.pageSize;
|
|
66346
67580
|
const paginationRangeEnd = paginationRangeStart + pagination.pageSize;
|
|
66347
67581
|
const pageWithinBaseWindow = paginationRangeEnd <= baseWindowRowsLength || trustedSourceRowCount !== void 0 && trustedSourceRowCount <= baseWindowRowsLength;
|
|
66348
|
-
const tablePageQueryEnabled =
|
|
67582
|
+
const tablePageQueryEnabled = !pageWithinBaseWindow && !reportOverride && !useInMemoryEngines && Boolean(client) && Boolean(sourceReport) && Boolean(tablePageReportBuilderState) && sourceReportMatchesEffectiveReportId && !pendingPivotRefresh;
|
|
66349
67583
|
const tablePageQuery = useQuery({
|
|
66350
67584
|
queryKey: createUseFormTablePageQueryKey({
|
|
66351
67585
|
reportId: effectiveReportId,
|
|
@@ -66356,7 +67590,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66356
67590
|
tenantHash,
|
|
66357
67591
|
clientHash
|
|
66358
67592
|
}),
|
|
66359
|
-
queryFn: createUseFormQueryFn(async () => {
|
|
67593
|
+
queryFn: createUseFormQueryFn(async (signal) => {
|
|
66360
67594
|
if (!tablePageReportBuilderState || !sourceReport || !client) {
|
|
66361
67595
|
return { report: null, error: "Missing table page prerequisites" };
|
|
66362
67596
|
}
|
|
@@ -66376,7 +67610,8 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66376
67610
|
pageSize: pagination.pageSize
|
|
66377
67611
|
},
|
|
66378
67612
|
paginationSort: tablePaginationSort,
|
|
66379
|
-
rowsOnly: true
|
|
67613
|
+
rowsOnly: true,
|
|
67614
|
+
abortSignal: signal
|
|
66380
67615
|
});
|
|
66381
67616
|
}),
|
|
66382
67617
|
enabled: tablePageQueryEnabled,
|
|
@@ -66410,7 +67645,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66410
67645
|
pagination.pageSize
|
|
66411
67646
|
);
|
|
66412
67647
|
paginationPageCountRef.current = paginationPageCount;
|
|
66413
|
-
|
|
67648
|
+
useEffect32(() => {
|
|
66414
67649
|
if (!pivotTableDataRefreshQueryEnabled) return;
|
|
66415
67650
|
if (pivotTableDataRefreshQuery.status !== "success" && pivotTableDataRefreshQuery.status !== "error") {
|
|
66416
67651
|
return;
|
|
@@ -66451,7 +67686,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66451
67686
|
pivotTableDataRefreshQueryEnabled,
|
|
66452
67687
|
effectiveReportId
|
|
66453
67688
|
]);
|
|
66454
|
-
|
|
67689
|
+
useEffect32(() => {
|
|
66455
67690
|
if (!pivotRefreshQueryEnabled) return;
|
|
66456
67691
|
if (pivotRefreshQuery.status !== "success" && pivotRefreshQuery.status !== "error") {
|
|
66457
67692
|
return;
|
|
@@ -66841,18 +68076,18 @@ function useReport(reportIdArg, options = {}) {
|
|
|
66841
68076
|
resolvedYAxisFieldsForDisplay
|
|
66842
68077
|
);
|
|
66843
68078
|
if (String(baseChart.chartType ?? "").toLowerCase() === "table" && baseChart.pivot) {
|
|
66844
|
-
const
|
|
68079
|
+
const pivotAggregations2 = getPivotAggregations(baseChart);
|
|
66845
68080
|
const hasCustomMeasureLabel = resolvedYAxisFields.some((axis) => {
|
|
66846
68081
|
const aggregation = findAggregationForFieldStrict(
|
|
66847
68082
|
axis.field,
|
|
66848
|
-
|
|
68083
|
+
pivotAggregations2
|
|
66849
68084
|
);
|
|
66850
68085
|
if (!aggregation) return false;
|
|
66851
68086
|
const label = String(axis.label ?? "").trim();
|
|
66852
68087
|
const defaultLabel = buildAggregationLabel(aggregation, baseChart);
|
|
66853
68088
|
return Boolean(label) && label !== defaultLabel;
|
|
66854
68089
|
});
|
|
66855
|
-
if (
|
|
68090
|
+
if (pivotAggregations2.length > 1 || hasCustomMeasureLabel) {
|
|
66856
68091
|
columns2 = mergePivotTableDisplayColumnLabelsFromYAxis({
|
|
66857
68092
|
columns: columns2 ?? baseChart.columns,
|
|
66858
68093
|
yAxisFields: resolvedYAxisFieldsForDisplay,
|
|
@@ -67204,7 +68439,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
67204
68439
|
);
|
|
67205
68440
|
const table = useMemo33(() => {
|
|
67206
68441
|
const baseWindowRows = Array.isArray(sourceReport?.rows) ? sourceReport.rows : [];
|
|
67207
|
-
const rawRows =
|
|
68442
|
+
const rawRows = tablePageRows ?? baseWindowRows.slice(paginationRangeStart, paginationRangeEnd);
|
|
67208
68443
|
const { columns: mergedFromReport } = mergeDisplayAndSourceForTableFormats({
|
|
67209
68444
|
effectiveReportBuilderTableNames,
|
|
67210
68445
|
scopedSchemaColumns,
|
|
@@ -67313,7 +68548,6 @@ function useReport(reportIdArg, options = {}) {
|
|
|
67313
68548
|
sourceReport,
|
|
67314
68549
|
tableColumnsEditedSignature,
|
|
67315
68550
|
pagination,
|
|
67316
|
-
paginationActive,
|
|
67317
68551
|
paginationPageCount,
|
|
67318
68552
|
paginationRangeEnd,
|
|
67319
68553
|
paginationRangeStart,
|
|
@@ -68399,15 +69633,54 @@ function useReport(reportIdArg, options = {}) {
|
|
|
68399
69633
|
});
|
|
68400
69634
|
}
|
|
68401
69635
|
} catch (error) {
|
|
69636
|
+
const requestedFieldNames = (resolved?.rules ?? []).map((rule) => String(rule?.field ?? "").trim()).filter(Boolean);
|
|
69637
|
+
const relevantFieldConfigs = Object.fromEntries(
|
|
69638
|
+
Object.entries(queryBuilderFieldConfigByName ?? {}).filter(
|
|
69639
|
+
([key, config]) => {
|
|
69640
|
+
const configuredField = String(config?.field ?? "").trim();
|
|
69641
|
+
return requestedFieldNames.some((requestedField) => {
|
|
69642
|
+
const bareRequestedField = requestedField.split(".").pop() ?? "";
|
|
69643
|
+
return key === requestedField || configuredField === requestedField || configuredField === bareRequestedField;
|
|
69644
|
+
});
|
|
69645
|
+
}
|
|
69646
|
+
)
|
|
69647
|
+
);
|
|
68402
69648
|
console.error("[useForm] setFilters swallowed error", {
|
|
68403
69649
|
error: error instanceof Error ? error.message : String(error),
|
|
68404
69650
|
stack: error instanceof Error ? error.stack : void 0,
|
|
69651
|
+
reportId: effectiveReportId,
|
|
68405
69652
|
requestedRules: (resolved?.rules ?? []).map((rule) => ({
|
|
68406
69653
|
table: rule?.table,
|
|
68407
69654
|
field: rule?.field,
|
|
68408
69655
|
operator: rule?.operator,
|
|
68409
69656
|
value: rule?.value
|
|
68410
69657
|
})),
|
|
69658
|
+
normalizedRules: (nextFiltersNormalizedForConfig?.rules ?? []).map((rule) => ({
|
|
69659
|
+
table: rule?.table,
|
|
69660
|
+
field: rule?.field,
|
|
69661
|
+
operator: rule?.operator,
|
|
69662
|
+
value: rule?.value
|
|
69663
|
+
})),
|
|
69664
|
+
relevantFieldConfigs,
|
|
69665
|
+
pivot: nextPivot,
|
|
69666
|
+
reportBuilderTables: effectiveReportBuilderState?.tables,
|
|
69667
|
+
reportBuilderColumns: effectiveReportBuilderColumns.filter(
|
|
69668
|
+
(column) => requestedFieldNames.some((requestedField) => {
|
|
69669
|
+
const bareRequestedField = requestedField.split(".").pop() ?? "";
|
|
69670
|
+
return String(column.field ?? "").trim() === bareRequestedField;
|
|
69671
|
+
})
|
|
69672
|
+
).map((column) => ({
|
|
69673
|
+
table: column.table,
|
|
69674
|
+
field: column.field,
|
|
69675
|
+
alias: column.alias
|
|
69676
|
+
})),
|
|
69677
|
+
schemaTablesWithRequestedFields: schemaForReportBuilderState.filter(
|
|
69678
|
+
(table2) => table2.columns?.some(
|
|
69679
|
+
(column) => requestedFieldNames.some(
|
|
69680
|
+
(requestedField) => String(column.field ?? "").trim() === (requestedField.split(".").pop() ?? "")
|
|
69681
|
+
)
|
|
69682
|
+
)
|
|
69683
|
+
).map((table2) => table2.name),
|
|
68411
69684
|
fieldConfigKeys: Object.keys(queryBuilderFieldConfigByName ?? {})
|
|
68412
69685
|
});
|
|
68413
69686
|
}
|
|
@@ -68457,8 +69730,19 @@ function useReport(reportIdArg, options = {}) {
|
|
|
68457
69730
|
tenants,
|
|
68458
69731
|
draftSessionId: draftSessionId || void 0
|
|
68459
69732
|
});
|
|
69733
|
+
const savedReportId = String(
|
|
69734
|
+
resp?.id ?? resp?._id ?? effectiveReportId ?? ""
|
|
69735
|
+
).trim();
|
|
69736
|
+
if (savedReportId && resp && resp.name !== "error" && !resp.error) {
|
|
69737
|
+
await cacheCab.evictReport(savedReportId, tenants);
|
|
69738
|
+
await queryClient.invalidateQueries({
|
|
69739
|
+
queryKey: ["quill", "dashboard-report", savedReportId],
|
|
69740
|
+
refetchType: "none"
|
|
69741
|
+
});
|
|
69742
|
+
}
|
|
68460
69743
|
return resp;
|
|
68461
69744
|
}, [
|
|
69745
|
+
cacheCab,
|
|
68462
69746
|
client,
|
|
68463
69747
|
dashboardNameForNewReport,
|
|
68464
69748
|
draftSessionId,
|
|
@@ -68467,6 +69751,7 @@ function useReport(reportIdArg, options = {}) {
|
|
|
68467
69751
|
eventTracking,
|
|
68468
69752
|
formReportName,
|
|
68469
69753
|
getToken,
|
|
69754
|
+
queryClient,
|
|
68470
69755
|
resolvedXAxisField,
|
|
68471
69756
|
resolvedXAxisFormat,
|
|
68472
69757
|
resolvedXAxisLabel,
|
|
@@ -68850,7 +70135,7 @@ function ToolCallBlock({ toolCall }) {
|
|
|
68850
70135
|
);
|
|
68851
70136
|
}
|
|
68852
70137
|
function ToolCallResult({ content }) {
|
|
68853
|
-
const [expanded, setExpanded] =
|
|
70138
|
+
const [expanded, setExpanded] = useState43(false);
|
|
68854
70139
|
if (!content) return null;
|
|
68855
70140
|
const isLong = content.length > 300;
|
|
68856
70141
|
const displayed = isLong && !expanded ? content.slice(0, 300) + "..." : content;
|
|
@@ -68905,15 +70190,15 @@ function Chat({
|
|
|
68905
70190
|
const [client] = useContext37(ClientContext);
|
|
68906
70191
|
const { getToken } = useContext37(FetchContext);
|
|
68907
70192
|
const { tenants } = useContext37(TenantContext);
|
|
68908
|
-
const [messages, setMessages] =
|
|
68909
|
-
const [input, setInput] =
|
|
68910
|
-
const [inputError, setInputError] =
|
|
68911
|
-
const [isLoading, setIsLoading] =
|
|
68912
|
-
const [model, setModel] =
|
|
70193
|
+
const [messages, setMessages] = useState43([]);
|
|
70194
|
+
const [input, setInput] = useState43("");
|
|
70195
|
+
const [inputError, setInputError] = useState43("");
|
|
70196
|
+
const [isLoading, setIsLoading] = useState43(false);
|
|
70197
|
+
const [model, setModel] = useState43("gemini-3-flash-preview");
|
|
68913
70198
|
const containerRef = useRef25(null);
|
|
68914
70199
|
const textareaRef = useRef25(null);
|
|
68915
70200
|
const abortControllerRef = useRef25(null);
|
|
68916
|
-
|
|
70201
|
+
useEffect33(() => {
|
|
68917
70202
|
if (!containerRef.current) {
|
|
68918
70203
|
return;
|
|
68919
70204
|
}
|
|
@@ -69347,7 +70632,7 @@ function Chat({
|
|
|
69347
70632
|
}
|
|
69348
70633
|
|
|
69349
70634
|
// src/hooks/useReportFilterDraft.ts
|
|
69350
|
-
import { useCallback as useCallback6, useEffect as
|
|
70635
|
+
import { useCallback as useCallback6, useEffect as useEffect34, useMemo as useMemo35, useRef as useRef26, useState as useState44 } from "react";
|
|
69351
70636
|
var normalizeOperatorKey = (operator) => String(operator ?? "").trim().toLowerCase().replace(/[_\s]+/g, "");
|
|
69352
70637
|
var defaultFilterRuleValueForOperator = (operator) => {
|
|
69353
70638
|
const key = normalizeOperatorKey(operator);
|
|
@@ -69409,11 +70694,11 @@ function useReportFilterDraft(args) {
|
|
|
69409
70694
|
() => fieldCatalogSignature(effectiveFields),
|
|
69410
70695
|
[effectiveFields]
|
|
69411
70696
|
);
|
|
69412
|
-
const [resetEpoch, setResetEpoch] =
|
|
69413
|
-
const [draftQuery, setDraftQuery] =
|
|
69414
|
-
const [hasUnappliedFilterChanges, setHasUnappliedFilterChanges] =
|
|
70697
|
+
const [resetEpoch, setResetEpoch] = useState44(0);
|
|
70698
|
+
const [draftQuery, setDraftQuery] = useState44(committed);
|
|
70699
|
+
const [hasUnappliedFilterChanges, setHasUnappliedFilterChanges] = useState44(false);
|
|
69415
70700
|
const draftResetKey = `${reportId}|${committedSignature}|${resetEpoch}`;
|
|
69416
|
-
|
|
70701
|
+
useEffect34(() => {
|
|
69417
70702
|
setDraftQuery(committedRef.current);
|
|
69418
70703
|
setHasUnappliedFilterChanges(false);
|
|
69419
70704
|
}, [draftResetKey]);
|
|
@@ -69505,7 +70790,7 @@ import {
|
|
|
69505
70790
|
useContext as useContext38,
|
|
69506
70791
|
useLayoutEffect as useLayoutEffect5,
|
|
69507
70792
|
useRef as useRef27,
|
|
69508
|
-
useState as
|
|
70793
|
+
useState as useState45
|
|
69509
70794
|
} from "react";
|
|
69510
70795
|
import { jsx as jsx89, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
69511
70796
|
var CHART_MIN_PX = 220;
|
|
@@ -69607,14 +70892,14 @@ function ReportDetail({
|
|
|
69607
70892
|
const useDetailTableFromUseForm = isTableChart && !isPivotTableChartConfig(chart);
|
|
69608
70893
|
const showBottomRawTable = !isTableChart;
|
|
69609
70894
|
const chartSlotRef = useRef27(null);
|
|
69610
|
-
const [chartHeightPx, setChartHeightPx] =
|
|
70895
|
+
const [chartHeightPx, setChartHeightPx] = useState45(360);
|
|
69611
70896
|
useLayoutEffect5(() => {
|
|
69612
70897
|
const el = chartSlotRef.current;
|
|
69613
70898
|
if (!el) {
|
|
69614
70899
|
return;
|
|
69615
70900
|
}
|
|
69616
|
-
const ro = new ResizeObserver((
|
|
69617
|
-
const entry =
|
|
70901
|
+
const ro = new ResizeObserver((entries2) => {
|
|
70902
|
+
const entry = entries2[0];
|
|
69618
70903
|
if (!entry) return;
|
|
69619
70904
|
const h = Math.floor(entry.contentRect.height);
|
|
69620
70905
|
if (h >= CHART_MIN_PX) {
|
|
@@ -69733,7 +71018,7 @@ function ReportDetail({
|
|
|
69733
71018
|
init_valueFormatter();
|
|
69734
71019
|
|
|
69735
71020
|
// src/hooks/useTenants.ts
|
|
69736
|
-
import { useContext as useContext39, useEffect as
|
|
71021
|
+
import { useContext as useContext39, useEffect as useEffect35 } from "react";
|
|
69737
71022
|
var useTenants = (dashboardName) => {
|
|
69738
71023
|
const {
|
|
69739
71024
|
tenants,
|
|
@@ -69747,12 +71032,12 @@ var useTenants = (dashboardName) => {
|
|
|
69747
71032
|
getMappedTenantsForDashboard,
|
|
69748
71033
|
getViewerTenantsByOwner
|
|
69749
71034
|
} = useContext39(TenantContext);
|
|
69750
|
-
|
|
71035
|
+
useEffect35(() => {
|
|
69751
71036
|
if (dashboardName) {
|
|
69752
71037
|
fetchViewerTenantsForDashboard(dashboardName);
|
|
69753
71038
|
}
|
|
69754
71039
|
}, [dashboardName, fetchViewerTenantsForDashboard]);
|
|
69755
|
-
|
|
71040
|
+
useEffect35(() => {
|
|
69756
71041
|
if (dashboardName) {
|
|
69757
71042
|
fetchMappedTenantsForDashboard(dashboardName);
|
|
69758
71043
|
}
|
|
@@ -69771,7 +71056,7 @@ var useTenants = (dashboardName) => {
|
|
|
69771
71056
|
};
|
|
69772
71057
|
|
|
69773
71058
|
// src/hooks/useQuill.ts
|
|
69774
|
-
import { useContext as useContext40, useEffect as
|
|
71059
|
+
import { useContext as useContext40, useEffect as useEffect36, useMemo as useMemo36, useState as useState46 } from "react";
|
|
69775
71060
|
init_paginationProcessing();
|
|
69776
71061
|
init_tableProcessing();
|
|
69777
71062
|
init_dataProcessing();
|
|
@@ -69794,9 +71079,9 @@ var useQuill = (reportId, pagination) => {
|
|
|
69794
71079
|
const [client, isClientLoading] = useContext40(ClientContext);
|
|
69795
71080
|
const { tenants } = useContext40(TenantContext);
|
|
69796
71081
|
const { eventTracking } = useContext40(EventTrackingContext);
|
|
69797
|
-
const [loading, setLoading] =
|
|
69798
|
-
const [error, setError] =
|
|
69799
|
-
const [previousPage, setPreviousPage] =
|
|
71082
|
+
const [loading, setLoading] = useState46(true);
|
|
71083
|
+
const [error, setError] = useState46(void 0);
|
|
71084
|
+
const [previousPage, setPreviousPage] = useState46(0);
|
|
69800
71085
|
const processedReport = useMemo36(() => {
|
|
69801
71086
|
return reportId && allReportsById[reportId] ? convertInternalReportToReport(
|
|
69802
71087
|
mergeComparisonRange(allReportsById[reportId]),
|
|
@@ -69805,7 +71090,7 @@ var useQuill = (reportId, pagination) => {
|
|
|
69805
71090
|
"useQuill"
|
|
69806
71091
|
) : void 0;
|
|
69807
71092
|
}, [reportId, reportId && allReportsById[reportId], specificReportFilters]);
|
|
69808
|
-
const [additionalProcessing, setAdditionProcessing] =
|
|
71093
|
+
const [additionalProcessing, setAdditionProcessing] = useState46(
|
|
69809
71094
|
pagination ? {
|
|
69810
71095
|
page: pagination
|
|
69811
71096
|
} : void 0
|
|
@@ -69954,7 +71239,7 @@ var useQuill = (reportId, pagination) => {
|
|
|
69954
71239
|
setLoading(false);
|
|
69955
71240
|
}
|
|
69956
71241
|
};
|
|
69957
|
-
|
|
71242
|
+
useEffect36(() => {
|
|
69958
71243
|
if (isClientLoading) return;
|
|
69959
71244
|
if (reportId && specificReportFilters) {
|
|
69960
71245
|
fetchReportHelper(reportId, {
|
|
@@ -70021,7 +71306,7 @@ var useMemoizedRows = (reportId) => {
|
|
|
70021
71306
|
};
|
|
70022
71307
|
|
|
70023
71308
|
// src/hooks/useAskQuill.tsx
|
|
70024
|
-
import { useContext as useContext41, useEffect as
|
|
71309
|
+
import { useContext as useContext41, useEffect as useEffect37, useState as useState47 } from "react";
|
|
70025
71310
|
init_astProcessing();
|
|
70026
71311
|
init_astFilterProcessing();
|
|
70027
71312
|
init_pivotProcessing();
|
|
@@ -70054,8 +71339,8 @@ var useAskQuill = (dashboardName) => {
|
|
|
70054
71339
|
const { tenants } = useContext41(TenantContext);
|
|
70055
71340
|
const { getToken } = useContext41(FetchContext);
|
|
70056
71341
|
const { eventTracking } = useContext41(EventTrackingContext);
|
|
70057
|
-
const [astInfo, setAstInfo] =
|
|
70058
|
-
const [data, setData] =
|
|
71342
|
+
const [astInfo, setAstInfo] = useState47(void 0);
|
|
71343
|
+
const [data, setData] = useState47({
|
|
70059
71344
|
rows: [],
|
|
70060
71345
|
columns: [],
|
|
70061
71346
|
pivot: null,
|
|
@@ -70065,9 +71350,9 @@ var useAskQuill = (dashboardName) => {
|
|
|
70065
71350
|
pivotColumnFields: [],
|
|
70066
71351
|
pivotValueFields: []
|
|
70067
71352
|
});
|
|
70068
|
-
const [loading, setLoading] =
|
|
70069
|
-
const [error, setError] =
|
|
70070
|
-
const [ask, setAsk] =
|
|
71353
|
+
const [loading, setLoading] = useState47(false);
|
|
71354
|
+
const [error, setError] = useState47(void 0);
|
|
71355
|
+
const [ask, setAsk] = useState47(
|
|
70071
71356
|
async () => void 0
|
|
70072
71357
|
);
|
|
70073
71358
|
const askHelper = async (query) => {
|
|
@@ -70267,7 +71552,7 @@ var useAskQuill = (dashboardName) => {
|
|
|
70267
71552
|
});
|
|
70268
71553
|
setLoading(false);
|
|
70269
71554
|
};
|
|
70270
|
-
|
|
71555
|
+
useEffect37(() => {
|
|
70271
71556
|
setAsk(() => askHelper);
|
|
70272
71557
|
}, [schemaData.schema]);
|
|
70273
71558
|
return {
|
|
@@ -70281,13 +71566,13 @@ var useAskQuill = (dashboardName) => {
|
|
|
70281
71566
|
};
|
|
70282
71567
|
|
|
70283
71568
|
// src/hooks/useVirtualTables.tsx
|
|
70284
|
-
import { useContext as useContext42, useState as
|
|
71569
|
+
import { useContext as useContext42, useState as useState48 } from "react";
|
|
70285
71570
|
var useVirtualTables = () => {
|
|
70286
71571
|
const [schemaData, setSchemaData] = useContext42(SchemaDataContext);
|
|
70287
71572
|
const { tenants } = useContext42(TenantContext);
|
|
70288
71573
|
const { getToken, quillFetchWithToken } = useContext42(FetchContext);
|
|
70289
71574
|
const { eventTracking } = useContext42(EventTrackingContext);
|
|
70290
|
-
const [loadingTables, setLoadingTables] =
|
|
71575
|
+
const [loadingTables, setLoadingTables] = useState48({});
|
|
70291
71576
|
const handleReload = async (client, caller) => {
|
|
70292
71577
|
setSchemaData({ ...schemaData, isSchemaLoading: true });
|
|
70293
71578
|
setLoadingTables(
|
|
@@ -70457,14 +71742,14 @@ var useChangelogRefresh = () => {
|
|
|
70457
71742
|
const [, setSchemaData] = useContext43(SchemaDataContext);
|
|
70458
71743
|
const { allReportsById } = useAllReports();
|
|
70459
71744
|
const { reloadSome } = useVirtualTables();
|
|
70460
|
-
const refreshChangelogEntries = async (
|
|
71745
|
+
const refreshChangelogEntries = async (entries2, client) => {
|
|
70461
71746
|
const dashboardsToReload = /* @__PURE__ */ new Set();
|
|
70462
71747
|
let reloadAllDashboards = false;
|
|
70463
71748
|
const schemaIds = [];
|
|
70464
71749
|
const schemaIdsToRemove = /* @__PURE__ */ new Set();
|
|
70465
71750
|
const dashboardsToRemove = /* @__PURE__ */ new Set();
|
|
70466
71751
|
const reportsToRemove = /* @__PURE__ */ new Map();
|
|
70467
|
-
for (const entry of
|
|
71752
|
+
for (const entry of entries2) {
|
|
70468
71753
|
if (!entry.entityId || !entry.entityType) continue;
|
|
70469
71754
|
const changeType = getChangeType(entry);
|
|
70470
71755
|
switch (entry.entityType) {
|