@quillsql/react 2.16.20 → 2.16.21
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 +2413 -198
- package/dist/index.d.cts +23 -2
- package/dist/index.d.ts +23 -2
- package/dist/index.js +2410 -177
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1572,6 +1572,7 @@ var init_dateRangePickerUtils = __esm({
|
|
|
1572
1572
|
}
|
|
1573
1573
|
});
|
|
1574
1574
|
const defaultCustomIntervals = defaultIntervals.flatMap((interval2) => {
|
|
1575
|
+
const normalizedLabel = interval2.label?.toLowerCase().trim();
|
|
1575
1576
|
let createdIntervals = [];
|
|
1576
1577
|
if (interval2.label === "This week") {
|
|
1577
1578
|
createdIntervals = [
|
|
@@ -1721,13 +1722,13 @@ var init_dateRangePickerUtils = __esm({
|
|
|
1721
1722
|
unit: "months"
|
|
1722
1723
|
}
|
|
1723
1724
|
];
|
|
1724
|
-
} else if (
|
|
1725
|
+
} else if (normalizedLabel === "last month") {
|
|
1725
1726
|
createdIntervals = [
|
|
1726
1727
|
{
|
|
1727
1728
|
type: "previous_month"
|
|
1728
1729
|
}
|
|
1729
1730
|
];
|
|
1730
|
-
} else if (
|
|
1731
|
+
} else if (normalizedLabel === "previous quarter" || normalizedLabel === "last quarter") {
|
|
1731
1732
|
createdIntervals = [
|
|
1732
1733
|
{
|
|
1733
1734
|
type: "previous_quarter"
|
|
@@ -2121,13 +2122,13 @@ var init_Filter = __esm({
|
|
|
2121
2122
|
TimeUnit2[TimeUnit2["Hour"] = HOUR] = "Hour";
|
|
2122
2123
|
return TimeUnit2;
|
|
2123
2124
|
})(TimeUnit || {});
|
|
2124
|
-
FieldType = /* @__PURE__ */ ((
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
return
|
|
2125
|
+
FieldType = /* @__PURE__ */ ((FieldType3) => {
|
|
2126
|
+
FieldType3[FieldType3["String"] = STRING] = "String";
|
|
2127
|
+
FieldType3[FieldType3["Number"] = NUMBER] = "Number";
|
|
2128
|
+
FieldType3[FieldType3["Date"] = DATE] = "Date";
|
|
2129
|
+
FieldType3[FieldType3["Null"] = NULL] = "Null";
|
|
2130
|
+
FieldType3[FieldType3["Boolean"] = BOOLEAN] = "Boolean";
|
|
2131
|
+
return FieldType3;
|
|
2131
2132
|
})(FieldType || {});
|
|
2132
2133
|
InternalFilterType = /* @__PURE__ */ ((InternalFilterType2) => {
|
|
2133
2134
|
InternalFilterType2["StringFilter"] = "string-filter";
|
|
@@ -2273,7 +2274,7 @@ var init_Filter = __esm({
|
|
|
2273
2274
|
fieldType = FieldType.Boolean;
|
|
2274
2275
|
operator = filter.operator;
|
|
2275
2276
|
field = filter.field;
|
|
2276
|
-
value =
|
|
2277
|
+
value = filter.value;
|
|
2277
2278
|
table = filter.table;
|
|
2278
2279
|
return {
|
|
2279
2280
|
filterType,
|
|
@@ -2284,7 +2285,7 @@ var init_Filter = __esm({
|
|
|
2284
2285
|
operator
|
|
2285
2286
|
};
|
|
2286
2287
|
case "date" /* Date */:
|
|
2287
|
-
if (typeof filter.value === "object" && filter.value && "
|
|
2288
|
+
if (typeof filter.value === "object" && filter.value && "unit" in filter.value) {
|
|
2288
2289
|
if (filter.value.value && typeof filter.value.value !== "number" || typeof filter.value.unit !== "string") {
|
|
2289
2290
|
throw new Error(
|
|
2290
2291
|
`Invalid value for DateFilter, expected { value: number, unit: string }, got ${filter.value}`
|
|
@@ -2340,7 +2341,7 @@ var init_Filter = __esm({
|
|
|
2340
2341
|
table = filter.table;
|
|
2341
2342
|
} else {
|
|
2342
2343
|
throw new Error(
|
|
2343
|
-
`Invalid value for DateFilter, expected { value
|
|
2344
|
+
`Invalid value for DateFilter, expected { value?: number, unit: string }, { startDate: string, endDate: string}, or string, got ${filter.value}`
|
|
2344
2345
|
);
|
|
2345
2346
|
}
|
|
2346
2347
|
return {
|
|
@@ -15951,7 +15952,7 @@ var init_dataProcessing = __esm({
|
|
|
15951
15952
|
} else {
|
|
15952
15953
|
if (data.dateField && data.dateField.field) {
|
|
15953
15954
|
const dateField = data.dateField.field.replaceAll('"', "");
|
|
15954
|
-
const
|
|
15955
|
+
const maxDate2 = new Date(
|
|
15955
15956
|
data.rows.reduce((acc, row) => {
|
|
15956
15957
|
const rowValue = row[dateField];
|
|
15957
15958
|
if (rowValue) {
|
|
@@ -15960,7 +15961,7 @@ var init_dataProcessing = __esm({
|
|
|
15960
15961
|
return Math.max(acc, 0);
|
|
15961
15962
|
}, 0)
|
|
15962
15963
|
);
|
|
15963
|
-
const
|
|
15964
|
+
const minDate2 = new Date(
|
|
15964
15965
|
data.rows.reduce((acc, row) => {
|
|
15965
15966
|
const rowValue = row[dateField];
|
|
15966
15967
|
if (rowValue) {
|
|
@@ -15970,16 +15971,16 @@ var init_dataProcessing = __esm({
|
|
|
15970
15971
|
}, (/* @__PURE__ */ new Date("3022-01-01")).getTime())
|
|
15971
15972
|
);
|
|
15972
15973
|
const dateBucket = getDateBucketFromRange({
|
|
15973
|
-
start:
|
|
15974
|
-
end:
|
|
15974
|
+
start: minDate2,
|
|
15975
|
+
end: maxDate2
|
|
15975
15976
|
});
|
|
15976
15977
|
const minDateBucket = getDateString(
|
|
15977
|
-
|
|
15978
|
+
minDate2.toISOString(),
|
|
15978
15979
|
void 0,
|
|
15979
15980
|
dateBucket
|
|
15980
15981
|
);
|
|
15981
15982
|
const maxDateBucket = getDateString(
|
|
15982
|
-
|
|
15983
|
+
maxDate2.toISOString(),
|
|
15983
15984
|
void 0,
|
|
15984
15985
|
dateBucket
|
|
15985
15986
|
);
|
|
@@ -16096,8 +16097,9 @@ async function generatePivotWithSQL({
|
|
|
16096
16097
|
getPivotRowCount = true,
|
|
16097
16098
|
caller,
|
|
16098
16099
|
getToken,
|
|
16099
|
-
reportBuilderState
|
|
16100
|
+
reportBuilderState,
|
|
16100
16101
|
// Add reportBuilderState parameter
|
|
16102
|
+
overwriteCache = false
|
|
16101
16103
|
}) {
|
|
16102
16104
|
const databaseType = client.databaseType || "postgresql";
|
|
16103
16105
|
if (!pivot.aggregations?.length && pivot.aggregationType) {
|
|
@@ -16146,7 +16148,8 @@ async function generatePivotWithSQL({
|
|
|
16146
16148
|
})),
|
|
16147
16149
|
// Only pass dashboard filters in Dashboard context, not ReportBuilder
|
|
16148
16150
|
tenants,
|
|
16149
|
-
additionalProcessing
|
|
16151
|
+
additionalProcessing,
|
|
16152
|
+
overwriteCache
|
|
16150
16153
|
},
|
|
16151
16154
|
getToken
|
|
16152
16155
|
});
|
|
@@ -16320,8 +16323,9 @@ async function generatePivotTable({
|
|
|
16320
16323
|
additionalProcessing,
|
|
16321
16324
|
caller,
|
|
16322
16325
|
pivotQuery,
|
|
16323
|
-
reportBuilderState
|
|
16326
|
+
reportBuilderState,
|
|
16324
16327
|
// Add reportBuilderState parameter
|
|
16328
|
+
overwriteCache
|
|
16325
16329
|
}) {
|
|
16326
16330
|
try {
|
|
16327
16331
|
if (report && client) {
|
|
@@ -16338,8 +16342,9 @@ async function generatePivotTable({
|
|
|
16338
16342
|
additionalProcessing,
|
|
16339
16343
|
caller,
|
|
16340
16344
|
getToken,
|
|
16341
|
-
reportBuilderState
|
|
16345
|
+
reportBuilderState,
|
|
16342
16346
|
// Pass reportBuilderState
|
|
16347
|
+
overwriteCache
|
|
16343
16348
|
});
|
|
16344
16349
|
return pivotTable;
|
|
16345
16350
|
}
|
|
@@ -18224,7 +18229,7 @@ var init_tableProcessing = __esm({
|
|
|
18224
18229
|
try {
|
|
18225
18230
|
let data;
|
|
18226
18231
|
if (reportBuilderState) {
|
|
18227
|
-
|
|
18232
|
+
({ data } = await quillFetch({
|
|
18228
18233
|
client,
|
|
18229
18234
|
task: "report-builder-counts",
|
|
18230
18235
|
metadata: {
|
|
@@ -18238,9 +18243,9 @@ var init_tableProcessing = __esm({
|
|
|
18238
18243
|
tenants
|
|
18239
18244
|
},
|
|
18240
18245
|
getToken
|
|
18241
|
-
});
|
|
18246
|
+
}));
|
|
18242
18247
|
} else {
|
|
18243
|
-
|
|
18248
|
+
({ data } = await quillFetch({
|
|
18244
18249
|
client,
|
|
18245
18250
|
task: "query",
|
|
18246
18251
|
metadata: {
|
|
@@ -18254,7 +18259,7 @@ var init_tableProcessing = __esm({
|
|
|
18254
18259
|
},
|
|
18255
18260
|
urlParameters: `caller=getCounts&task=query`,
|
|
18256
18261
|
getToken
|
|
18257
|
-
});
|
|
18262
|
+
}));
|
|
18258
18263
|
}
|
|
18259
18264
|
if (data.errorMessage) {
|
|
18260
18265
|
return { filteredColumns: columns, exceededColumns: void 0 };
|
|
@@ -19244,9 +19249,9 @@ var init_dataFetcher = __esm({
|
|
|
19244
19249
|
return { error: "Failed to fetch data" };
|
|
19245
19250
|
}
|
|
19246
19251
|
};
|
|
19247
|
-
parseFetchResponse = async (client, task, response, getToken) => {
|
|
19252
|
+
parseFetchResponse = async (client, task, response, getToken, useInMemory = false) => {
|
|
19248
19253
|
try {
|
|
19249
|
-
if (response.status === "error" || response.data?.error) {
|
|
19254
|
+
if (response.status === "error" || response.data?.error && !useInMemory) {
|
|
19250
19255
|
let errorPrefix = "Error: ";
|
|
19251
19256
|
let errorMessage = "Failed to fetch report: " + (response.error || response.data?.error);
|
|
19252
19257
|
if (task === "query" || task === "report-builder") {
|
|
@@ -19831,7 +19836,8 @@ async function cleanDashboardItem({
|
|
|
19831
19836
|
additionalProcessing,
|
|
19832
19837
|
customFields,
|
|
19833
19838
|
skipPivotFetch,
|
|
19834
|
-
tenants
|
|
19839
|
+
tenants,
|
|
19840
|
+
overwriteCache
|
|
19835
19841
|
}) {
|
|
19836
19842
|
if (!item) return defaultDashboardItem;
|
|
19837
19843
|
if (!item.rows) {
|
|
@@ -19935,7 +19941,8 @@ async function cleanDashboardItem({
|
|
|
19935
19941
|
dateBucket,
|
|
19936
19942
|
shouldPaginatePivotAsTable ? additionalProcessing : pivotChartProcessing,
|
|
19937
19943
|
tenants,
|
|
19938
|
-
customFields
|
|
19944
|
+
customFields,
|
|
19945
|
+
overwriteCache
|
|
19939
19946
|
);
|
|
19940
19947
|
}
|
|
19941
19948
|
} catch (e) {
|
|
@@ -20040,7 +20047,7 @@ async function cleanDashboardItem({
|
|
|
20040
20047
|
referenceLines: item.referenceLines
|
|
20041
20048
|
};
|
|
20042
20049
|
}
|
|
20043
|
-
async function getPivotTable(report, dashboardFilters, dashboardName, getToken, client, eventTracking, dateBucketInitial, additionalProcessing, tenants, customFields) {
|
|
20050
|
+
async function getPivotTable(report, dashboardFilters, dashboardName, getToken, client, eventTracking, dateBucketInitial, additionalProcessing, tenants, customFields, overwriteCache) {
|
|
20044
20051
|
if (!report) return void 0;
|
|
20045
20052
|
const dateFilter = Object.values(dashboardFilters ?? {}).find(
|
|
20046
20053
|
(filter) => filter.filterType === "date_range" || filter.operator === "BETWEEN"
|
|
@@ -20108,7 +20115,8 @@ async function getPivotTable(report, dashboardFilters, dashboardName, getToken,
|
|
|
20108
20115
|
dashboardFilters,
|
|
20109
20116
|
tenants,
|
|
20110
20117
|
additionalProcessing,
|
|
20111
|
-
getToken
|
|
20118
|
+
getToken,
|
|
20119
|
+
overwriteCache
|
|
20112
20120
|
});
|
|
20113
20121
|
return pivotTable;
|
|
20114
20122
|
} catch (e) {
|
|
@@ -20356,7 +20364,8 @@ async function fetchReportRows({
|
|
|
20356
20364
|
filters = [],
|
|
20357
20365
|
getToken,
|
|
20358
20366
|
abortSignal,
|
|
20359
|
-
additionalProcessing
|
|
20367
|
+
additionalProcessing,
|
|
20368
|
+
overwriteCache = false
|
|
20360
20369
|
}) {
|
|
20361
20370
|
const fetchResp = await quillFetch({
|
|
20362
20371
|
client,
|
|
@@ -20368,7 +20377,8 @@ async function fetchReportRows({
|
|
|
20368
20377
|
filters: filters.map((filter) => ({ ...filter, options: void 0 })),
|
|
20369
20378
|
useNewNodeSql: true,
|
|
20370
20379
|
tenants,
|
|
20371
|
-
additionalProcessing
|
|
20380
|
+
additionalProcessing,
|
|
20381
|
+
overwriteCache
|
|
20372
20382
|
},
|
|
20373
20383
|
abortSignal,
|
|
20374
20384
|
getToken
|
|
@@ -20399,7 +20409,8 @@ async function fetchReport({
|
|
|
20399
20409
|
abortSignal,
|
|
20400
20410
|
getToken,
|
|
20401
20411
|
eventTracking,
|
|
20402
|
-
usePivotTask = false
|
|
20412
|
+
usePivotTask = false,
|
|
20413
|
+
overwriteCache = false
|
|
20403
20414
|
}) {
|
|
20404
20415
|
let reportInfo = void 0;
|
|
20405
20416
|
let errorMessage = void 0;
|
|
@@ -20419,7 +20430,8 @@ async function fetchReport({
|
|
|
20419
20430
|
rowsOnly,
|
|
20420
20431
|
rowCountOnly,
|
|
20421
20432
|
tenants,
|
|
20422
|
-
flags
|
|
20433
|
+
flags,
|
|
20434
|
+
overwriteCache
|
|
20423
20435
|
},
|
|
20424
20436
|
abortSignal,
|
|
20425
20437
|
getToken
|
|
@@ -20440,7 +20452,9 @@ async function fetchReport({
|
|
|
20440
20452
|
getToken,
|
|
20441
20453
|
eventTracking,
|
|
20442
20454
|
tenants,
|
|
20443
|
-
|
|
20455
|
+
// When not using pivot-template, avoid fallback pivot-template fetches.
|
|
20456
|
+
skipPivotFetch: !usePivotTask,
|
|
20457
|
+
overwriteCache
|
|
20444
20458
|
});
|
|
20445
20459
|
} catch (error) {
|
|
20446
20460
|
if (error instanceof Error && error.name === "AbortError") {
|
|
@@ -20490,7 +20504,8 @@ async function processReportResponse({
|
|
|
20490
20504
|
getToken,
|
|
20491
20505
|
eventTracking,
|
|
20492
20506
|
tenants,
|
|
20493
|
-
skipPivotFetch = false
|
|
20507
|
+
skipPivotFetch = false,
|
|
20508
|
+
overwriteCache
|
|
20494
20509
|
}) {
|
|
20495
20510
|
const shouldSkipPivotFetch = skipPivotFetch || !!resp?.pivotRows && !!resp?.fields;
|
|
20496
20511
|
const dashboardItem = {
|
|
@@ -20523,7 +20538,8 @@ async function processReportResponse({
|
|
|
20523
20538
|
getToken,
|
|
20524
20539
|
tenants,
|
|
20525
20540
|
eventTracking,
|
|
20526
|
-
skipPivotFetch: shouldSkipPivotFetch
|
|
20541
|
+
skipPivotFetch: shouldSkipPivotFetch,
|
|
20542
|
+
overwriteCache
|
|
20527
20543
|
});
|
|
20528
20544
|
if (additionalProcessing) {
|
|
20529
20545
|
reportInfo.pagination = additionalProcessing.page;
|
|
@@ -21600,6 +21616,1817 @@ async function getClientTenantIds({
|
|
|
21600
21616
|
|
|
21601
21617
|
// src/Context.tsx
|
|
21602
21618
|
init_columnProcessing();
|
|
21619
|
+
|
|
21620
|
+
// src/utils/cacheCab.ts
|
|
21621
|
+
init_dataFetcher();
|
|
21622
|
+
|
|
21623
|
+
// src/utils/inMemoryFilterEngine.ts
|
|
21624
|
+
init_Filter();
|
|
21625
|
+
init_dateRangePickerUtils();
|
|
21626
|
+
import {
|
|
21627
|
+
addHours,
|
|
21628
|
+
addMonths,
|
|
21629
|
+
addWeeks,
|
|
21630
|
+
addYears,
|
|
21631
|
+
addDays as addDays2,
|
|
21632
|
+
isValid as isValid4,
|
|
21633
|
+
startOfDay as startOfDay3,
|
|
21634
|
+
startOfHour,
|
|
21635
|
+
startOfMonth as startOfMonth2,
|
|
21636
|
+
startOfQuarter as startOfQuarter2,
|
|
21637
|
+
startOfWeek as startOfWeek3,
|
|
21638
|
+
startOfYear,
|
|
21639
|
+
subDays as subDays2,
|
|
21640
|
+
subHours as subHours2,
|
|
21641
|
+
subMonths as subMonths3,
|
|
21642
|
+
subWeeks as subWeeks2,
|
|
21643
|
+
subYears as subYears2
|
|
21644
|
+
} from "date-fns";
|
|
21645
|
+
var UNSET = Symbol("unset");
|
|
21646
|
+
var isFilter = (f) => {
|
|
21647
|
+
return f && typeof f === "object" && "filterType" in f && !("id" in f);
|
|
21648
|
+
};
|
|
21649
|
+
var isDashboardFilterUpdate = (f) => {
|
|
21650
|
+
return f && typeof f === "object" && "label" in f;
|
|
21651
|
+
};
|
|
21652
|
+
var normalizeFilterString = (value) => value.replaceAll("%", "").toLowerCase();
|
|
21653
|
+
var normalizeRowString = (value) => value.toLowerCase();
|
|
21654
|
+
var resolveFieldKeys = (field, table, resolver) => {
|
|
21655
|
+
if (!field) return [];
|
|
21656
|
+
const resolved = resolver?.(field, table);
|
|
21657
|
+
if (Array.isArray(resolved)) return resolved;
|
|
21658
|
+
if (typeof resolved === "string") return [resolved];
|
|
21659
|
+
return [field];
|
|
21660
|
+
};
|
|
21661
|
+
var getRowValue = (row, fieldKeys, cache) => {
|
|
21662
|
+
if (fieldKeys.length === 0) return void 0;
|
|
21663
|
+
const cacheKey = fieldKeys.join("|");
|
|
21664
|
+
if (Object.prototype.hasOwnProperty.call(cache, cacheKey)) {
|
|
21665
|
+
return cache[cacheKey];
|
|
21666
|
+
}
|
|
21667
|
+
for (const key of fieldKeys) {
|
|
21668
|
+
if (Object.prototype.hasOwnProperty.call(row, key)) {
|
|
21669
|
+
cache[cacheKey] = row[key];
|
|
21670
|
+
return row[key];
|
|
21671
|
+
}
|
|
21672
|
+
}
|
|
21673
|
+
cache[cacheKey] = void 0;
|
|
21674
|
+
return void 0;
|
|
21675
|
+
};
|
|
21676
|
+
var coerceNumber = (value) => {
|
|
21677
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
21678
|
+
if (typeof value === "string" && value !== "") {
|
|
21679
|
+
const parsed = Number(value);
|
|
21680
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
21681
|
+
}
|
|
21682
|
+
return null;
|
|
21683
|
+
};
|
|
21684
|
+
var coerceBoolean = (value) => {
|
|
21685
|
+
if (typeof value === "boolean") return value;
|
|
21686
|
+
if (typeof value === "number") return value !== 0;
|
|
21687
|
+
if (typeof value === "string") {
|
|
21688
|
+
const normalized = value.toLowerCase();
|
|
21689
|
+
if (normalized === "true" || normalized === "1") return true;
|
|
21690
|
+
if (normalized === "false" || normalized === "0") return false;
|
|
21691
|
+
}
|
|
21692
|
+
return null;
|
|
21693
|
+
};
|
|
21694
|
+
var toDateMs = (value) => {
|
|
21695
|
+
if (value instanceof Date) {
|
|
21696
|
+
return isValid4(value) ? value.getTime() : null;
|
|
21697
|
+
}
|
|
21698
|
+
if (typeof value === "number") {
|
|
21699
|
+
const date = new Date(value);
|
|
21700
|
+
return isValid4(date) ? date.getTime() : null;
|
|
21701
|
+
}
|
|
21702
|
+
if (typeof value === "string") {
|
|
21703
|
+
const date = new Date(value);
|
|
21704
|
+
return isValid4(date) ? date.getTime() : null;
|
|
21705
|
+
}
|
|
21706
|
+
return null;
|
|
21707
|
+
};
|
|
21708
|
+
var buildColumnTypeMap = (columns) => {
|
|
21709
|
+
if (!columns?.length) return null;
|
|
21710
|
+
const map = /* @__PURE__ */ Object.create(null);
|
|
21711
|
+
for (const column of columns) {
|
|
21712
|
+
map[column.field] = column.jsType;
|
|
21713
|
+
}
|
|
21714
|
+
return map;
|
|
21715
|
+
};
|
|
21716
|
+
var resolveDashboardField = (filter, options) => {
|
|
21717
|
+
const mapped = options.filterMap?.[filter.label];
|
|
21718
|
+
if (mapped?.field) {
|
|
21719
|
+
return { field: mapped.field, table: mapped.table };
|
|
21720
|
+
}
|
|
21721
|
+
if (filter.filterType === "date_range" /* Date */ && options.dateField?.field) {
|
|
21722
|
+
return { field: options.dateField.field, table: options.dateField.table };
|
|
21723
|
+
}
|
|
21724
|
+
if (filter.field) {
|
|
21725
|
+
return { field: filter.field, table: filter.table };
|
|
21726
|
+
}
|
|
21727
|
+
return null;
|
|
21728
|
+
};
|
|
21729
|
+
var buildRelativeDateRange = (operator, value, now2, weekStartsOn) => {
|
|
21730
|
+
const amount = value.value || 1;
|
|
21731
|
+
const unit = value.unit;
|
|
21732
|
+
const currentStart = (() => {
|
|
21733
|
+
switch (unit) {
|
|
21734
|
+
case TimeUnit.Hour:
|
|
21735
|
+
return startOfHour(now2);
|
|
21736
|
+
case TimeUnit.Day:
|
|
21737
|
+
return startOfDay3(now2);
|
|
21738
|
+
case TimeUnit.Week:
|
|
21739
|
+
return startOfWeek3(now2, { weekStartsOn });
|
|
21740
|
+
case TimeUnit.Month:
|
|
21741
|
+
return startOfMonth2(now2);
|
|
21742
|
+
case TimeUnit.Quarter:
|
|
21743
|
+
return startOfQuarter2(now2);
|
|
21744
|
+
case TimeUnit.Year:
|
|
21745
|
+
return startOfYear(now2);
|
|
21746
|
+
default:
|
|
21747
|
+
return startOfDay3(now2);
|
|
21748
|
+
}
|
|
21749
|
+
})();
|
|
21750
|
+
const addUnit = (base, multiplier) => {
|
|
21751
|
+
switch (unit) {
|
|
21752
|
+
case TimeUnit.Hour:
|
|
21753
|
+
return addHours(base, multiplier);
|
|
21754
|
+
case TimeUnit.Day:
|
|
21755
|
+
return addDays2(base, multiplier);
|
|
21756
|
+
case TimeUnit.Week:
|
|
21757
|
+
return addWeeks(base, multiplier);
|
|
21758
|
+
case TimeUnit.Month:
|
|
21759
|
+
return addMonths(base, multiplier);
|
|
21760
|
+
case TimeUnit.Quarter:
|
|
21761
|
+
return addMonths(base, multiplier * 3);
|
|
21762
|
+
case TimeUnit.Year:
|
|
21763
|
+
return addYears(base, multiplier);
|
|
21764
|
+
default:
|
|
21765
|
+
return addDays2(base, multiplier);
|
|
21766
|
+
}
|
|
21767
|
+
};
|
|
21768
|
+
const subUnit = (base, multiplier) => {
|
|
21769
|
+
switch (unit) {
|
|
21770
|
+
case TimeUnit.Hour:
|
|
21771
|
+
return subHours2(base, multiplier);
|
|
21772
|
+
case TimeUnit.Day:
|
|
21773
|
+
return subDays2(base, multiplier);
|
|
21774
|
+
case TimeUnit.Week:
|
|
21775
|
+
return subWeeks2(base, multiplier);
|
|
21776
|
+
case TimeUnit.Month:
|
|
21777
|
+
return subMonths3(base, multiplier);
|
|
21778
|
+
case TimeUnit.Quarter:
|
|
21779
|
+
return subMonths3(base, multiplier * 3);
|
|
21780
|
+
case TimeUnit.Year:
|
|
21781
|
+
return subYears2(base, multiplier);
|
|
21782
|
+
default:
|
|
21783
|
+
return subDays2(base, multiplier);
|
|
21784
|
+
}
|
|
21785
|
+
};
|
|
21786
|
+
switch (operator) {
|
|
21787
|
+
case DateOperator.InTheLast: {
|
|
21788
|
+
const start2 = subUnit(now2, amount);
|
|
21789
|
+
return { start: start2.getTime() };
|
|
21790
|
+
}
|
|
21791
|
+
case DateOperator.InThePrevious: {
|
|
21792
|
+
const start2 = subUnit(currentStart, amount);
|
|
21793
|
+
return { start: start2.getTime(), end: currentStart.getTime(), endExclusive: true };
|
|
21794
|
+
}
|
|
21795
|
+
case DateOperator.InTheCurrent: {
|
|
21796
|
+
const end = addUnit(currentStart, 1);
|
|
21797
|
+
return {
|
|
21798
|
+
start: currentStart.getTime(),
|
|
21799
|
+
end: end.getTime(),
|
|
21800
|
+
endExclusive: true
|
|
21801
|
+
};
|
|
21802
|
+
}
|
|
21803
|
+
default:
|
|
21804
|
+
return null;
|
|
21805
|
+
}
|
|
21806
|
+
};
|
|
21807
|
+
var buildStringPredicate = (operator, value, fieldKeys) => {
|
|
21808
|
+
if (value === void 0 || value === null) return null;
|
|
21809
|
+
const normalizedValue = Array.isArray(value) ? value.map((v) => normalizeFilterString(String(v))) : normalizeFilterString(String(value));
|
|
21810
|
+
if (Array.isArray(normalizedValue)) {
|
|
21811
|
+
if (normalizedValue.length === 0) return null;
|
|
21812
|
+
} else if (normalizedValue === "") {
|
|
21813
|
+
return null;
|
|
21814
|
+
}
|
|
21815
|
+
if (operator === StringOperator.Is || operator === StringOperator.IsNot) {
|
|
21816
|
+
const values = Array.isArray(normalizedValue) ? normalizedValue : [normalizedValue];
|
|
21817
|
+
const valueSet = new Set(values);
|
|
21818
|
+
return (row, cache) => {
|
|
21819
|
+
const rowValue = getRowValue(row, fieldKeys, cache);
|
|
21820
|
+
if (rowValue === null || rowValue === void 0) return false;
|
|
21821
|
+
const normalized = normalizeRowString(String(rowValue));
|
|
21822
|
+
const hasValue = valueSet.has(normalized);
|
|
21823
|
+
return operator === StringOperator.Is ? hasValue : !hasValue;
|
|
21824
|
+
};
|
|
21825
|
+
}
|
|
21826
|
+
if (Array.isArray(normalizedValue)) {
|
|
21827
|
+
return null;
|
|
21828
|
+
}
|
|
21829
|
+
return (row, cache) => {
|
|
21830
|
+
const rowValue = getRowValue(row, fieldKeys, cache);
|
|
21831
|
+
if (rowValue === null || rowValue === void 0) return false;
|
|
21832
|
+
const normalizedRow = normalizeRowString(String(rowValue));
|
|
21833
|
+
switch (operator) {
|
|
21834
|
+
case StringOperator.IsExactly:
|
|
21835
|
+
return normalizedRow === normalizedValue;
|
|
21836
|
+
case StringOperator.IsNotExactly:
|
|
21837
|
+
return normalizedRow !== normalizedValue;
|
|
21838
|
+
case StringOperator.Contains:
|
|
21839
|
+
return normalizedRow.includes(normalizedValue);
|
|
21840
|
+
default:
|
|
21841
|
+
return false;
|
|
21842
|
+
}
|
|
21843
|
+
};
|
|
21844
|
+
};
|
|
21845
|
+
var buildNumericPredicate = (operator, value, fieldKeys) => {
|
|
21846
|
+
const filterValue = coerceNumber(value);
|
|
21847
|
+
if (filterValue === null) return null;
|
|
21848
|
+
return (row, cache) => {
|
|
21849
|
+
const rowValue = getRowValue(row, fieldKeys, cache);
|
|
21850
|
+
const parsed = coerceNumber(rowValue);
|
|
21851
|
+
if (parsed === null) return false;
|
|
21852
|
+
switch (operator) {
|
|
21853
|
+
case NumberOperator.EqualTo:
|
|
21854
|
+
return parsed === filterValue;
|
|
21855
|
+
case NumberOperator.NotEqualTo:
|
|
21856
|
+
return parsed !== filterValue;
|
|
21857
|
+
case NumberOperator.GreaterThan:
|
|
21858
|
+
return parsed > filterValue;
|
|
21859
|
+
case NumberOperator.LessThan:
|
|
21860
|
+
return parsed < filterValue;
|
|
21861
|
+
case NumberOperator.GreaterThanOrEqualTo:
|
|
21862
|
+
return parsed >= filterValue;
|
|
21863
|
+
case NumberOperator.LessThanOrEqualTo:
|
|
21864
|
+
return parsed <= filterValue;
|
|
21865
|
+
default:
|
|
21866
|
+
return false;
|
|
21867
|
+
}
|
|
21868
|
+
};
|
|
21869
|
+
};
|
|
21870
|
+
var buildNullPredicate = (operator, fieldKeys) => {
|
|
21871
|
+
return (row, cache) => {
|
|
21872
|
+
const rowValue = getRowValue(row, fieldKeys, cache);
|
|
21873
|
+
const isNullish = rowValue === null || rowValue === void 0;
|
|
21874
|
+
return operator === NullOperator.IsNull ? isNullish : !isNullish;
|
|
21875
|
+
};
|
|
21876
|
+
};
|
|
21877
|
+
var buildBooleanPredicate = (operator, value, fieldKeys) => {
|
|
21878
|
+
const filterValue = coerceBoolean(value);
|
|
21879
|
+
if (filterValue === null) return null;
|
|
21880
|
+
return (row, cache) => {
|
|
21881
|
+
const rowValue = getRowValue(row, fieldKeys, cache);
|
|
21882
|
+
const parsed = coerceBoolean(rowValue);
|
|
21883
|
+
if (parsed === null) return false;
|
|
21884
|
+
return operator === BoolOperator.EqualTo ? parsed === filterValue : parsed !== filterValue;
|
|
21885
|
+
};
|
|
21886
|
+
};
|
|
21887
|
+
var buildDateComparisonPredicate = (operator, value, fieldKeys) => {
|
|
21888
|
+
const filterDate = toDateMs(value);
|
|
21889
|
+
if (filterDate === null) return null;
|
|
21890
|
+
return (row, cache) => {
|
|
21891
|
+
const rowValue = getRowValue(row, fieldKeys, cache);
|
|
21892
|
+
const rowDate = toDateMs(rowValue);
|
|
21893
|
+
if (rowDate === null) return false;
|
|
21894
|
+
switch (operator) {
|
|
21895
|
+
case DateOperator.EqualTo:
|
|
21896
|
+
return rowDate === filterDate;
|
|
21897
|
+
case DateOperator.NotEqualTo:
|
|
21898
|
+
return rowDate !== filterDate;
|
|
21899
|
+
case DateOperator.GreaterThan:
|
|
21900
|
+
return rowDate > filterDate;
|
|
21901
|
+
case DateOperator.LessThan:
|
|
21902
|
+
return rowDate < filterDate;
|
|
21903
|
+
case DateOperator.GreaterThanOrEqualTo:
|
|
21904
|
+
return rowDate >= filterDate;
|
|
21905
|
+
case DateOperator.LessThanOrEqualTo:
|
|
21906
|
+
return rowDate <= filterDate;
|
|
21907
|
+
default:
|
|
21908
|
+
return false;
|
|
21909
|
+
}
|
|
21910
|
+
};
|
|
21911
|
+
};
|
|
21912
|
+
var buildDateRangePredicate = (range, fieldKeys) => {
|
|
21913
|
+
if (range.start === void 0 && range.end === void 0) return null;
|
|
21914
|
+
return (row, cache) => {
|
|
21915
|
+
const rowValue = getRowValue(row, fieldKeys, cache);
|
|
21916
|
+
const rowDate = toDateMs(rowValue);
|
|
21917
|
+
if (rowDate === null) return false;
|
|
21918
|
+
if (range.start !== void 0 && rowDate < range.start) return false;
|
|
21919
|
+
if (range.end !== void 0) {
|
|
21920
|
+
if (range.endExclusive) {
|
|
21921
|
+
return rowDate < range.end;
|
|
21922
|
+
}
|
|
21923
|
+
return rowDate <= range.end;
|
|
21924
|
+
}
|
|
21925
|
+
return true;
|
|
21926
|
+
};
|
|
21927
|
+
};
|
|
21928
|
+
var buildCustomDatePredicate = (value, fieldKeys) => {
|
|
21929
|
+
const start2 = value.startDate ? toDateMs(value.startDate) : null;
|
|
21930
|
+
const end = value.endDate ? toDateMs(value.endDate) : null;
|
|
21931
|
+
if (start2 === null && end === null) return null;
|
|
21932
|
+
return buildDateRangePredicate(
|
|
21933
|
+
{
|
|
21934
|
+
start: start2 ?? void 0,
|
|
21935
|
+
end: end ?? void 0,
|
|
21936
|
+
endExclusive: false
|
|
21937
|
+
},
|
|
21938
|
+
fieldKeys
|
|
21939
|
+
);
|
|
21940
|
+
};
|
|
21941
|
+
var compileCustomFilter = (filter, options) => {
|
|
21942
|
+
const fieldKeys = resolveFieldKeys(
|
|
21943
|
+
filter.field,
|
|
21944
|
+
filter.table,
|
|
21945
|
+
options.fieldKeyResolver
|
|
21946
|
+
);
|
|
21947
|
+
if (fieldKeys.length === 0) return null;
|
|
21948
|
+
switch (filter.filterType) {
|
|
21949
|
+
case "string-filter" /* StringFilter */:
|
|
21950
|
+
case "string-in-filter" /* StringInFilter */:
|
|
21951
|
+
return buildStringPredicate(
|
|
21952
|
+
filter.operator,
|
|
21953
|
+
filter.value,
|
|
21954
|
+
fieldKeys
|
|
21955
|
+
);
|
|
21956
|
+
case "numeric-filter" /* NumericFilter */:
|
|
21957
|
+
return buildNumericPredicate(
|
|
21958
|
+
filter.operator,
|
|
21959
|
+
filter.value,
|
|
21960
|
+
fieldKeys
|
|
21961
|
+
);
|
|
21962
|
+
case "null-filter" /* NullFilter */:
|
|
21963
|
+
return buildNullPredicate(
|
|
21964
|
+
filter.operator,
|
|
21965
|
+
fieldKeys
|
|
21966
|
+
);
|
|
21967
|
+
case "boolean-filter" /* BooleanFilter */:
|
|
21968
|
+
return buildBooleanPredicate(
|
|
21969
|
+
filter.operator,
|
|
21970
|
+
filter.value,
|
|
21971
|
+
fieldKeys
|
|
21972
|
+
);
|
|
21973
|
+
case "date-custom-filter" /* DateCustomFilter */:
|
|
21974
|
+
return buildCustomDatePredicate(
|
|
21975
|
+
filter.value,
|
|
21976
|
+
fieldKeys
|
|
21977
|
+
);
|
|
21978
|
+
case "date-comparison-filter" /* DateComparisonFilter */:
|
|
21979
|
+
return buildDateComparisonPredicate(
|
|
21980
|
+
filter.operator,
|
|
21981
|
+
filter.value,
|
|
21982
|
+
fieldKeys
|
|
21983
|
+
);
|
|
21984
|
+
case "date-filter" /* DateFilter */: {
|
|
21985
|
+
const value = filter.value;
|
|
21986
|
+
if (!value?.unit) return null;
|
|
21987
|
+
const now2 = options.now ?? /* @__PURE__ */ new Date();
|
|
21988
|
+
const range = buildRelativeDateRange(
|
|
21989
|
+
filter.operator,
|
|
21990
|
+
value,
|
|
21991
|
+
now2,
|
|
21992
|
+
options.weekStartsOn ?? 0
|
|
21993
|
+
);
|
|
21994
|
+
if (!range) return null;
|
|
21995
|
+
return buildDateRangePredicate(range, fieldKeys);
|
|
21996
|
+
}
|
|
21997
|
+
default:
|
|
21998
|
+
return null;
|
|
21999
|
+
}
|
|
22000
|
+
};
|
|
22001
|
+
var compileDashboardFilter = (filter, options, columnTypeMap) => {
|
|
22002
|
+
const resolved = resolveDashboardField(filter, options);
|
|
22003
|
+
if (!resolved?.field) return null;
|
|
22004
|
+
const fieldKeys = resolveFieldKeys(
|
|
22005
|
+
resolved.field,
|
|
22006
|
+
resolved.table,
|
|
22007
|
+
options.fieldKeyResolver
|
|
22008
|
+
);
|
|
22009
|
+
if (fieldKeys.length === 0) return null;
|
|
22010
|
+
switch (filter.filterType) {
|
|
22011
|
+
case "string" /* String */: {
|
|
22012
|
+
const stringFilter = filter;
|
|
22013
|
+
if (stringFilter.stringFilterType === "multiselect" /* Multiselect */) {
|
|
22014
|
+
if (!stringFilter.values || stringFilter.values.length === 0) {
|
|
22015
|
+
return null;
|
|
22016
|
+
}
|
|
22017
|
+
return buildStringPredicate(
|
|
22018
|
+
StringOperator.Is,
|
|
22019
|
+
stringFilter.values,
|
|
22020
|
+
fieldKeys
|
|
22021
|
+
);
|
|
22022
|
+
}
|
|
22023
|
+
if (!stringFilter.selectedValue) return null;
|
|
22024
|
+
return buildStringPredicate(
|
|
22025
|
+
StringOperator.IsExactly,
|
|
22026
|
+
stringFilter.selectedValue,
|
|
22027
|
+
fieldKeys
|
|
22028
|
+
);
|
|
22029
|
+
}
|
|
22030
|
+
case "date_range" /* Date */: {
|
|
22031
|
+
const dateFilter = filter;
|
|
22032
|
+
const start2 = dateFilter.startDate ? dateFilter.startDate.getTime() : void 0;
|
|
22033
|
+
const end = dateFilter.endDate ? dateFilter.endDate.getTime() : void 0;
|
|
22034
|
+
return buildDateRangePredicate(
|
|
22035
|
+
{ start: start2, end, endExclusive: false },
|
|
22036
|
+
fieldKeys
|
|
22037
|
+
);
|
|
22038
|
+
}
|
|
22039
|
+
case "tenant" /* Tenant */: {
|
|
22040
|
+
const tenantFilter = filter;
|
|
22041
|
+
if (!tenantFilter.values || tenantFilter.values.length === 0) {
|
|
22042
|
+
return null;
|
|
22043
|
+
}
|
|
22044
|
+
const normalizedValues = tenantFilter.values.map(
|
|
22045
|
+
(v) => normalizeFilterString(String(v))
|
|
22046
|
+
);
|
|
22047
|
+
const valueSet = new Set(normalizedValues);
|
|
22048
|
+
const fieldType = columnTypeMap?.[resolved.field] ?? "string";
|
|
22049
|
+
return (row, cache) => {
|
|
22050
|
+
const rowValue = getRowValue(row, fieldKeys, cache);
|
|
22051
|
+
if (rowValue === null || rowValue === void 0) return false;
|
|
22052
|
+
if (fieldType === "number") {
|
|
22053
|
+
const numeric = coerceNumber(rowValue);
|
|
22054
|
+
return numeric !== null && valueSet.has(normalizeFilterString(String(numeric)));
|
|
22055
|
+
}
|
|
22056
|
+
return valueSet.has(normalizeRowString(String(rowValue)));
|
|
22057
|
+
};
|
|
22058
|
+
}
|
|
22059
|
+
default:
|
|
22060
|
+
return null;
|
|
22061
|
+
}
|
|
22062
|
+
};
|
|
22063
|
+
var updateDashboardFilters = (filtersToUpdate, dashboardFilters) => {
|
|
22064
|
+
return dashboardFilters.map((filter) => {
|
|
22065
|
+
const update = filtersToUpdate.find((u) => u.label === filter.label);
|
|
22066
|
+
if (!update) return filter;
|
|
22067
|
+
if (filter.filterType === "string" /* String */) {
|
|
22068
|
+
if (filter.stringFilterType === "multiselect" /* Multiselect */) {
|
|
22069
|
+
return {
|
|
22070
|
+
...filter,
|
|
22071
|
+
values: update.value
|
|
22072
|
+
};
|
|
22073
|
+
}
|
|
22074
|
+
return {
|
|
22075
|
+
...filter,
|
|
22076
|
+
selectedValue: update.value
|
|
22077
|
+
};
|
|
22078
|
+
}
|
|
22079
|
+
if (filter.filterType === "date_range" /* Date */) {
|
|
22080
|
+
const presetOptions = convertPresetOptionsToSelectableList(
|
|
22081
|
+
filter.presetOptions ?? [],
|
|
22082
|
+
filter.defaultPresetRanges ?? []
|
|
22083
|
+
);
|
|
22084
|
+
const value = update.value;
|
|
22085
|
+
const preset = presetOptions.find((p) => {
|
|
22086
|
+
const pStart = p.startDate ? new Date(p.startDate).toISOString() : void 0;
|
|
22087
|
+
const vStart = value.startDate ? new Date(value.startDate).toISOString() : void 0;
|
|
22088
|
+
const pEnd = p.endDate ? new Date(p.endDate).toISOString() : void 0;
|
|
22089
|
+
const vEnd = value.endDate ? new Date(value.endDate).toISOString() : void 0;
|
|
22090
|
+
return pStart === vStart && pEnd === vEnd;
|
|
22091
|
+
});
|
|
22092
|
+
if (!preset) {
|
|
22093
|
+
return { ...filter, startDate: value.startDate, endDate: value.endDate };
|
|
22094
|
+
}
|
|
22095
|
+
return {
|
|
22096
|
+
...filter,
|
|
22097
|
+
preset,
|
|
22098
|
+
startDate: value.startDate,
|
|
22099
|
+
endDate: value.endDate
|
|
22100
|
+
};
|
|
22101
|
+
}
|
|
22102
|
+
if (filter.filterType === "tenant" /* Tenant */) {
|
|
22103
|
+
const value = update.value;
|
|
22104
|
+
let values;
|
|
22105
|
+
if (Array.isArray(value)) {
|
|
22106
|
+
values = value;
|
|
22107
|
+
} else if (typeof value === "string") {
|
|
22108
|
+
values = [value];
|
|
22109
|
+
} else {
|
|
22110
|
+
values = [];
|
|
22111
|
+
}
|
|
22112
|
+
return {
|
|
22113
|
+
...filter,
|
|
22114
|
+
values
|
|
22115
|
+
};
|
|
22116
|
+
}
|
|
22117
|
+
return filter;
|
|
22118
|
+
});
|
|
22119
|
+
};
|
|
22120
|
+
var compileApplyFiltersPredicate = (filters, options) => {
|
|
22121
|
+
const dashboardUpdates = filters.filter(isDashboardFilterUpdate);
|
|
22122
|
+
const customFilters = filters.filter(isFilter);
|
|
22123
|
+
const internalCustomFilters = customFilters.map((filter) => {
|
|
22124
|
+
try {
|
|
22125
|
+
return convertCustomFilter(filter);
|
|
22126
|
+
} catch (error) {
|
|
22127
|
+
return null;
|
|
22128
|
+
}
|
|
22129
|
+
}).concat(options.customFilters ?? []).filter((filter) => filter !== null && filter !== void 0);
|
|
22130
|
+
const dashboardFilters = options.dashboardFilters ?? [];
|
|
22131
|
+
const updatedDashboardFilters = dashboardUpdates.length ? updateDashboardFilters(dashboardUpdates, dashboardFilters) : dashboardFilters;
|
|
22132
|
+
const columnTypeMap = buildColumnTypeMap(options.columns);
|
|
22133
|
+
const predicates = [];
|
|
22134
|
+
for (const filter of internalCustomFilters) {
|
|
22135
|
+
const predicate = compileCustomFilter(filter, options);
|
|
22136
|
+
if (predicate) predicates.push(predicate);
|
|
22137
|
+
}
|
|
22138
|
+
for (const filter of updatedDashboardFilters) {
|
|
22139
|
+
const predicate = compileDashboardFilter(
|
|
22140
|
+
filter,
|
|
22141
|
+
options,
|
|
22142
|
+
columnTypeMap
|
|
22143
|
+
);
|
|
22144
|
+
if (predicate) predicates.push(predicate);
|
|
22145
|
+
}
|
|
22146
|
+
if (predicates.length === 0) {
|
|
22147
|
+
return { predicate: () => true, hasPredicates: false };
|
|
22148
|
+
}
|
|
22149
|
+
return {
|
|
22150
|
+
predicate: (row) => {
|
|
22151
|
+
const cache = /* @__PURE__ */ Object.create(null);
|
|
22152
|
+
for (const predicate of predicates) {
|
|
22153
|
+
if (!predicate(row, cache)) return false;
|
|
22154
|
+
}
|
|
22155
|
+
return true;
|
|
22156
|
+
},
|
|
22157
|
+
hasPredicates: true
|
|
22158
|
+
};
|
|
22159
|
+
};
|
|
22160
|
+
var applyFiltersInMemory = (rows, filters, options) => {
|
|
22161
|
+
if (!rows.length) return rows;
|
|
22162
|
+
const { predicate, hasPredicates } = compileApplyFiltersPredicate(
|
|
22163
|
+
filters,
|
|
22164
|
+
options
|
|
22165
|
+
);
|
|
22166
|
+
if (!hasPredicates) return rows;
|
|
22167
|
+
const results = [];
|
|
22168
|
+
for (let i = 0; i < rows.length; i += 1) {
|
|
22169
|
+
const row = rows[i];
|
|
22170
|
+
if (predicate(row)) {
|
|
22171
|
+
results.push(row);
|
|
22172
|
+
}
|
|
22173
|
+
}
|
|
22174
|
+
return results;
|
|
22175
|
+
};
|
|
22176
|
+
|
|
22177
|
+
// src/utils/inMemoryPivotEngine.ts
|
|
22178
|
+
init_columnType();
|
|
22179
|
+
var MS_IN_DAY = 24 * 60 * 60 * 1e3;
|
|
22180
|
+
var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
22181
|
+
var INVALID_DATE_KEY = "-2026";
|
|
22182
|
+
function singleAggToMultiAgg(pivot) {
|
|
22183
|
+
if (pivot.aggregations) {
|
|
22184
|
+
return pivot;
|
|
22185
|
+
}
|
|
22186
|
+
const newPivot = { ...pivot };
|
|
22187
|
+
const newAgg = { aggregationType: pivot.aggregationType };
|
|
22188
|
+
const fieldsToCopy = ["valueField", "valueFieldType", "valueField2", "valueField2Type"];
|
|
22189
|
+
fieldsToCopy.forEach((x) => {
|
|
22190
|
+
if (pivot[x]) {
|
|
22191
|
+
newAgg[x] = pivot[x];
|
|
22192
|
+
delete newPivot[x];
|
|
22193
|
+
}
|
|
22194
|
+
});
|
|
22195
|
+
newPivot.aggregations = [newAgg];
|
|
22196
|
+
return newPivot;
|
|
22197
|
+
}
|
|
22198
|
+
function isDateFormat2(xAxisFormat) {
|
|
22199
|
+
const DATE_FORMATS = [
|
|
22200
|
+
"yyyy",
|
|
22201
|
+
"mmm_dd",
|
|
22202
|
+
"mmm_yyyy",
|
|
22203
|
+
"mmm_dd_yyyy",
|
|
22204
|
+
"hh_ap_pm",
|
|
22205
|
+
"mmm_dd-mmm_dd",
|
|
22206
|
+
"mmm_dd_hh:mm_ap_pm",
|
|
22207
|
+
"wo, yyyy"
|
|
22208
|
+
];
|
|
22209
|
+
const isDate = DATE_FORMATS.includes(xAxisFormat.toLowerCase());
|
|
22210
|
+
return isDate;
|
|
22211
|
+
}
|
|
22212
|
+
function isValidDate3(date) {
|
|
22213
|
+
try {
|
|
22214
|
+
return date instanceof Date && !isNaN(date.getTime());
|
|
22215
|
+
} catch {
|
|
22216
|
+
return false;
|
|
22217
|
+
}
|
|
22218
|
+
}
|
|
22219
|
+
function inferDateBucketFromFilters(pivot, filters) {
|
|
22220
|
+
if (!pivot?.rowFieldType) {
|
|
22221
|
+
return void 0;
|
|
22222
|
+
}
|
|
22223
|
+
const normalizedType = String(pivot.rowFieldType).toLowerCase();
|
|
22224
|
+
if (isDateFormat2(normalizedType)) {
|
|
22225
|
+
switch (normalizedType) {
|
|
22226
|
+
case "mmm_dd-mmm_dd":
|
|
22227
|
+
return "week";
|
|
22228
|
+
case "yyyy":
|
|
22229
|
+
case "wo, yyyy":
|
|
22230
|
+
return "year";
|
|
22231
|
+
case "mmm_dd_hh:mm_ap_pm":
|
|
22232
|
+
case "hh_ap_pm":
|
|
22233
|
+
return "day";
|
|
22234
|
+
default:
|
|
22235
|
+
return "month";
|
|
22236
|
+
}
|
|
22237
|
+
}
|
|
22238
|
+
const isDateLike = isDateType(normalizedType);
|
|
22239
|
+
if (!isDateLike) {
|
|
22240
|
+
return void 0;
|
|
22241
|
+
}
|
|
22242
|
+
let earliest;
|
|
22243
|
+
let latest;
|
|
22244
|
+
const extractTimestamp = (value) => {
|
|
22245
|
+
if (!value) {
|
|
22246
|
+
return void 0;
|
|
22247
|
+
}
|
|
22248
|
+
if (value instanceof Date) {
|
|
22249
|
+
return value.getTime();
|
|
22250
|
+
}
|
|
22251
|
+
const parsed = Date.parse(value);
|
|
22252
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
22253
|
+
};
|
|
22254
|
+
(Array.isArray(filters) ? filters : []).forEach((filter) => {
|
|
22255
|
+
if (!filter || filter.filterType !== "date_range") {
|
|
22256
|
+
return;
|
|
22257
|
+
}
|
|
22258
|
+
if (filter.primaryRange?.value === "ALL_TIME") {
|
|
22259
|
+
earliest = -1;
|
|
22260
|
+
return;
|
|
22261
|
+
}
|
|
22262
|
+
const possibleStarts = [
|
|
22263
|
+
filter.startDate,
|
|
22264
|
+
filter.start,
|
|
22265
|
+
filter.primaryRange?.startDate,
|
|
22266
|
+
filter.primaryRange?.start,
|
|
22267
|
+
filter.range?.startDate,
|
|
22268
|
+
filter.range?.start
|
|
22269
|
+
];
|
|
22270
|
+
const possibleEnds = [
|
|
22271
|
+
filter.endDate,
|
|
22272
|
+
filter.end,
|
|
22273
|
+
filter.primaryRange?.endDate,
|
|
22274
|
+
filter.primaryRange?.end,
|
|
22275
|
+
filter.range?.endDate,
|
|
22276
|
+
filter.range?.end
|
|
22277
|
+
];
|
|
22278
|
+
possibleStarts.forEach((value) => {
|
|
22279
|
+
const timestamp = extractTimestamp(value);
|
|
22280
|
+
if (timestamp === void 0) {
|
|
22281
|
+
return;
|
|
22282
|
+
}
|
|
22283
|
+
earliest = earliest === void 0 ? timestamp : Math.min(earliest, timestamp);
|
|
22284
|
+
});
|
|
22285
|
+
possibleEnds.forEach((value) => {
|
|
22286
|
+
const timestamp = extractTimestamp(value);
|
|
22287
|
+
if (timestamp === void 0) {
|
|
22288
|
+
return;
|
|
22289
|
+
}
|
|
22290
|
+
latest = latest === void 0 ? timestamp : Math.max(latest, timestamp);
|
|
22291
|
+
});
|
|
22292
|
+
});
|
|
22293
|
+
if (earliest === -1) {
|
|
22294
|
+
return "month";
|
|
22295
|
+
}
|
|
22296
|
+
if (earliest === void 0 || latest === void 0) {
|
|
22297
|
+
return void 0;
|
|
22298
|
+
}
|
|
22299
|
+
if (latest < earliest) {
|
|
22300
|
+
[earliest, latest] = [latest, earliest];
|
|
22301
|
+
}
|
|
22302
|
+
const diffInDays = Math.max(1, Math.round((latest - earliest) / MS_IN_DAY));
|
|
22303
|
+
if (diffInDays < 20) {
|
|
22304
|
+
return "day";
|
|
22305
|
+
}
|
|
22306
|
+
if (diffInDays <= 59) {
|
|
22307
|
+
return "week";
|
|
22308
|
+
}
|
|
22309
|
+
if (diffInDays <= 400) {
|
|
22310
|
+
return "month";
|
|
22311
|
+
}
|
|
22312
|
+
return "year";
|
|
22313
|
+
}
|
|
22314
|
+
function getDateRangeFromFilters(filters) {
|
|
22315
|
+
let earliest;
|
|
22316
|
+
let latest;
|
|
22317
|
+
const extractTimestamp = (value) => {
|
|
22318
|
+
if (!value) return void 0;
|
|
22319
|
+
if (value instanceof Date) return value.getTime();
|
|
22320
|
+
const parsed = Date.parse(value);
|
|
22321
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
22322
|
+
};
|
|
22323
|
+
(Array.isArray(filters) ? filters : []).forEach((filter) => {
|
|
22324
|
+
if (!filter || filter.filterType !== "date_range") return;
|
|
22325
|
+
if (filter.primaryRange?.value === "ALL_TIME") return;
|
|
22326
|
+
const possibleStarts = [
|
|
22327
|
+
filter.startDate,
|
|
22328
|
+
filter.start,
|
|
22329
|
+
filter.primaryRange?.startDate,
|
|
22330
|
+
filter.primaryRange?.start,
|
|
22331
|
+
filter.range?.startDate,
|
|
22332
|
+
filter.range?.start
|
|
22333
|
+
];
|
|
22334
|
+
const possibleEnds = [
|
|
22335
|
+
filter.endDate,
|
|
22336
|
+
filter.end,
|
|
22337
|
+
filter.primaryRange?.endDate,
|
|
22338
|
+
filter.primaryRange?.end,
|
|
22339
|
+
filter.range?.endDate,
|
|
22340
|
+
filter.range?.end
|
|
22341
|
+
];
|
|
22342
|
+
possibleStarts.forEach((v) => {
|
|
22343
|
+
const ts = extractTimestamp(v);
|
|
22344
|
+
if (ts === void 0) return;
|
|
22345
|
+
earliest = earliest === void 0 ? ts : Math.min(earliest, ts);
|
|
22346
|
+
});
|
|
22347
|
+
possibleEnds.forEach((v) => {
|
|
22348
|
+
const ts = extractTimestamp(v);
|
|
22349
|
+
if (ts === void 0) return;
|
|
22350
|
+
latest = latest === void 0 ? ts : Math.max(latest, ts);
|
|
22351
|
+
});
|
|
22352
|
+
});
|
|
22353
|
+
if (earliest === void 0 || latest === void 0) return void 0;
|
|
22354
|
+
if (latest < earliest) [earliest, latest] = [latest, earliest];
|
|
22355
|
+
return {
|
|
22356
|
+
start: new Date(earliest),
|
|
22357
|
+
end: new Date(latest)
|
|
22358
|
+
};
|
|
22359
|
+
}
|
|
22360
|
+
function generateBucketKeys(start2, end, bucket) {
|
|
22361
|
+
const keys = /* @__PURE__ */ new Set();
|
|
22362
|
+
const startDay = new Date(Date.UTC(start2.getUTCFullYear(), start2.getUTCMonth(), start2.getUTCDate()));
|
|
22363
|
+
const endDay = new Date(Date.UTC(end.getUTCFullYear(), end.getUTCMonth(), end.getUTCDate()));
|
|
22364
|
+
const cur = new Date(startDay);
|
|
22365
|
+
while (cur <= endDay) {
|
|
22366
|
+
keys.add(getDateKey(cur, bucket));
|
|
22367
|
+
cur.setUTCDate(cur.getUTCDate() + 1);
|
|
22368
|
+
}
|
|
22369
|
+
return Array.from(keys).sort((a, b) => parseInt(a) - parseInt(b));
|
|
22370
|
+
}
|
|
22371
|
+
function buildEmptyAggRow(aggregations) {
|
|
22372
|
+
const multiAgg = aggregations.length > 1;
|
|
22373
|
+
const empty = {};
|
|
22374
|
+
aggregations.forEach((agg) => {
|
|
22375
|
+
const { aggregationType: type, valueField } = agg;
|
|
22376
|
+
const key = !valueField ? `${type}` + (multiAgg ? `_${type}` : "") : `${valueField}` + (multiAgg ? `_${type}` : "");
|
|
22377
|
+
empty[key] = 0;
|
|
22378
|
+
});
|
|
22379
|
+
return empty;
|
|
22380
|
+
}
|
|
22381
|
+
function getBucketRange(dateKey, bucket) {
|
|
22382
|
+
const d = new Date(parseInt(dateKey, 10));
|
|
22383
|
+
let start2 = new Date(d);
|
|
22384
|
+
let end = new Date(d);
|
|
22385
|
+
switch (bucket) {
|
|
22386
|
+
case "day":
|
|
22387
|
+
start2 = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
|
|
22388
|
+
end = new Date(start2);
|
|
22389
|
+
break;
|
|
22390
|
+
case "week":
|
|
22391
|
+
start2 = new Date(d);
|
|
22392
|
+
end = new Date(start2);
|
|
22393
|
+
end.setUTCDate(start2.getUTCDate() + 6);
|
|
22394
|
+
break;
|
|
22395
|
+
case "month":
|
|
22396
|
+
start2 = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1));
|
|
22397
|
+
end = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 0));
|
|
22398
|
+
break;
|
|
22399
|
+
case "year":
|
|
22400
|
+
start2 = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
|
22401
|
+
end = new Date(Date.UTC(d.getUTCFullYear(), 11, 31));
|
|
22402
|
+
break;
|
|
22403
|
+
}
|
|
22404
|
+
return { start: start2, end };
|
|
22405
|
+
}
|
|
22406
|
+
function formatBucketNameFromRange(start2, end, bucket) {
|
|
22407
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
22408
|
+
switch (bucket) {
|
|
22409
|
+
case "day":
|
|
22410
|
+
return `${pad(start2.getUTCDate())} ${MONTHS[start2.getUTCMonth()]} ${start2.getUTCFullYear()}`;
|
|
22411
|
+
case "week": {
|
|
22412
|
+
const sameMonth = start2.getUTCMonth() === end.getUTCMonth();
|
|
22413
|
+
return sameMonth ? `${MONTHS[start2.getUTCMonth()]} ${start2.getUTCDate()} - ${end.getUTCDate()}` : `${MONTHS[start2.getUTCMonth()]} ${start2.getUTCDate()} - ${MONTHS[end.getUTCMonth()]} ${end.getUTCDate()}`;
|
|
22414
|
+
}
|
|
22415
|
+
case "month":
|
|
22416
|
+
return `${MONTHS[start2.getUTCMonth()]} ${start2.getUTCFullYear()}`;
|
|
22417
|
+
case "year":
|
|
22418
|
+
return `${start2.getUTCFullYear()}`;
|
|
22419
|
+
default:
|
|
22420
|
+
return "";
|
|
22421
|
+
}
|
|
22422
|
+
}
|
|
22423
|
+
function getDateKey(date, bucket) {
|
|
22424
|
+
if (!isValidDate3(date)) {
|
|
22425
|
+
return INVALID_DATE_KEY;
|
|
22426
|
+
}
|
|
22427
|
+
switch (bucket) {
|
|
22428
|
+
case "day":
|
|
22429
|
+
return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()).toString();
|
|
22430
|
+
case "week": {
|
|
22431
|
+
const day = date.getUTCDay();
|
|
22432
|
+
const mondayUtc = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate() - (day + 6) % 7);
|
|
22433
|
+
return mondayUtc.toString();
|
|
22434
|
+
}
|
|
22435
|
+
case "month":
|
|
22436
|
+
return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1).toString();
|
|
22437
|
+
case "year":
|
|
22438
|
+
return Date.UTC(date.getUTCFullYear(), 0, 1).toString();
|
|
22439
|
+
default:
|
|
22440
|
+
return INVALID_DATE_KEY;
|
|
22441
|
+
}
|
|
22442
|
+
}
|
|
22443
|
+
function sortRows(rows, pivot) {
|
|
22444
|
+
try {
|
|
22445
|
+
const { sort, sortField, sortFieldType, sortDirection } = pivot;
|
|
22446
|
+
if (!sort || sortField == null || sortFieldType == null) return rows;
|
|
22447
|
+
const sortFunc = isBoolType(sortFieldType) ? (a, b) => a === b ? 0 : a ? 1 : -1 : isDateType(sortFieldType) ? (a, b) => {
|
|
22448
|
+
const ta = new Date(a), tb = new Date(b);
|
|
22449
|
+
const aValid = isValidDate3(ta), bValid = isValidDate3(tb);
|
|
22450
|
+
if (!aValid && !bValid) return 0;
|
|
22451
|
+
if (!aValid) return 1;
|
|
22452
|
+
if (!bValid) return -1;
|
|
22453
|
+
return ta.getTime() - tb.getTime();
|
|
22454
|
+
} : isStringType(sortFieldType) ? (a, b) => a.localeCompare(b) : (a, b) => a - b;
|
|
22455
|
+
const dir = sortDirection === "ASC" ? 1 : -1;
|
|
22456
|
+
rows.sort((a, b) => {
|
|
22457
|
+
const av = a[sortField], bv = b[sortField];
|
|
22458
|
+
if (av == null && bv == null) return 0;
|
|
22459
|
+
if (av == null) return 1;
|
|
22460
|
+
if (bv == null) return -1;
|
|
22461
|
+
return dir * sortFunc(av, bv);
|
|
22462
|
+
});
|
|
22463
|
+
} catch {
|
|
22464
|
+
console.warn(`Sorting failed.`);
|
|
22465
|
+
}
|
|
22466
|
+
return rows;
|
|
22467
|
+
}
|
|
22468
|
+
function assembleFinalRows(seen, rowKey, dateBucket, dateRange) {
|
|
22469
|
+
const allColumns = /* @__PURE__ */ new Set();
|
|
22470
|
+
Object.keys(seen).forEach((rowKeyVal) => {
|
|
22471
|
+
Object.keys(seen[rowKeyVal]).forEach((col) => {
|
|
22472
|
+
allColumns.add(col);
|
|
22473
|
+
});
|
|
22474
|
+
});
|
|
22475
|
+
const filled = {};
|
|
22476
|
+
Object.keys(seen).forEach((rowKeyVal) => {
|
|
22477
|
+
filled[rowKeyVal] = {};
|
|
22478
|
+
allColumns.forEach((col) => {
|
|
22479
|
+
const value = seen[rowKeyVal][col];
|
|
22480
|
+
filled[rowKeyVal][col] = value ?? 0;
|
|
22481
|
+
});
|
|
22482
|
+
});
|
|
22483
|
+
if (dateBucket) {
|
|
22484
|
+
return Object.keys(filled).sort((a, b) => parseInt(a) - parseInt(b)).map((k) => {
|
|
22485
|
+
if (k === INVALID_DATE_KEY) {
|
|
22486
|
+
return { [rowKey]: "Invalid Date", ...filled[k], __quillRawDate: 0 };
|
|
22487
|
+
}
|
|
22488
|
+
const { start: start2, end } = getBucketRange(k, dateBucket);
|
|
22489
|
+
let bucketStart = start2;
|
|
22490
|
+
let bucketEnd = end;
|
|
22491
|
+
if (dateRange) {
|
|
22492
|
+
if (bucketStart < dateRange.start) bucketStart = dateRange.start;
|
|
22493
|
+
if (bucketEnd > dateRange.end) bucketEnd = dateRange.end;
|
|
22494
|
+
}
|
|
22495
|
+
return {
|
|
22496
|
+
[rowKey]: formatBucketNameFromRange(bucketStart, bucketEnd, dateBucket),
|
|
22497
|
+
...filled[k],
|
|
22498
|
+
__quillRawDate: bucketStart.toISOString()
|
|
22499
|
+
};
|
|
22500
|
+
});
|
|
22501
|
+
}
|
|
22502
|
+
return Object.keys(filled).sort().map((k) => ({ [rowKey]: k, ...filled[k] }));
|
|
22503
|
+
}
|
|
22504
|
+
function anyToNum(valueFieldType, obj) {
|
|
22505
|
+
if (!valueFieldType) {
|
|
22506
|
+
if (typeof obj === "number") return obj;
|
|
22507
|
+
if (typeof obj === "string" && !isNaN(Number(obj))) return Number(obj);
|
|
22508
|
+
return obj ? 1 : 0;
|
|
22509
|
+
}
|
|
22510
|
+
if (isNumberType(valueFieldType)) {
|
|
22511
|
+
return Number(obj);
|
|
22512
|
+
}
|
|
22513
|
+
return obj ? 1 : 0;
|
|
22514
|
+
}
|
|
22515
|
+
function updateAccumulator(acc, row, agg, isOneRow) {
|
|
22516
|
+
const {
|
|
22517
|
+
aggregationType: type,
|
|
22518
|
+
valueField,
|
|
22519
|
+
valueFieldType,
|
|
22520
|
+
valueField2,
|
|
22521
|
+
valueField2Type
|
|
22522
|
+
} = agg;
|
|
22523
|
+
if (!valueField) return;
|
|
22524
|
+
const distinctDenom = !!valueField2 && !!valueField2Type && valueField !== valueField2;
|
|
22525
|
+
const rawVal = row[valueField];
|
|
22526
|
+
if (valueFieldType && (type === "min" || type === "max") && (isDateType(valueFieldType) || isDateFormat2(valueFieldType))) {
|
|
22527
|
+
const dateVal = rawVal instanceof Date ? rawVal : new Date(rawVal);
|
|
22528
|
+
if (!isNaN(dateVal.getTime())) {
|
|
22529
|
+
if (type === "min") {
|
|
22530
|
+
acc.minDate = acc.minDate && acc.minDate.getTime() < dateVal.getTime() ? acc.minDate : dateVal;
|
|
22531
|
+
} else {
|
|
22532
|
+
acc.maxDate = acc.maxDate && acc.maxDate.getTime() > dateVal.getTime() ? acc.maxDate : dateVal;
|
|
22533
|
+
}
|
|
22534
|
+
}
|
|
22535
|
+
return;
|
|
22536
|
+
}
|
|
22537
|
+
const numVal = anyToNum(valueFieldType, rawVal);
|
|
22538
|
+
switch (type) {
|
|
22539
|
+
case "sum":
|
|
22540
|
+
acc.sum += numVal;
|
|
22541
|
+
break;
|
|
22542
|
+
case "average":
|
|
22543
|
+
case "avg":
|
|
22544
|
+
acc.sum += numVal;
|
|
22545
|
+
acc.count++;
|
|
22546
|
+
break;
|
|
22547
|
+
case "min":
|
|
22548
|
+
acc.min = acc.hasVal ? Math.min(acc.min, numVal) : numVal;
|
|
22549
|
+
acc.hasVal = true;
|
|
22550
|
+
break;
|
|
22551
|
+
case "max":
|
|
22552
|
+
acc.max = acc.hasVal ? Math.max(acc.max, numVal) : numVal;
|
|
22553
|
+
acc.hasVal = true;
|
|
22554
|
+
break;
|
|
22555
|
+
case "count":
|
|
22556
|
+
acc.count += numVal;
|
|
22557
|
+
break;
|
|
22558
|
+
case "percentage":
|
|
22559
|
+
acc.sum += numVal;
|
|
22560
|
+
acc.count += distinctDenom ? anyToNum(valueField2Type, row[valueField2]) : isOneRow ? 1 : numVal;
|
|
22561
|
+
break;
|
|
22562
|
+
}
|
|
22563
|
+
}
|
|
22564
|
+
function getFinalAggregationValue({
|
|
22565
|
+
type,
|
|
22566
|
+
valueFieldType,
|
|
22567
|
+
valueField,
|
|
22568
|
+
acc,
|
|
22569
|
+
distinctDenom = false,
|
|
22570
|
+
sumOfDenom,
|
|
22571
|
+
rowsLength,
|
|
22572
|
+
totalRowsForCount
|
|
22573
|
+
}) {
|
|
22574
|
+
if (valueFieldType && (type === "min" || type === "max") && (isDateType(valueFieldType) || isDateFormat2(valueFieldType))) {
|
|
22575
|
+
const dateVal = type === "min" ? acc.minDate : acc.maxDate;
|
|
22576
|
+
return dateVal?.toISOString() ?? "";
|
|
22577
|
+
}
|
|
22578
|
+
if (type === "count") {
|
|
22579
|
+
return totalRowsForCount ?? acc.count;
|
|
22580
|
+
}
|
|
22581
|
+
let final;
|
|
22582
|
+
if (!valueField && type === "percentage" && rowsLength !== void 0) {
|
|
22583
|
+
final = rowsLength ? (totalRowsForCount ?? 0) / rowsLength : 0;
|
|
22584
|
+
} else {
|
|
22585
|
+
switch (type) {
|
|
22586
|
+
case "sum":
|
|
22587
|
+
final = acc.sum;
|
|
22588
|
+
break;
|
|
22589
|
+
case "average":
|
|
22590
|
+
case "avg":
|
|
22591
|
+
final = acc.count ? acc.sum / acc.count : 0;
|
|
22592
|
+
break;
|
|
22593
|
+
case "min":
|
|
22594
|
+
final = acc.hasVal ? acc.min : 0;
|
|
22595
|
+
break;
|
|
22596
|
+
case "max":
|
|
22597
|
+
final = acc.hasVal ? acc.max : 0;
|
|
22598
|
+
break;
|
|
22599
|
+
case "percentage": {
|
|
22600
|
+
const denom = distinctDenom ? acc.count : sumOfDenom ?? acc.count;
|
|
22601
|
+
final = denom ? acc.sum / denom : 0;
|
|
22602
|
+
break;
|
|
22603
|
+
}
|
|
22604
|
+
default:
|
|
22605
|
+
final = 0;
|
|
22606
|
+
}
|
|
22607
|
+
}
|
|
22608
|
+
return final;
|
|
22609
|
+
}
|
|
22610
|
+
function aggregateToOneRow(rows, aggregations) {
|
|
22611
|
+
const multiAgg = aggregations.length > 1;
|
|
22612
|
+
const resultArray = aggregations.map((agg) => {
|
|
22613
|
+
const { aggregationType: type, valueField, valueFieldType } = agg;
|
|
22614
|
+
if (!valueField) {
|
|
22615
|
+
if (type !== "count") {
|
|
22616
|
+
return {};
|
|
22617
|
+
}
|
|
22618
|
+
const finalKey2 = "count" + (multiAgg ? "_count" : "");
|
|
22619
|
+
return { [finalKey2]: rows.length };
|
|
22620
|
+
}
|
|
22621
|
+
const finalKey = `${valueField}` + (multiAgg ? `_${type}` : "");
|
|
22622
|
+
const acc = {
|
|
22623
|
+
sum: 0,
|
|
22624
|
+
count: 0,
|
|
22625
|
+
min: Infinity,
|
|
22626
|
+
max: -Infinity,
|
|
22627
|
+
hasVal: false,
|
|
22628
|
+
minDate: null,
|
|
22629
|
+
maxDate: null
|
|
22630
|
+
};
|
|
22631
|
+
for (const row of rows) {
|
|
22632
|
+
updateAccumulator(acc, row, agg, true);
|
|
22633
|
+
}
|
|
22634
|
+
return {
|
|
22635
|
+
[finalKey]: getFinalAggregationValue({
|
|
22636
|
+
type,
|
|
22637
|
+
valueFieldType,
|
|
22638
|
+
valueField,
|
|
22639
|
+
acc,
|
|
22640
|
+
totalRowsForCount: acc.count
|
|
22641
|
+
})
|
|
22642
|
+
};
|
|
22643
|
+
});
|
|
22644
|
+
return [
|
|
22645
|
+
resultArray.reduce((acc, current) => {
|
|
22646
|
+
return { ...acc, ...current };
|
|
22647
|
+
}, {})
|
|
22648
|
+
];
|
|
22649
|
+
}
|
|
22650
|
+
function aggregateWithColumn(rows, colKey, aggregations, getGroupKey) {
|
|
22651
|
+
if (!colKey) return;
|
|
22652
|
+
const seen = {};
|
|
22653
|
+
const multiAgg = aggregations.length > 1;
|
|
22654
|
+
aggregations.forEach((agg) => {
|
|
22655
|
+
const { aggregationType: type, valueField, valueFieldType, valueField2, valueField2Type } = agg;
|
|
22656
|
+
if (!valueField) {
|
|
22657
|
+
if (type !== "count" && type !== "percentage") return;
|
|
22658
|
+
}
|
|
22659
|
+
const distinctDenom = !!valueField2 && !!valueField2Type && valueField !== valueField2;
|
|
22660
|
+
const accs = {};
|
|
22661
|
+
rows.forEach((row) => {
|
|
22662
|
+
const groupKey = getGroupKey(row);
|
|
22663
|
+
const colVal = row[colKey];
|
|
22664
|
+
if (!accs[groupKey]) accs[groupKey] = {};
|
|
22665
|
+
if (!accs[groupKey][colVal]) {
|
|
22666
|
+
accs[groupKey][colVal] = {
|
|
22667
|
+
sum: 0,
|
|
22668
|
+
count: 0,
|
|
22669
|
+
min: Infinity,
|
|
22670
|
+
max: -Infinity,
|
|
22671
|
+
hasVal: false,
|
|
22672
|
+
minDate: null,
|
|
22673
|
+
maxDate: null,
|
|
22674
|
+
totalRows: 0
|
|
22675
|
+
};
|
|
22676
|
+
}
|
|
22677
|
+
const acc = accs[groupKey][colVal];
|
|
22678
|
+
acc.totalRows += 1;
|
|
22679
|
+
if (!valueField) {
|
|
22680
|
+
if (type === "count") acc.count += 1;
|
|
22681
|
+
else if (type === "percentage") acc.sum += 1;
|
|
22682
|
+
return;
|
|
22683
|
+
}
|
|
22684
|
+
updateAccumulator(acc, row, agg, false);
|
|
22685
|
+
});
|
|
22686
|
+
Object.keys(accs).forEach((groupKey) => {
|
|
22687
|
+
if (!seen[groupKey]) seen[groupKey] = {};
|
|
22688
|
+
const sumOfDenom = Object.values(accs[groupKey]).reduce((t, a) => t + a.count, 0);
|
|
22689
|
+
Object.keys(accs[groupKey]).forEach((colVal) => {
|
|
22690
|
+
const acc = accs[groupKey][colVal];
|
|
22691
|
+
const finalKey = `${colVal}` + (multiAgg ? `_${type}` : "");
|
|
22692
|
+
seen[groupKey][finalKey] = getFinalAggregationValue({
|
|
22693
|
+
type,
|
|
22694
|
+
valueFieldType,
|
|
22695
|
+
valueField,
|
|
22696
|
+
acc,
|
|
22697
|
+
distinctDenom,
|
|
22698
|
+
sumOfDenom,
|
|
22699
|
+
totalRowsForCount: acc.totalRows
|
|
22700
|
+
});
|
|
22701
|
+
});
|
|
22702
|
+
});
|
|
22703
|
+
});
|
|
22704
|
+
return seen;
|
|
22705
|
+
}
|
|
22706
|
+
function aggregateWithoutColumn(rows, aggregations, getGroupKey) {
|
|
22707
|
+
const seen = {};
|
|
22708
|
+
const multiAgg = aggregations.length > 1;
|
|
22709
|
+
aggregations.forEach((agg) => {
|
|
22710
|
+
const { aggregationType: type, valueField, valueFieldType, valueField2, valueField2Type } = agg;
|
|
22711
|
+
if (!valueField) {
|
|
22712
|
+
if (type !== "count" && type !== "percentage") return;
|
|
22713
|
+
}
|
|
22714
|
+
const finalKey = !valueField ? `${type}` + (multiAgg ? `_${type}` : "") : `${valueField}` + (multiAgg ? `_${type}` : "");
|
|
22715
|
+
const distinctDenom = !!valueField2 && !!valueField2Type && valueField !== valueField2;
|
|
22716
|
+
const accs = {};
|
|
22717
|
+
rows.forEach((row) => {
|
|
22718
|
+
const key = getGroupKey(row);
|
|
22719
|
+
if (!seen[key]) seen[key] = {};
|
|
22720
|
+
if (!accs[key]) {
|
|
22721
|
+
accs[key] = {
|
|
22722
|
+
sum: 0,
|
|
22723
|
+
count: 0,
|
|
22724
|
+
min: Infinity,
|
|
22725
|
+
max: -Infinity,
|
|
22726
|
+
hasVal: false,
|
|
22727
|
+
minDate: null,
|
|
22728
|
+
maxDate: null,
|
|
22729
|
+
totalRows: 0
|
|
22730
|
+
};
|
|
22731
|
+
}
|
|
22732
|
+
const acc = accs[key];
|
|
22733
|
+
acc.totalRows += 1;
|
|
22734
|
+
if (!valueField) {
|
|
22735
|
+
if (type === "count") acc.count += 1;
|
|
22736
|
+
else if (type === "percentage") acc.sum += 1;
|
|
22737
|
+
return;
|
|
22738
|
+
}
|
|
22739
|
+
updateAccumulator(acc, row, agg, false);
|
|
22740
|
+
});
|
|
22741
|
+
const sumOfDenom = Object.values(accs).reduce((t, a) => t + a.count, 0);
|
|
22742
|
+
Object.keys(accs).forEach((k) => {
|
|
22743
|
+
const acc = accs[k];
|
|
22744
|
+
seen[k][finalKey] = getFinalAggregationValue({
|
|
22745
|
+
type,
|
|
22746
|
+
valueFieldType,
|
|
22747
|
+
valueField,
|
|
22748
|
+
acc,
|
|
22749
|
+
distinctDenom,
|
|
22750
|
+
sumOfDenom,
|
|
22751
|
+
rowsLength: rows.length,
|
|
22752
|
+
totalRowsForCount: acc.totalRows
|
|
22753
|
+
});
|
|
22754
|
+
});
|
|
22755
|
+
});
|
|
22756
|
+
return seen;
|
|
22757
|
+
}
|
|
22758
|
+
function applyPivotInMemory(rows, pivot, filters) {
|
|
22759
|
+
if (!pivot) return rows;
|
|
22760
|
+
const multiAggPivot = pivot.aggregations ? pivot : singleAggToMultiAgg(pivot);
|
|
22761
|
+
if (multiAggPivot.rowField === void 0) {
|
|
22762
|
+
return aggregateToOneRow(rows, multiAggPivot.aggregations);
|
|
22763
|
+
}
|
|
22764
|
+
const { rowField, columnField, aggregations } = multiAggPivot;
|
|
22765
|
+
const dateBucket = inferDateBucketFromFilters(pivot, filters);
|
|
22766
|
+
const dateRange = dateBucket ? getDateRangeFromFilters(filters) : void 0;
|
|
22767
|
+
const getRowKey = dateBucket ? (row) => {
|
|
22768
|
+
const rawValue = row[rowField];
|
|
22769
|
+
const rawDateValue = rawValue !== null && typeof rawValue === "object" && rawValue.value ? rawValue.value : rawValue;
|
|
22770
|
+
return getDateKey(new Date(rawDateValue), dateBucket);
|
|
22771
|
+
} : (row) => row[rowField];
|
|
22772
|
+
const aggregated = columnField ? aggregateWithColumn(rows, columnField, aggregations, getRowKey) : aggregateWithoutColumn(rows, aggregations, getRowKey);
|
|
22773
|
+
const aggregatedRows = aggregated || {};
|
|
22774
|
+
if (rows.length === 0 && dateBucket && dateRange && !columnField) {
|
|
22775
|
+
const bucketKeys = generateBucketKeys(dateRange.start, dateRange.end, dateBucket);
|
|
22776
|
+
const emptyAgg = buildEmptyAggRow(aggregations);
|
|
22777
|
+
bucketKeys.forEach((k) => {
|
|
22778
|
+
aggregatedRows[k] = { ...emptyAgg };
|
|
22779
|
+
});
|
|
22780
|
+
}
|
|
22781
|
+
const finalRows = assembleFinalRows(
|
|
22782
|
+
aggregatedRows,
|
|
22783
|
+
rowField,
|
|
22784
|
+
dateBucket,
|
|
22785
|
+
rows.length === 0 ? dateRange : void 0
|
|
22786
|
+
);
|
|
22787
|
+
const sorted = sortRows(finalRows, pivot);
|
|
22788
|
+
if (pivot.rowLimit) {
|
|
22789
|
+
return sorted.slice(0, pivot.rowLimit);
|
|
22790
|
+
}
|
|
22791
|
+
return sorted;
|
|
22792
|
+
}
|
|
22793
|
+
|
|
22794
|
+
// src/utils/cacheCab.ts
|
|
22795
|
+
import { openDB } from "idb";
|
|
22796
|
+
import { endOfDay as endOfDay3, max as maxDate, subMonths as subMonths4, min as minDate, startOfDay as startOfDay4 } from "date-fns";
|
|
22797
|
+
import { utcToZonedTime as utcToZonedTime2, zonedTimeToUtc } from "date-fns-tz";
|
|
22798
|
+
var TZ = "America/Los_Angeles";
|
|
22799
|
+
var CacheCab = class {
|
|
22800
|
+
fetchedRange = {};
|
|
22801
|
+
cachedReportIds = [];
|
|
22802
|
+
uncacheableReportIDs = [];
|
|
22803
|
+
uncacheableInFlight = /* @__PURE__ */ new Map();
|
|
22804
|
+
storage;
|
|
22805
|
+
META_KEY = "cachecab:meta";
|
|
22806
|
+
DATA_PREFIX = "cachecab:data:";
|
|
22807
|
+
UNCACHEABLE_PREFIX = "cachecab:uncacheable:";
|
|
22808
|
+
constructor({
|
|
22809
|
+
storageType = "memory"
|
|
22810
|
+
} = {}) {
|
|
22811
|
+
this.storage = storageType !== "idb" ? new MemoryStorage() : new IdbStorage();
|
|
22812
|
+
void this.loadMetaFromStorage();
|
|
22813
|
+
}
|
|
22814
|
+
async get(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, pageSize, getToken, eventTracking, forceRefresh) {
|
|
22815
|
+
if (this.isCached(reportId, tenants) && !forceRefresh) {
|
|
22816
|
+
return this.getFromCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking);
|
|
22817
|
+
} else {
|
|
22818
|
+
return this.addToCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, true, forceRefresh);
|
|
22819
|
+
}
|
|
22820
|
+
}
|
|
22821
|
+
isCached(reportId, tenants) {
|
|
22822
|
+
return this.cachedReportIds.includes(this.getCacheKey(reportId, tenants));
|
|
22823
|
+
}
|
|
22824
|
+
isCacheable(reportId) {
|
|
22825
|
+
return !this.uncacheableReportIDs.includes(reportId);
|
|
22826
|
+
}
|
|
22827
|
+
async getUncacheableResult(reportId, client, tenants, flags, filters, additionalProcessing, pivot) {
|
|
22828
|
+
const key = this.getUncacheableRequestKey(
|
|
22829
|
+
reportId,
|
|
22830
|
+
client,
|
|
22831
|
+
tenants,
|
|
22832
|
+
flags,
|
|
22833
|
+
filters,
|
|
22834
|
+
additionalProcessing,
|
|
22835
|
+
pivot
|
|
22836
|
+
);
|
|
22837
|
+
try {
|
|
22838
|
+
const raw = await this.storage.getItem(key);
|
|
22839
|
+
return raw ? JSON.parse(raw) : null;
|
|
22840
|
+
} catch {
|
|
22841
|
+
return null;
|
|
22842
|
+
}
|
|
22843
|
+
}
|
|
22844
|
+
async setUncacheableResult(reportId, client, tenants, flags, filters, additionalProcessing, pivot, report) {
|
|
22845
|
+
const key = this.getUncacheableRequestKey(
|
|
22846
|
+
reportId,
|
|
22847
|
+
client,
|
|
22848
|
+
tenants,
|
|
22849
|
+
flags,
|
|
22850
|
+
filters,
|
|
22851
|
+
additionalProcessing,
|
|
22852
|
+
pivot
|
|
22853
|
+
);
|
|
22854
|
+
try {
|
|
22855
|
+
await this.storage.setItem(key, JSON.stringify(report));
|
|
22856
|
+
} catch {
|
|
22857
|
+
}
|
|
22858
|
+
}
|
|
22859
|
+
async getOrFetchUncacheableResult(reportId, client, tenants, flags, filters, additionalProcessing, pivot, fetcher, forceRefresh = false) {
|
|
22860
|
+
const key = this.getUncacheableRequestKey(
|
|
22861
|
+
reportId,
|
|
22862
|
+
client,
|
|
22863
|
+
tenants,
|
|
22864
|
+
flags,
|
|
22865
|
+
filters,
|
|
22866
|
+
additionalProcessing,
|
|
22867
|
+
pivot
|
|
22868
|
+
);
|
|
22869
|
+
if (!forceRefresh) {
|
|
22870
|
+
const raw = await this.storage.getItem(key);
|
|
22871
|
+
if (raw) {
|
|
22872
|
+
return { report: JSON.parse(raw), fromCache: true };
|
|
22873
|
+
}
|
|
22874
|
+
const inFlight = this.uncacheableInFlight.get(key);
|
|
22875
|
+
if (inFlight) {
|
|
22876
|
+
const report = await inFlight;
|
|
22877
|
+
return { report, fromCache: false };
|
|
22878
|
+
}
|
|
22879
|
+
}
|
|
22880
|
+
const requestPromise = (async () => {
|
|
22881
|
+
const report = await fetcher();
|
|
22882
|
+
try {
|
|
22883
|
+
await this.storage.setItem(key, JSON.stringify(report));
|
|
22884
|
+
} catch {
|
|
22885
|
+
}
|
|
22886
|
+
return report;
|
|
22887
|
+
})();
|
|
22888
|
+
this.uncacheableInFlight.set(key, requestPromise);
|
|
22889
|
+
try {
|
|
22890
|
+
const report = await requestPromise;
|
|
22891
|
+
return { report, fromCache: false };
|
|
22892
|
+
} finally {
|
|
22893
|
+
this.uncacheableInFlight.delete(key);
|
|
22894
|
+
}
|
|
22895
|
+
}
|
|
22896
|
+
async addToCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, firstTime = true, forceRefresh = false) {
|
|
22897
|
+
const tenantPart = tenants ? JSON.stringify(tenants) : "";
|
|
22898
|
+
const cacheKey = this.getCacheKey(reportId, tenants);
|
|
22899
|
+
if (firstTime) {
|
|
22900
|
+
const result = await this.fetchInitialReport({ reportId, client, tenants, flags, filters: dashboardFilters, getToken, eventTracking, forceRefresh });
|
|
22901
|
+
try {
|
|
22902
|
+
await this.storage.setItem(this.DATA_PREFIX + cacheKey, JSON.stringify(result));
|
|
22903
|
+
this.cachedReportIds.push(cacheKey);
|
|
22904
|
+
await this.persistMetaToStorage();
|
|
22905
|
+
} catch {
|
|
22906
|
+
console.warn(`Failed to cache report: ${reportId}. Cache full?`);
|
|
22907
|
+
}
|
|
22908
|
+
const newRows = await this.applyPivotsAndFilters(result, dashboardFilters, customFilters, pivot, tenantPart, false);
|
|
22909
|
+
if (pivot) {
|
|
22910
|
+
return { ...result, pivotRows: newRows, pivotRowCount: newRows.length };
|
|
22911
|
+
}
|
|
22912
|
+
return { ...result, rows: newRows, rowCount: newRows.length };
|
|
22913
|
+
} else {
|
|
22914
|
+
const dbDateFilter = dashboardFilters.find((x) => x.filterType === "date_range");
|
|
22915
|
+
const { start: requestedStart, end: requestedEnd } = normalizePSTRanges(
|
|
22916
|
+
dbDateFilter?.startDate ? new Date(dbDateFilter.startDate) : void 0,
|
|
22917
|
+
dbDateFilter?.endDate ? new Date(dbDateFilter.endDate) : void 0
|
|
22918
|
+
);
|
|
22919
|
+
if (!requestedStart || !requestedEnd) {
|
|
22920
|
+
return this.addToCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, true);
|
|
22921
|
+
}
|
|
22922
|
+
const currentRange = this.fetchedRange[cacheKey];
|
|
22923
|
+
const rangeStart = currentRange?.start ?? requestedStart;
|
|
22924
|
+
const rangeEnd = currentRange?.end ?? endOfDayPST(/* @__PURE__ */ new Date());
|
|
22925
|
+
const existingRaw = await this.storage.getItem(this.DATA_PREFIX + cacheKey);
|
|
22926
|
+
let existing;
|
|
22927
|
+
let fetchedRows = [];
|
|
22928
|
+
try {
|
|
22929
|
+
existing = JSON.parse(existingRaw);
|
|
22930
|
+
if (!existing.rows) {
|
|
22931
|
+
throw new Error("Invalid Cache!");
|
|
22932
|
+
}
|
|
22933
|
+
if (requestedStart < rangeStart) {
|
|
22934
|
+
const olderReport = await this.fetchReport({
|
|
22935
|
+
reportId,
|
|
22936
|
+
client,
|
|
22937
|
+
tenants,
|
|
22938
|
+
flags,
|
|
22939
|
+
filters: dashboardFilters,
|
|
22940
|
+
getToken,
|
|
22941
|
+
eventTracking,
|
|
22942
|
+
start: requestedStart,
|
|
22943
|
+
end: rangeStart
|
|
22944
|
+
});
|
|
22945
|
+
fetchedRows = olderReport.rows;
|
|
22946
|
+
}
|
|
22947
|
+
if (requestedEnd && requestedEnd > rangeEnd) {
|
|
22948
|
+
const newerReport = await this.fetchReport({
|
|
22949
|
+
reportId,
|
|
22950
|
+
client,
|
|
22951
|
+
tenants,
|
|
22952
|
+
flags,
|
|
22953
|
+
filters: dashboardFilters,
|
|
22954
|
+
getToken,
|
|
22955
|
+
eventTracking,
|
|
22956
|
+
start: rangeEnd,
|
|
22957
|
+
end: requestedEnd
|
|
22958
|
+
});
|
|
22959
|
+
fetchedRows = fetchedRows.concat(newerReport.rows);
|
|
22960
|
+
}
|
|
22961
|
+
} catch {
|
|
22962
|
+
existing = await this.fetchReport({
|
|
22963
|
+
reportId,
|
|
22964
|
+
client,
|
|
22965
|
+
tenants,
|
|
22966
|
+
flags,
|
|
22967
|
+
filters: dashboardFilters,
|
|
22968
|
+
getToken,
|
|
22969
|
+
eventTracking,
|
|
22970
|
+
start: requestedStart,
|
|
22971
|
+
end: requestedEnd
|
|
22972
|
+
});
|
|
22973
|
+
fetchedRows = existing.rows;
|
|
22974
|
+
}
|
|
22975
|
+
const dateKey = existing.dateField?.field ? removeQuotes(existing.dateField.field) : void 0;
|
|
22976
|
+
let mergedRows;
|
|
22977
|
+
if (dateKey) {
|
|
22978
|
+
const startMs = rangeStart.getTime();
|
|
22979
|
+
const endMs = rangeEnd.getTime();
|
|
22980
|
+
const boundaryRows = existing.rows.filter((row) => {
|
|
22981
|
+
const raw = row[dateKey];
|
|
22982
|
+
if (!raw) return false;
|
|
22983
|
+
const t = new Date(raw).getTime();
|
|
22984
|
+
return Math.abs(t - startMs) <= MS_IN_DAY || Math.abs(t - endMs) <= MS_IN_DAY;
|
|
22985
|
+
});
|
|
22986
|
+
const filteredNew = filterNewRows(boundaryRows, fetchedRows);
|
|
22987
|
+
mergedRows = filteredNew.concat(existing.rows);
|
|
22988
|
+
} else {
|
|
22989
|
+
mergedRows = filterNewRows(existing.rows, fetchedRows).concat(existing.rows);
|
|
22990
|
+
}
|
|
22991
|
+
const merged = { ...existing, rows: mergedRows };
|
|
22992
|
+
await this.storage.setItem(this.DATA_PREFIX + cacheKey, JSON.stringify(merged));
|
|
22993
|
+
await this.persistMetaToStorage();
|
|
22994
|
+
const newRows = await this.applyPivotsAndFilters(merged, dashboardFilters, customFilters, pivot, tenantPart, false);
|
|
22995
|
+
if (pivot) {
|
|
22996
|
+
return { ...merged, pivotRows: newRows, pivotRowCount: newRows.length };
|
|
22997
|
+
}
|
|
22998
|
+
return { ...merged, rows: newRows, rowCount: newRows.length };
|
|
22999
|
+
}
|
|
23000
|
+
}
|
|
23001
|
+
/**
|
|
23002
|
+
* Returns cache entry (or re-queries if stale)
|
|
23003
|
+
*/
|
|
23004
|
+
async getFromCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking) {
|
|
23005
|
+
const dateRangeFilter = dashboardFilters.find((x) => x.filterType === "date_range");
|
|
23006
|
+
const cacheKey = this.getCacheKey(reportId, tenants);
|
|
23007
|
+
if (!dateRangeFilter || dateRangeFilter?.primaryRange.value === "ALL_TIME") {
|
|
23008
|
+
const fetchInfo = this.fetchedRange[cacheKey];
|
|
23009
|
+
if (!fetchInfo || fetchInfo?.allTimeDoneBefore === false || Date.now() - fetchInfo.fetchedAtUTCMS >= MS_IN_DAY) {
|
|
23010
|
+
return this.addToCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, true);
|
|
23011
|
+
}
|
|
23012
|
+
} else if (this.weShouldReQuery(cacheKey, dateRangeFilter)) {
|
|
23013
|
+
return this.addToCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, false);
|
|
23014
|
+
}
|
|
23015
|
+
try {
|
|
23016
|
+
const raw = await this.storage.getItem(this.DATA_PREFIX + cacheKey);
|
|
23017
|
+
if (!raw) {
|
|
23018
|
+
throw new Error("Invalid Cache!");
|
|
23019
|
+
}
|
|
23020
|
+
const parsed = JSON.parse(raw);
|
|
23021
|
+
const tenantPart = tenants ? JSON.stringify(tenants) : "";
|
|
23022
|
+
const newRows = await this.applyPivotsAndFilters(parsed, dashboardFilters, customFilters, pivot, tenantPart);
|
|
23023
|
+
if (pivot) {
|
|
23024
|
+
return { ...parsed, pivotRows: newRows, pivotRowCount: newRows.length };
|
|
23025
|
+
}
|
|
23026
|
+
return { ...parsed, rows: newRows, rowCount: newRows.length };
|
|
23027
|
+
} catch (err) {
|
|
23028
|
+
console.error(err);
|
|
23029
|
+
return this.addToCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, false);
|
|
23030
|
+
}
|
|
23031
|
+
}
|
|
23032
|
+
weShouldReQuery(cacheKey, dateRangeFilter) {
|
|
23033
|
+
const start2 = dateRangeFilter.startDate;
|
|
23034
|
+
const end = dateRangeFilter.endDate;
|
|
23035
|
+
const range = this.fetchedRange[cacheKey];
|
|
23036
|
+
const { start: s, end: e } = normalizePSTRanges(
|
|
23037
|
+
start2 ? new Date(start2) : void 0,
|
|
23038
|
+
end ? new Date(end) : void 0
|
|
23039
|
+
);
|
|
23040
|
+
return !range || !s || !e || range.start > s || range.end < e;
|
|
23041
|
+
}
|
|
23042
|
+
async fetchInitialReport({
|
|
23043
|
+
reportId,
|
|
23044
|
+
client,
|
|
23045
|
+
tenants,
|
|
23046
|
+
flags,
|
|
23047
|
+
filters = [],
|
|
23048
|
+
getToken,
|
|
23049
|
+
eventTracking,
|
|
23050
|
+
forceRefresh
|
|
23051
|
+
}) {
|
|
23052
|
+
let start2;
|
|
23053
|
+
let end;
|
|
23054
|
+
const dateRangeFilter = filters.find((x) => x.filterType === "date_range");
|
|
23055
|
+
const cacheRange = dateRangeFilter?.initialCacheDateRange;
|
|
23056
|
+
if (cacheRange && cacheRange.startDate) {
|
|
23057
|
+
const startDate = dateRangeFilter?.startDate;
|
|
23058
|
+
start2 = startDate ? minDate([new Date(cacheRange.startDate), new Date(startDate)]) : new Date(cacheRange.startDate);
|
|
23059
|
+
end = endOfDayPST(/* @__PURE__ */ new Date());
|
|
23060
|
+
} else {
|
|
23061
|
+
const endDate = dateRangeFilter?.endDate ? new Date(dateRangeFilter.endDate) : void 0;
|
|
23062
|
+
const currentDay = endOfDayPST(/* @__PURE__ */ new Date());
|
|
23063
|
+
end = endDate ? maxDate([currentDay, endDate]) : currentDay;
|
|
23064
|
+
start2 = subMonths4(end, 7);
|
|
23065
|
+
}
|
|
23066
|
+
const normalized = normalizePSTRanges(start2, end);
|
|
23067
|
+
return this.fetchReport({
|
|
23068
|
+
reportId,
|
|
23069
|
+
client,
|
|
23070
|
+
tenants,
|
|
23071
|
+
flags,
|
|
23072
|
+
filters,
|
|
23073
|
+
getToken,
|
|
23074
|
+
eventTracking,
|
|
23075
|
+
start: normalized.start,
|
|
23076
|
+
end: normalized.end,
|
|
23077
|
+
forceRefresh
|
|
23078
|
+
});
|
|
23079
|
+
}
|
|
23080
|
+
async fetchReport({
|
|
23081
|
+
reportId,
|
|
23082
|
+
client,
|
|
23083
|
+
tenants,
|
|
23084
|
+
flags,
|
|
23085
|
+
filters = [],
|
|
23086
|
+
getToken,
|
|
23087
|
+
eventTracking,
|
|
23088
|
+
start: start2,
|
|
23089
|
+
end,
|
|
23090
|
+
forceRefresh
|
|
23091
|
+
}) {
|
|
23092
|
+
let reportInfo = void 0;
|
|
23093
|
+
try {
|
|
23094
|
+
const { start: s, end: e } = normalizePSTRanges(start2, end);
|
|
23095
|
+
const adjusted = [...filters].map((x) => {
|
|
23096
|
+
return { ...x, options: void 0 };
|
|
23097
|
+
});
|
|
23098
|
+
const dateFilterIndex = adjusted.findIndex((x) => x.filterType === "date_range");
|
|
23099
|
+
const isAllTime = dateFilterIndex !== -1 && adjusted[dateFilterIndex].primaryRange?.value === "ALL_TIME";
|
|
23100
|
+
if (!isAllTime) {
|
|
23101
|
+
const dateFilter = adjusted[dateFilterIndex];
|
|
23102
|
+
if (dateFilter && dateFilter.startDate && dateFilter.endDate) {
|
|
23103
|
+
adjusted[dateFilterIndex] = { ...dateFilter, startDate: s, endDate: e };
|
|
23104
|
+
}
|
|
23105
|
+
}
|
|
23106
|
+
const fetchResp = await quillFetch({
|
|
23107
|
+
client,
|
|
23108
|
+
task: "report",
|
|
23109
|
+
metadata: {
|
|
23110
|
+
reportId,
|
|
23111
|
+
clientId: client.publicKey,
|
|
23112
|
+
databaseType: client.databaseType,
|
|
23113
|
+
filters: adjusted,
|
|
23114
|
+
additionalProcessing: { page: { rowsPerPage: 1e3, rowsPerRequest: 1e5 } },
|
|
23115
|
+
useNewNodeSql: true,
|
|
23116
|
+
tenants,
|
|
23117
|
+
flags,
|
|
23118
|
+
overwriteCache: forceRefresh ?? false
|
|
23119
|
+
},
|
|
23120
|
+
getToken
|
|
23121
|
+
});
|
|
23122
|
+
const resp = await parseFetchResponse(
|
|
23123
|
+
client,
|
|
23124
|
+
"report",
|
|
23125
|
+
fetchResp,
|
|
23126
|
+
getToken,
|
|
23127
|
+
true
|
|
23128
|
+
);
|
|
23129
|
+
reportInfo = await processReportResponse({
|
|
23130
|
+
resp,
|
|
23131
|
+
client,
|
|
23132
|
+
filters: adjusted,
|
|
23133
|
+
dateBucket: resp?.dateBucket,
|
|
23134
|
+
additionalProcessing: { page: { rowsPerPage: 1e3, rowsPerRequest: 1e5 } },
|
|
23135
|
+
getToken,
|
|
23136
|
+
eventTracking,
|
|
23137
|
+
tenants,
|
|
23138
|
+
// CacheCab fetches with task: 'report'; keep pivot processing local.
|
|
23139
|
+
skipPivotFetch: true,
|
|
23140
|
+
overwriteCache: forceRefresh ?? false
|
|
23141
|
+
});
|
|
23142
|
+
const dateField = reportInfo.dateField?.field;
|
|
23143
|
+
if (!isAllTime && dateField !== void 0 && reportInfo.rows.length > 0) {
|
|
23144
|
+
const cleanedDateField = removeQuotes(dateField);
|
|
23145
|
+
const missingDateFieldCount = reportInfo.rows.some((row) => row[cleanedDateField] === void 0);
|
|
23146
|
+
if (missingDateFieldCount) {
|
|
23147
|
+
this.uncacheableReportIDs.push(reportId);
|
|
23148
|
+
return EMPTY_INTERNAL_REPORT;
|
|
23149
|
+
}
|
|
23150
|
+
}
|
|
23151
|
+
const requiredFilterFields = adjusted.flatMap((x, idx) => {
|
|
23152
|
+
if (idx === dateFilterIndex || !x.values && !x.selectedValue) return [];
|
|
23153
|
+
return removeQuotes(x.field);
|
|
23154
|
+
});
|
|
23155
|
+
const missingFields = [...new Set(requiredFilterFields.filter(
|
|
23156
|
+
(field) => reportInfo?.rows.some((row) => row[field] === void 0)
|
|
23157
|
+
))];
|
|
23158
|
+
if (missingFields.length > 0) {
|
|
23159
|
+
this.uncacheableReportIDs.push(reportId);
|
|
23160
|
+
return EMPTY_INTERNAL_REPORT;
|
|
23161
|
+
}
|
|
23162
|
+
const cacheKey = this.getCacheKey(reportId, tenants);
|
|
23163
|
+
if (isAllTime) {
|
|
23164
|
+
this.fetchedRange[cacheKey] = { start: /* @__PURE__ */ new Date(0), end: /* @__PURE__ */ new Date(), fetchedAtUTCMS: Date.now(), allTimeDoneBefore: true };
|
|
23165
|
+
} else {
|
|
23166
|
+
const existing = this.fetchedRange[cacheKey];
|
|
23167
|
+
if (existing && !forceRefresh) {
|
|
23168
|
+
const oldStart = existing.start;
|
|
23169
|
+
const oldEnd = existing.end;
|
|
23170
|
+
this.fetchedRange[cacheKey] = { start: getMinDate(oldStart, s), end: getMaxDate(oldEnd, e), fetchedAtUTCMS: Date.now(), allTimeDoneBefore: false };
|
|
23171
|
+
} else {
|
|
23172
|
+
this.fetchedRange[cacheKey] = { start: s, end: e, fetchedAtUTCMS: Date.now(), allTimeDoneBefore: false };
|
|
23173
|
+
}
|
|
23174
|
+
}
|
|
23175
|
+
} catch (error) {
|
|
23176
|
+
console.warn(error);
|
|
23177
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
23178
|
+
throw error;
|
|
23179
|
+
}
|
|
23180
|
+
}
|
|
23181
|
+
return reportInfo || EMPTY_INTERNAL_REPORT;
|
|
23182
|
+
}
|
|
23183
|
+
async applyPivotsAndFilters(report, dashboardFilters, customFilters, pivot, tenantPart, useCache = true) {
|
|
23184
|
+
const datasetVersion = this.fetchedRange[report.id + tenantPart]?.fetchedAtUTCMS ?? 0;
|
|
23185
|
+
const keyParts = [
|
|
23186
|
+
report.queryString,
|
|
23187
|
+
tenantPart,
|
|
23188
|
+
datasetVersion,
|
|
23189
|
+
// prevents fetching stale filters on hard refresh
|
|
23190
|
+
hashString(stableStringify(dashboardFilters)),
|
|
23191
|
+
hashString(stableStringify(customFilters))
|
|
23192
|
+
];
|
|
23193
|
+
const queryKey = this.DATA_PREFIX + keyParts.join("|");
|
|
23194
|
+
let filtersApplied;
|
|
23195
|
+
if (useCache) {
|
|
23196
|
+
try {
|
|
23197
|
+
const cache = await this.storage.getItem(queryKey);
|
|
23198
|
+
if (cache) {
|
|
23199
|
+
filtersApplied = JSON.parse(cache);
|
|
23200
|
+
}
|
|
23201
|
+
} catch {
|
|
23202
|
+
}
|
|
23203
|
+
}
|
|
23204
|
+
if (!filtersApplied) {
|
|
23205
|
+
const dateIndex = dashboardFilters.findIndex((x) => x.filterType === "date_range");
|
|
23206
|
+
const requiredFilterFields = dashboardFilters.flatMap((x, idx) => {
|
|
23207
|
+
if (idx === dateIndex || !x.values?.length && !x.selectedValue) return [];
|
|
23208
|
+
return removeQuotes(x.field);
|
|
23209
|
+
});
|
|
23210
|
+
const missingFields = [...new Set(requiredFilterFields.filter(
|
|
23211
|
+
(field) => report.rows.some((row) => row[field] === void 0)
|
|
23212
|
+
))];
|
|
23213
|
+
if (missingFields.length > 0) {
|
|
23214
|
+
this.uncacheableReportIDs.push(report.id);
|
|
23215
|
+
return [];
|
|
23216
|
+
}
|
|
23217
|
+
const dbDateFilter = dashboardFilters.find((x) => x.filterType === "date_range");
|
|
23218
|
+
if (report.dateField && dbDateFilter?.startDate) {
|
|
23219
|
+
const { start: startDate, end: endDate } = normalizePSTRanges(
|
|
23220
|
+
new Date(dbDateFilter.startDate),
|
|
23221
|
+
dbDateFilter.endDate ? new Date(dbDateFilter.endDate) : void 0
|
|
23222
|
+
);
|
|
23223
|
+
const fieldToUse = report.rows[0] && report.rows[0]["__quillRawDate"] ? "__quillRawDate" : removeQuotes(report.dateField.field);
|
|
23224
|
+
const dateFilteredRows = report.rows.filter((x) => {
|
|
23225
|
+
const rowDate = new Date(x[fieldToUse]);
|
|
23226
|
+
return startDate <= rowDate && (endDate ? rowDate <= endDate : true);
|
|
23227
|
+
});
|
|
23228
|
+
filtersApplied = applyFiltersInMemory(dateFilteredRows, [], { dashboardFilters, customFilters });
|
|
23229
|
+
} else {
|
|
23230
|
+
filtersApplied = applyFiltersInMemory(report.rows, [], { dashboardFilters, customFilters });
|
|
23231
|
+
}
|
|
23232
|
+
}
|
|
23233
|
+
try {
|
|
23234
|
+
await this.storage.setItem(queryKey, JSON.stringify(filtersApplied));
|
|
23235
|
+
} catch {
|
|
23236
|
+
}
|
|
23237
|
+
const withPivot = applyPivotInMemory(filtersApplied, pivot, dashboardFilters.concat(customFilters));
|
|
23238
|
+
return withPivot;
|
|
23239
|
+
}
|
|
23240
|
+
getCacheKey(reportId, tenants) {
|
|
23241
|
+
const tenantPart = tenants ? JSON.stringify(tenants) : "";
|
|
23242
|
+
return reportId + tenantPart;
|
|
23243
|
+
}
|
|
23244
|
+
getUncacheableRequestKey(reportId, client, tenants, flags, filters, additionalProcessing, pivot) {
|
|
23245
|
+
const canonicalFilters = filters.map(
|
|
23246
|
+
(f) => canonicalizeFilterForUncacheableKey(f)
|
|
23247
|
+
);
|
|
23248
|
+
const keyParts = [
|
|
23249
|
+
reportId,
|
|
23250
|
+
client.publicKey,
|
|
23251
|
+
client.databaseType,
|
|
23252
|
+
hashString(stableStringify(canonicalizeForKey(tenants ?? null))),
|
|
23253
|
+
hashString(stableStringify(canonicalizeForKey(flags ?? null))),
|
|
23254
|
+
hashString(stableStringify(canonicalFilters)),
|
|
23255
|
+
hashString(stableStringify(canonicalizeForKey(additionalProcessing ?? null))),
|
|
23256
|
+
hashString(stableStringify(canonicalizeForKey(pivot ?? null)))
|
|
23257
|
+
];
|
|
23258
|
+
return this.UNCACHEABLE_PREFIX + keyParts.join("|");
|
|
23259
|
+
}
|
|
23260
|
+
async loadMetaFromStorage() {
|
|
23261
|
+
const meta = await this.storage.getItem(this.META_KEY);
|
|
23262
|
+
if (!meta) return;
|
|
23263
|
+
try {
|
|
23264
|
+
const parsed = JSON.parse(meta);
|
|
23265
|
+
this.cachedReportIds = parsed.cached || [];
|
|
23266
|
+
this.uncacheableReportIDs = parsed.cannotBeCached;
|
|
23267
|
+
this.fetchedRange = Object.fromEntries(
|
|
23268
|
+
Object.entries(parsed.fetchedRange || {}).map(([id2, range]) => [
|
|
23269
|
+
id2,
|
|
23270
|
+
{ ...range, start: new Date(range.start), end: new Date(range.end) }
|
|
23271
|
+
])
|
|
23272
|
+
);
|
|
23273
|
+
} catch (err) {
|
|
23274
|
+
console.warn("CacheCab: could not parse meta from storage", err);
|
|
23275
|
+
}
|
|
23276
|
+
}
|
|
23277
|
+
async persistMetaToStorage() {
|
|
23278
|
+
const serializableRange = Object.fromEntries(
|
|
23279
|
+
Object.entries(this.fetchedRange).map(([id2, range]) => [
|
|
23280
|
+
id2,
|
|
23281
|
+
{ ...range }
|
|
23282
|
+
])
|
|
23283
|
+
);
|
|
23284
|
+
await this.storage.setItem(
|
|
23285
|
+
this.META_KEY,
|
|
23286
|
+
JSON.stringify({
|
|
23287
|
+
fetchedRange: serializableRange,
|
|
23288
|
+
cached: this.cachedReportIds,
|
|
23289
|
+
cannotBeCached: this.uncacheableReportIDs
|
|
23290
|
+
})
|
|
23291
|
+
);
|
|
23292
|
+
}
|
|
23293
|
+
};
|
|
23294
|
+
var MemoryStorage = class {
|
|
23295
|
+
store = /* @__PURE__ */ new Map();
|
|
23296
|
+
async getItem(key) {
|
|
23297
|
+
return this.store.get(key) ?? null;
|
|
23298
|
+
}
|
|
23299
|
+
async setItem(key, value) {
|
|
23300
|
+
this.store.set(key, value);
|
|
23301
|
+
}
|
|
23302
|
+
};
|
|
23303
|
+
var DB_NAME = "quill.cachecab";
|
|
23304
|
+
var STORE_NAME = "kv";
|
|
23305
|
+
var IdbStorage = class {
|
|
23306
|
+
dbPromise;
|
|
23307
|
+
constructor() {
|
|
23308
|
+
this.dbPromise = openDB(DB_NAME, 1, {
|
|
23309
|
+
upgrade(db) {
|
|
23310
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
23311
|
+
db.createObjectStore(STORE_NAME);
|
|
23312
|
+
}
|
|
23313
|
+
}
|
|
23314
|
+
});
|
|
23315
|
+
}
|
|
23316
|
+
async getItem(key) {
|
|
23317
|
+
const db = await this.dbPromise;
|
|
23318
|
+
return await db.get(STORE_NAME, key) ?? null;
|
|
23319
|
+
}
|
|
23320
|
+
async setItem(key, value) {
|
|
23321
|
+
const db = await this.dbPromise;
|
|
23322
|
+
await db.put(STORE_NAME, value, key);
|
|
23323
|
+
}
|
|
23324
|
+
};
|
|
23325
|
+
function removeQuotes(str) {
|
|
23326
|
+
return str.replace(/^['"]|['"]$/g, "");
|
|
23327
|
+
}
|
|
23328
|
+
function getMaxDate(d1, d2) {
|
|
23329
|
+
return d1 > d2 ? d1 : d2;
|
|
23330
|
+
}
|
|
23331
|
+
function getMinDate(d1, d2) {
|
|
23332
|
+
return d2 > d1 ? d1 : d2;
|
|
23333
|
+
}
|
|
23334
|
+
function hashString(str) {
|
|
23335
|
+
let h1 = 3735928559 ^ 0, h2 = 1103547991 ^ 0;
|
|
23336
|
+
for (let i = 0, ch; i < str.length; i++) {
|
|
23337
|
+
ch = str.charCodeAt(i);
|
|
23338
|
+
h1 = Math.imul(h1 ^ ch, 2654435761);
|
|
23339
|
+
h2 = Math.imul(h2 ^ ch, 1597334677);
|
|
23340
|
+
}
|
|
23341
|
+
h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909);
|
|
23342
|
+
h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909);
|
|
23343
|
+
return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(36);
|
|
23344
|
+
}
|
|
23345
|
+
function filterNewRows(existingRows, newRows) {
|
|
23346
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23347
|
+
const getKey = (row) => stableStringify(row);
|
|
23348
|
+
existingRows.forEach((row) => seen.add(getKey(row)));
|
|
23349
|
+
return newRows.filter((row) => {
|
|
23350
|
+
const k = getKey(row);
|
|
23351
|
+
if (seen.has(k)) return false;
|
|
23352
|
+
seen.add(k);
|
|
23353
|
+
return true;
|
|
23354
|
+
});
|
|
23355
|
+
}
|
|
23356
|
+
function stableStringify(obj) {
|
|
23357
|
+
if (obj === null || typeof obj !== "object") return JSON.stringify(obj);
|
|
23358
|
+
if (Array.isArray(obj)) {
|
|
23359
|
+
return `[${obj.map(stableStringify).join(",")}]`;
|
|
23360
|
+
}
|
|
23361
|
+
const keys = Object.keys(obj).sort();
|
|
23362
|
+
return `{${keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",")}}`;
|
|
23363
|
+
}
|
|
23364
|
+
function canonicalizeForKey(value) {
|
|
23365
|
+
if (value instanceof Date) {
|
|
23366
|
+
return value.toISOString();
|
|
23367
|
+
}
|
|
23368
|
+
if (Array.isArray(value)) {
|
|
23369
|
+
return value.map(canonicalizeForKey);
|
|
23370
|
+
}
|
|
23371
|
+
if (value && typeof value === "object") {
|
|
23372
|
+
const out = {};
|
|
23373
|
+
Object.keys(value).sort().forEach((key) => {
|
|
23374
|
+
if (value[key] !== void 0) {
|
|
23375
|
+
out[key] = canonicalizeForKey(value[key]);
|
|
23376
|
+
}
|
|
23377
|
+
});
|
|
23378
|
+
return out;
|
|
23379
|
+
}
|
|
23380
|
+
return value;
|
|
23381
|
+
}
|
|
23382
|
+
function canonicalizeFilterForUncacheableKey(filter) {
|
|
23383
|
+
const raw = canonicalizeForKey(filter) ?? {};
|
|
23384
|
+
const base = {
|
|
23385
|
+
filterType: raw.filterType,
|
|
23386
|
+
field: raw.field,
|
|
23387
|
+
table: raw.table,
|
|
23388
|
+
label: raw.label,
|
|
23389
|
+
operator: raw.operator
|
|
23390
|
+
};
|
|
23391
|
+
if (raw.selectedValue !== void 0) {
|
|
23392
|
+
base.selectedValue = raw.selectedValue;
|
|
23393
|
+
}
|
|
23394
|
+
if (Array.isArray(raw.values)) {
|
|
23395
|
+
base.values = [...raw.values].map(canonicalizeForKey).sort();
|
|
23396
|
+
}
|
|
23397
|
+
if (raw.value !== void 0) {
|
|
23398
|
+
base.value = canonicalizeForKey(raw.value);
|
|
23399
|
+
}
|
|
23400
|
+
if (raw.filterType === "date_range") {
|
|
23401
|
+
const { start: start2, end } = normalizePSTRanges(
|
|
23402
|
+
raw.startDate ? new Date(raw.startDate) : void 0,
|
|
23403
|
+
raw.endDate ? new Date(raw.endDate) : void 0
|
|
23404
|
+
);
|
|
23405
|
+
base.startDate = start2 ? start2.toISOString() : void 0;
|
|
23406
|
+
base.endDate = end ? end.toISOString() : void 0;
|
|
23407
|
+
base.primaryRange = raw.primaryRange?.value;
|
|
23408
|
+
base.comparisonRange = raw.comparisonRange?.value;
|
|
23409
|
+
}
|
|
23410
|
+
return canonicalizeForKey(base);
|
|
23411
|
+
}
|
|
23412
|
+
function startOfDayPST(date) {
|
|
23413
|
+
const pstDate = utcToZonedTime2(date, TZ);
|
|
23414
|
+
const startPst = startOfDay4(pstDate);
|
|
23415
|
+
return zonedTimeToUtc(startPst, TZ);
|
|
23416
|
+
}
|
|
23417
|
+
function endOfDayPST(date) {
|
|
23418
|
+
const pstDate = utcToZonedTime2(date, TZ);
|
|
23419
|
+
const endPst = endOfDay3(pstDate);
|
|
23420
|
+
return zonedTimeToUtc(endPst, TZ);
|
|
23421
|
+
}
|
|
23422
|
+
function normalizePSTRanges(start2, end) {
|
|
23423
|
+
return {
|
|
23424
|
+
start: start2 ? startOfDayPST(start2) : void 0,
|
|
23425
|
+
end: end ? endOfDayPST(end) : void 0
|
|
23426
|
+
};
|
|
23427
|
+
}
|
|
23428
|
+
|
|
23429
|
+
// src/Context.tsx
|
|
21603
23430
|
import { jsx } from "react/jsx-runtime";
|
|
21604
23431
|
var dummySetter = () => {
|
|
21605
23432
|
};
|
|
@@ -21931,7 +23758,9 @@ var ReportFiltersContext = createContext({
|
|
|
21931
23758
|
loadFiltersForReport: async () => {
|
|
21932
23759
|
},
|
|
21933
23760
|
abortLoadingFilters: () => {
|
|
21934
|
-
}
|
|
23761
|
+
},
|
|
23762
|
+
customFiltersLoaded: false,
|
|
23763
|
+
setCustomFiltersLoaded: dummySetter
|
|
21935
23764
|
});
|
|
21936
23765
|
var customDashboardFiltersReducer = (state, action) => {
|
|
21937
23766
|
switch (action.type) {
|
|
@@ -22021,6 +23850,9 @@ var FetchContext = createContext({
|
|
|
22021
23850
|
var EventTrackingContext = createContext({
|
|
22022
23851
|
eventTracking: null
|
|
22023
23852
|
});
|
|
23853
|
+
var CacheCabContext = createContext({
|
|
23854
|
+
getCacheCab: (storageType) => new CacheCab({ storageType })
|
|
23855
|
+
});
|
|
22024
23856
|
var ContextProvider = ({
|
|
22025
23857
|
children,
|
|
22026
23858
|
initialTheme,
|
|
@@ -22034,6 +23866,14 @@ var ContextProvider = ({
|
|
|
22034
23866
|
getAuthorizationToken = async () => "",
|
|
22035
23867
|
eventTracking = null
|
|
22036
23868
|
}) => {
|
|
23869
|
+
const cacheCabByTypeRef = useRef({});
|
|
23870
|
+
const getCacheCab = useCallback((storageType) => {
|
|
23871
|
+
const key = storageType === "idb" ? "idb" : "memory";
|
|
23872
|
+
if (!cacheCabByTypeRef.current[key]) {
|
|
23873
|
+
cacheCabByTypeRef.current[key] = new CacheCab({ storageType: key });
|
|
23874
|
+
}
|
|
23875
|
+
return cacheCabByTypeRef.current[key];
|
|
23876
|
+
}, []);
|
|
22037
23877
|
const [client, setClient] = useState(
|
|
22038
23878
|
typeof window !== "undefined" && sessionStorage ? JSON.parse(sessionStorage.getItem("quill-client") ?? "null") : null
|
|
22039
23879
|
);
|
|
@@ -22096,6 +23936,7 @@ var ContextProvider = ({
|
|
|
22096
23936
|
reportFiltersReducer,
|
|
22097
23937
|
{}
|
|
22098
23938
|
);
|
|
23939
|
+
const [customFiltersLoaded, setCustomFiltersLoaded] = useState(false);
|
|
22099
23940
|
const reportFilterOptionsAbortControllers = useRef({});
|
|
22100
23941
|
const [reports, reportsDispatch] = useReducer(reportsReducer, {});
|
|
22101
23942
|
const [reportsLoadingState, reportsLoadingStateDispatch] = useReducer(
|
|
@@ -22119,6 +23960,11 @@ var ContextProvider = ({
|
|
|
22119
23960
|
const viewerTenantsByOwnerRequests = useRef(/* @__PURE__ */ new Set());
|
|
22120
23961
|
const mappedTenantsRequests = useRef(/* @__PURE__ */ new Set());
|
|
22121
23962
|
const loadDashboardProcessId = useRef({});
|
|
23963
|
+
useEffect(() => {
|
|
23964
|
+
if (Object.keys(customReportFilters).length) {
|
|
23965
|
+
setCustomFiltersLoaded(true);
|
|
23966
|
+
}
|
|
23967
|
+
}, [customReportFilters]);
|
|
22122
23968
|
useEffect(() => {
|
|
22123
23969
|
if (!theme) {
|
|
22124
23970
|
const populatedTheme = {
|
|
@@ -22887,6 +24733,7 @@ var ContextProvider = ({
|
|
|
22887
24733
|
...dashboard2,
|
|
22888
24734
|
dateFilter: dashboard2.dateFilter ? {
|
|
22889
24735
|
...dashboard2.dateFilter,
|
|
24736
|
+
initialCacheDateRange: dashboard2.initialCacheDateRange ? { ...dashboard2.initialCacheDateRange } : void 0,
|
|
22890
24737
|
presetOptions: dashboard2.dateFilter.presetOptions?.map(
|
|
22891
24738
|
(preset) => ({
|
|
22892
24739
|
...preset,
|
|
@@ -23229,6 +25076,7 @@ var ContextProvider = ({
|
|
|
23229
25076
|
...dashboard2,
|
|
23230
25077
|
dateFilter: dashboard2.dateFilter ? {
|
|
23231
25078
|
...dashboard2.dateFilter,
|
|
25079
|
+
initialCacheDateRange: dashboard2.initialCacheDateRange ? { ...dashboard2.initialCacheDateRange } : void 0,
|
|
23232
25080
|
presetOptions: dashboard2.dateFilter.presetOptions?.map(
|
|
23233
25081
|
(preset) => ({
|
|
23234
25082
|
...preset,
|
|
@@ -23273,6 +25121,7 @@ var ContextProvider = ({
|
|
|
23273
25121
|
if (dashboard2.dateFilter) {
|
|
23274
25122
|
dashboard2.dateFilter = {
|
|
23275
25123
|
...dashboard2.dateFilter,
|
|
25124
|
+
initialCacheDateRange: dashboard2.initialCacheDateRange ? { ...dashboard2.initialCacheDateRange } : void 0,
|
|
23276
25125
|
startDate: presetOptions.find(
|
|
23277
25126
|
(elem) => elem.value === dashboard2.dateFilter.primaryRange?.value
|
|
23278
25127
|
)?.startDate,
|
|
@@ -23541,7 +25390,7 @@ var ContextProvider = ({
|
|
|
23541
25390
|
if (!theme) {
|
|
23542
25391
|
return null;
|
|
23543
25392
|
}
|
|
23544
|
-
return /* @__PURE__ */ jsx(
|
|
25393
|
+
return /* @__PURE__ */ jsx(CacheCabContext.Provider, { value: { getCacheCab }, children: /* @__PURE__ */ jsx(
|
|
23545
25394
|
ClientContext.Provider,
|
|
23546
25395
|
{
|
|
23547
25396
|
value: [
|
|
@@ -23582,7 +25431,9 @@ var ContextProvider = ({
|
|
|
23582
25431
|
reportFiltersDispatch,
|
|
23583
25432
|
customReportFiltersDispatch,
|
|
23584
25433
|
loadFiltersForReport,
|
|
23585
|
-
abortLoadingFilters
|
|
25434
|
+
abortLoadingFilters,
|
|
25435
|
+
customFiltersLoaded,
|
|
25436
|
+
setCustomFiltersLoaded
|
|
23586
25437
|
},
|
|
23587
25438
|
children: /* @__PURE__ */ jsx(
|
|
23588
25439
|
ReportsContext.Provider,
|
|
@@ -23625,7 +25476,7 @@ var ContextProvider = ({
|
|
|
23625
25476
|
}
|
|
23626
25477
|
) })
|
|
23627
25478
|
}
|
|
23628
|
-
);
|
|
25479
|
+
) });
|
|
23629
25480
|
};
|
|
23630
25481
|
|
|
23631
25482
|
// src/hooks/useExport.tsx
|
|
@@ -23644,12 +25495,12 @@ init_filterProcessing();
|
|
|
23644
25495
|
init_columnType();
|
|
23645
25496
|
import {
|
|
23646
25497
|
add,
|
|
23647
|
-
startOfDay as
|
|
23648
|
-
startOfMonth as
|
|
23649
|
-
startOfWeek as
|
|
23650
|
-
startOfYear
|
|
25498
|
+
startOfDay as startOfDay5,
|
|
25499
|
+
startOfMonth as startOfMonth3,
|
|
25500
|
+
startOfWeek as startOfWeek4,
|
|
25501
|
+
startOfYear as startOfYear2
|
|
23651
25502
|
} from "date-fns";
|
|
23652
|
-
import { utcToZonedTime as
|
|
25503
|
+
import { utcToZonedTime as utcToZonedTime3 } from "date-fns-tz";
|
|
23653
25504
|
function mergeComparisonRange(resp) {
|
|
23654
25505
|
if (resp.chartType === "table") return resp;
|
|
23655
25506
|
const compRows = resp.compareRows;
|
|
@@ -23692,6 +25543,18 @@ var useDashboardInternal = (dashboardName, customFilters) => {
|
|
|
23692
25543
|
(f) => f.filter
|
|
23693
25544
|
) : null;
|
|
23694
25545
|
}, [dashboardFilters, dashboardName]);
|
|
25546
|
+
const getExistingDateFilter = useMemo2(
|
|
25547
|
+
() => (name2) => {
|
|
25548
|
+
if (!name2) return void 0;
|
|
25549
|
+
const filtersForDashboard = dashboardFilters[name2];
|
|
25550
|
+
if (!filtersForDashboard) return void 0;
|
|
25551
|
+
const entry = Object.values(filtersForDashboard).find(
|
|
25552
|
+
(f) => f?.filter?.filterType === "date_range" /* Date */
|
|
25553
|
+
);
|
|
25554
|
+
return entry?.filter;
|
|
25555
|
+
},
|
|
25556
|
+
[dashboardFilters]
|
|
25557
|
+
);
|
|
23695
25558
|
useEffect2(() => {
|
|
23696
25559
|
if (!dashboardName) return;
|
|
23697
25560
|
if (backfilledDashboards.current.has(dashboardName)) return;
|
|
@@ -23729,7 +25592,7 @@ var useDashboardInternal = (dashboardName, customFilters) => {
|
|
|
23729
25592
|
customFilters
|
|
23730
25593
|
);
|
|
23731
25594
|
}, [dashboardName, loading, dashboardConfig, dashboardFilters]);
|
|
23732
|
-
const handleReload = async (overrideDashboardName, fetchFromServer = false, reportAction, overrideFilters) => {
|
|
25595
|
+
const handleReload = async (overrideDashboardName, fetchFromServer = false, reportAction, overrideFilters, options) => {
|
|
23733
25596
|
if (!dashboardName) return;
|
|
23734
25597
|
if (overrideFilters) {
|
|
23735
25598
|
const dateFilter2 = overrideFilters.filters.find(
|
|
@@ -23782,10 +25645,19 @@ var useDashboardInternal = (dashboardName, customFilters) => {
|
|
|
23782
25645
|
Object.values(dashboard?.sections ?? {}).flat(),
|
|
23783
25646
|
dashboardName
|
|
23784
25647
|
) : void 0;
|
|
25648
|
+
const existingDateFilter = options?.preserveExistingDateFilter ? getExistingDateFilter(dashboardName) : void 0;
|
|
25649
|
+
const mergedDateFilter = dateFilter && existingDateFilter ? {
|
|
25650
|
+
...dateFilter,
|
|
25651
|
+
startDate: existingDateFilter.startDate ?? dateFilter.startDate,
|
|
25652
|
+
endDate: existingDateFilter.endDate ?? dateFilter.endDate,
|
|
25653
|
+
preset: existingDateFilter.preset ?? dateFilter.preset,
|
|
25654
|
+
primaryRange: existingDateFilter.primaryRange ?? dateFilter.primaryRange,
|
|
25655
|
+
comparisonRange: existingDateFilter.comparisonRange ?? dateFilter.comparisonRange
|
|
25656
|
+
} : dateFilter ?? existingDateFilter;
|
|
23785
25657
|
loadFiltersForDashboard(
|
|
23786
25658
|
dashboardName,
|
|
23787
25659
|
[
|
|
23788
|
-
...
|
|
25660
|
+
...mergedDateFilter ? [mergedDateFilter] : [],
|
|
23789
25661
|
...updatedDashboard?.filters?.map((filter) => ({
|
|
23790
25662
|
...filter,
|
|
23791
25663
|
query: void 0
|
|
@@ -24070,7 +25942,8 @@ var useDashboards = () => {
|
|
|
24070
25942
|
tenantFilters,
|
|
24071
25943
|
dateFilter,
|
|
24072
25944
|
customFilters,
|
|
24073
|
-
tenantKeys
|
|
25945
|
+
tenantKeys,
|
|
25946
|
+
initialCacheDateRange
|
|
24074
25947
|
}) => {
|
|
24075
25948
|
if (!client) return;
|
|
24076
25949
|
if (tenantKeys?.some((key) => !key)) {
|
|
@@ -24091,6 +25964,7 @@ var useDashboards = () => {
|
|
|
24091
25964
|
filters,
|
|
24092
25965
|
tenantFilters,
|
|
24093
25966
|
dateFilter: dateFilter ?? null,
|
|
25967
|
+
initialCacheDateRange,
|
|
24094
25968
|
name: name2.trim(),
|
|
24095
25969
|
task: "edit-dashboard",
|
|
24096
25970
|
clientId: client.clientId,
|
|
@@ -24302,7 +26176,9 @@ var useDashboards = () => {
|
|
|
24302
26176
|
};
|
|
24303
26177
|
};
|
|
24304
26178
|
var useDashboard = (dashboardName, config) => {
|
|
26179
|
+
const logCacheStatistics = config?.showCacheLogs || false;
|
|
24305
26180
|
const { data, dashboardFilters, reload, isLoading } = useDashboardInternal(dashboardName);
|
|
26181
|
+
const [lastUpdated, setLastUpdated] = useState2(0);
|
|
24306
26182
|
const { customFilterDispatch } = useContext(DashboardFiltersContext);
|
|
24307
26183
|
const { reportsDispatch, reportsLoadingStateDispatch } = useContext(ReportsContext);
|
|
24308
26184
|
const initialLoad = useRef2(true);
|
|
@@ -24311,15 +26187,19 @@ var useDashboard = (dashboardName, config) => {
|
|
|
24311
26187
|
const [client] = useContext(ClientContext);
|
|
24312
26188
|
const { tenants, flags } = useContext(TenantContext);
|
|
24313
26189
|
const { getToken } = useContext(FetchContext);
|
|
24314
|
-
const { customReportFilters } = useContext(ReportFiltersContext);
|
|
26190
|
+
const { customReportFilters, customFiltersLoaded, setCustomFiltersLoaded } = useContext(ReportFiltersContext);
|
|
24315
26191
|
const { eventTracking } = useContext(EventTrackingContext);
|
|
24316
|
-
const
|
|
26192
|
+
const { getCacheCab } = useContext(CacheCabContext);
|
|
24317
26193
|
const reportRequestIds = useRef2({});
|
|
24318
26194
|
const lastDashboardName = useRef2(null);
|
|
24319
26195
|
const pendingNameChangeReload = useRef2(false);
|
|
24320
|
-
|
|
24321
|
-
|
|
24322
|
-
|
|
26196
|
+
const [loadedDashes, setLoadedDashes] = useState2([]);
|
|
26197
|
+
const [lastUpdatedDict, setLastUpdatedDict] = useState2({});
|
|
26198
|
+
const cacheEnabled = config?.cacheEnabled ?? true;
|
|
26199
|
+
const cacheCab = useMemo2(
|
|
26200
|
+
() => getCacheCab(config?.cacheType),
|
|
26201
|
+
[getCacheCab, config?.cacheType]
|
|
26202
|
+
);
|
|
24323
26203
|
useEffect2(() => {
|
|
24324
26204
|
const nameChanged = dashboardName !== lastDashboardName.current;
|
|
24325
26205
|
if (nameChanged) {
|
|
@@ -24329,19 +26209,29 @@ var useDashboard = (dashboardName, config) => {
|
|
|
24329
26209
|
backfilledDashboards.current = false;
|
|
24330
26210
|
reportRequestIds.current = {};
|
|
24331
26211
|
pendingNameChangeReload.current = true;
|
|
26212
|
+
if (customFiltersLoaded && !loadedDashes.includes(dashboardName)) {
|
|
26213
|
+
setCustomFiltersLoaded(false);
|
|
26214
|
+
}
|
|
26215
|
+
setLastUpdated(lastUpdatedDict[dashboardName] || 0);
|
|
24332
26216
|
}
|
|
24333
26217
|
if (!dashboardName) return;
|
|
24334
26218
|
if (pendingNameChangeReload.current && data) {
|
|
24335
26219
|
pendingNameChangeReload.current = false;
|
|
24336
26220
|
initialLoad.current = false;
|
|
26221
|
+
fetchedInitialReports.current = false;
|
|
24337
26222
|
return;
|
|
24338
26223
|
}
|
|
24339
26224
|
if (pendingNameChangeReload.current && !isLoading && !data && initialLoad.current) {
|
|
24340
26225
|
initialLoad.current = false;
|
|
24341
26226
|
pendingNameChangeReload.current = false;
|
|
24342
|
-
reload(
|
|
26227
|
+
reload(dashboardName, false, void 0, void 0, {
|
|
26228
|
+
preserveExistingDateFilter: true
|
|
26229
|
+
});
|
|
24343
26230
|
}
|
|
24344
26231
|
}, [isLoading, data, dashboardName]);
|
|
26232
|
+
useEffect2(() => {
|
|
26233
|
+
setLastUpdated(lastUpdatedDict[dashboardName] || 0);
|
|
26234
|
+
}, [lastUpdatedDict, dashboardName]);
|
|
24345
26235
|
useEffect2(() => {
|
|
24346
26236
|
if (backfilledDashboards.current) return;
|
|
24347
26237
|
if (isLoading || !data) return;
|
|
@@ -24350,7 +26240,9 @@ var useDashboard = (dashboardName, config) => {
|
|
|
24350
26240
|
);
|
|
24351
26241
|
if (!needsBackfill) return;
|
|
24352
26242
|
backfilledDashboards.current = true;
|
|
24353
|
-
reload(dashboardName, false
|
|
26243
|
+
reload(dashboardName, false, void 0, void 0, {
|
|
26244
|
+
preserveExistingDateFilter: true
|
|
26245
|
+
});
|
|
24354
26246
|
}, [isLoading, data, dashboardFilters, dashboardName]);
|
|
24355
26247
|
const { allReportsById } = useAllReports();
|
|
24356
26248
|
const sections = useMemo2(() => {
|
|
@@ -24374,7 +26266,13 @@ var useDashboard = (dashboardName, config) => {
|
|
|
24374
26266
|
fetchedInitialReports.current = true;
|
|
24375
26267
|
fetchReports([], dashboardFilters ?? [], config?.pageSize);
|
|
24376
26268
|
}
|
|
24377
|
-
}, [fetchedInitialReports, data, dashboardFilters]);
|
|
26269
|
+
}, [fetchedInitialReports, data, dashboardFilters, customFiltersLoaded]);
|
|
26270
|
+
useEffect2(() => {
|
|
26271
|
+
if (customFiltersLoaded && data && dashboardFilters !== null) {
|
|
26272
|
+
fetchedInitialReports.current = true;
|
|
26273
|
+
fetchReports([], dashboardFilters ?? [], config?.pageSize);
|
|
26274
|
+
}
|
|
26275
|
+
}, [customFiltersLoaded]);
|
|
24378
26276
|
const applyDashboardFilters = (filtersToUpdate) => {
|
|
24379
26277
|
const newFilters = (dashboardFilters ?? []).map((f) => {
|
|
24380
26278
|
const update = filtersToUpdate.find((u) => u.label === f.label);
|
|
@@ -24453,7 +26351,7 @@ var useDashboard = (dashboardName, config) => {
|
|
|
24453
26351
|
});
|
|
24454
26352
|
return internalFilters;
|
|
24455
26353
|
};
|
|
24456
|
-
const
|
|
26354
|
+
const isFilter2 = (f) => {
|
|
24457
26355
|
return f && typeof f === "object" && "filterType" in f && !("id" in f);
|
|
24458
26356
|
};
|
|
24459
26357
|
const isDashboardFilter = (f) => {
|
|
@@ -24461,29 +26359,22 @@ var useDashboard = (dashboardName, config) => {
|
|
|
24461
26359
|
};
|
|
24462
26360
|
const applyFilters = (filters2) => {
|
|
24463
26361
|
const dashboardFilters2 = filters2.filter(isDashboardFilter);
|
|
24464
|
-
const customFilters = filters2.filter(
|
|
26362
|
+
const customFilters = filters2.filter(isFilter2);
|
|
24465
26363
|
const newCustomFilters = applyCustomFilters(customFilters);
|
|
24466
26364
|
const newDashboardFilters = applyDashboardFilters(dashboardFilters2);
|
|
24467
26365
|
fetchReports(newCustomFilters, newDashboardFilters);
|
|
24468
26366
|
};
|
|
24469
|
-
const
|
|
24470
|
-
|
|
24471
|
-
|
|
24472
|
-
while (attempts < maxAttempts) {
|
|
24473
|
-
const filters2 = customFiltersRef.current[reportId];
|
|
24474
|
-
if (filters2 && filters2.length > 0) {
|
|
24475
|
-
return filters2;
|
|
24476
|
-
}
|
|
24477
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
24478
|
-
attempts++;
|
|
24479
|
-
}
|
|
24480
|
-
return [];
|
|
26367
|
+
const forceCacheRefresh = () => {
|
|
26368
|
+
if (!cacheEnabled) return;
|
|
26369
|
+
fetchReports([], dashboardFilters ?? [], config?.pageSize, true);
|
|
24481
26370
|
};
|
|
24482
|
-
const fetchReports = async (customFilters, dashboardFilters2, pageSize) => {
|
|
26371
|
+
const fetchReports = async (customFilters, dashboardFilters2, pageSize, forceCacheToRefresh = false) => {
|
|
24483
26372
|
if (!client || !sections) return;
|
|
24484
26373
|
const allReports = Object.values(sections).flat();
|
|
26374
|
+
const fetchStartTime = Date.now();
|
|
26375
|
+
let totalCached = 0;
|
|
24485
26376
|
await Promise.all(
|
|
24486
|
-
allReports.map(async (reportInfo) => {
|
|
26377
|
+
allReports.map(async (reportInfo, idx) => {
|
|
24487
26378
|
const reportId = reportInfo.id;
|
|
24488
26379
|
const requestId = (reportRequestIds.current[reportId] ?? 0) + 1;
|
|
24489
26380
|
reportRequestIds.current[reportId] = requestId;
|
|
@@ -24492,7 +26383,7 @@ var useDashboard = (dashboardName, config) => {
|
|
|
24492
26383
|
id: reportId,
|
|
24493
26384
|
data: true
|
|
24494
26385
|
});
|
|
24495
|
-
const customReportFiltersArray =
|
|
26386
|
+
const customReportFiltersArray = customReportFilters[reportId] ?? [];
|
|
24496
26387
|
let rowsPerRequest = pageSize || 600;
|
|
24497
26388
|
if (!pageSize && (reportInfo.chartType === "table" || reportInfo.chartType === "metric")) {
|
|
24498
26389
|
rowsPerRequest = 10;
|
|
@@ -24504,17 +26395,138 @@ var useDashboard = (dashboardName, config) => {
|
|
|
24504
26395
|
const additionalProcessing = {
|
|
24505
26396
|
page: pagination
|
|
24506
26397
|
};
|
|
24507
|
-
const usePivotTask = !!reportInfo.pivot;
|
|
26398
|
+
const usePivotTask = !cacheEnabled && !!reportInfo.pivot;
|
|
26399
|
+
const allFilters = dashboardFilters2.concat(customFilters).concat(customReportFiltersArray);
|
|
26400
|
+
if (cacheEnabled && cacheCab.isCacheable(reportId)) {
|
|
26401
|
+
const report2 = await cacheCab.get(reportId, dashboardFilters2, customFilters.concat(customReportFiltersArray), reportInfo.pivot, client, tenants, flags, pageSize, getToken, eventTracking, forceCacheToRefresh);
|
|
26402
|
+
if (reportRequestIds.current[reportId] !== requestId) {
|
|
26403
|
+
return null;
|
|
26404
|
+
}
|
|
26405
|
+
if (cacheCab.isCacheable(reportId)) {
|
|
26406
|
+
reportsDispatch({
|
|
26407
|
+
type: "UPDATE_REPORT",
|
|
26408
|
+
id: reportId,
|
|
26409
|
+
data: {
|
|
26410
|
+
...report2,
|
|
26411
|
+
pagination,
|
|
26412
|
+
triggerReload: false
|
|
26413
|
+
}
|
|
26414
|
+
});
|
|
26415
|
+
reportsLoadingStateDispatch({
|
|
26416
|
+
type: "SET_REPORT_LOADING",
|
|
26417
|
+
id: reportId,
|
|
26418
|
+
data: false
|
|
26419
|
+
});
|
|
26420
|
+
totalCached += 1;
|
|
26421
|
+
return report2;
|
|
26422
|
+
}
|
|
26423
|
+
}
|
|
26424
|
+
if (cacheEnabled && !cacheCab.isCacheable(reportId)) {
|
|
26425
|
+
try {
|
|
26426
|
+
const { report: uncacheableReport, fromCache } = await cacheCab.getOrFetchUncacheableResult(
|
|
26427
|
+
reportId,
|
|
26428
|
+
client,
|
|
26429
|
+
tenants,
|
|
26430
|
+
flags,
|
|
26431
|
+
allFilters,
|
|
26432
|
+
additionalProcessing,
|
|
26433
|
+
reportInfo.pivot,
|
|
26434
|
+
async () => {
|
|
26435
|
+
const { report: report2, error: error2 } = await fetchReport({
|
|
26436
|
+
reportId,
|
|
26437
|
+
client,
|
|
26438
|
+
tenants,
|
|
26439
|
+
flags,
|
|
26440
|
+
additionalProcessing,
|
|
26441
|
+
filters: allFilters,
|
|
26442
|
+
getToken,
|
|
26443
|
+
eventTracking,
|
|
26444
|
+
usePivotTask,
|
|
26445
|
+
overwriteCache: forceCacheToRefresh
|
|
26446
|
+
});
|
|
26447
|
+
if (error2 || !report2) {
|
|
26448
|
+
throw error2 ?? new Error("Failed to fetch uncacheable report");
|
|
26449
|
+
}
|
|
26450
|
+
return report2;
|
|
26451
|
+
},
|
|
26452
|
+
forceCacheToRefresh
|
|
26453
|
+
);
|
|
26454
|
+
if (reportRequestIds.current[reportId] !== requestId) {
|
|
26455
|
+
return null;
|
|
26456
|
+
}
|
|
26457
|
+
reportsDispatch({
|
|
26458
|
+
type: "UPDATE_REPORT",
|
|
26459
|
+
id: reportId,
|
|
26460
|
+
data: {
|
|
26461
|
+
...uncacheableReport,
|
|
26462
|
+
pagination,
|
|
26463
|
+
triggerReload: false
|
|
26464
|
+
}
|
|
26465
|
+
});
|
|
26466
|
+
reportsLoadingStateDispatch({
|
|
26467
|
+
type: "SET_REPORT_LOADING",
|
|
26468
|
+
id: reportId,
|
|
26469
|
+
data: false
|
|
26470
|
+
});
|
|
26471
|
+
if (fromCache) {
|
|
26472
|
+
totalCached += 1;
|
|
26473
|
+
}
|
|
26474
|
+
if (usePivotTask) {
|
|
26475
|
+
fetchReportRows({
|
|
26476
|
+
reportId,
|
|
26477
|
+
client,
|
|
26478
|
+
tenants,
|
|
26479
|
+
filters: allFilters,
|
|
26480
|
+
getToken,
|
|
26481
|
+
additionalProcessing,
|
|
26482
|
+
overwriteCache: forceCacheToRefresh
|
|
26483
|
+
}).then(({ rows, rowCount, columns, fields }) => {
|
|
26484
|
+
if (reportRequestIds.current[reportId] !== requestId) {
|
|
26485
|
+
return;
|
|
26486
|
+
}
|
|
26487
|
+
reportsDispatch({
|
|
26488
|
+
type: "UPDATE_REPORT",
|
|
26489
|
+
id: reportId,
|
|
26490
|
+
data: {
|
|
26491
|
+
rows,
|
|
26492
|
+
rowCount,
|
|
26493
|
+
columnInternal: columns,
|
|
26494
|
+
columns: columns.map((col) => ({
|
|
26495
|
+
field: col.field,
|
|
26496
|
+
format: col.format,
|
|
26497
|
+
label: col.label,
|
|
26498
|
+
inferFormat: col.inferFormat
|
|
26499
|
+
})),
|
|
26500
|
+
// @ts-ignore fields is not typed on QuillReportInternal
|
|
26501
|
+
fields,
|
|
26502
|
+
triggerReload: false
|
|
26503
|
+
}
|
|
26504
|
+
});
|
|
26505
|
+
}).catch((e) => {
|
|
26506
|
+
if (e instanceof Error && e.name === "AbortError") {
|
|
26507
|
+
return;
|
|
26508
|
+
}
|
|
26509
|
+
console.error("Failed to fetch background rows", e);
|
|
26510
|
+
});
|
|
26511
|
+
}
|
|
26512
|
+
return uncacheableReport;
|
|
26513
|
+
} catch (error2) {
|
|
26514
|
+
console.error(error2);
|
|
26515
|
+
return null;
|
|
26516
|
+
}
|
|
26517
|
+
}
|
|
24508
26518
|
const { report, error } = await fetchReport({
|
|
24509
26519
|
reportId,
|
|
24510
26520
|
client,
|
|
24511
26521
|
tenants,
|
|
24512
26522
|
flags,
|
|
24513
26523
|
additionalProcessing,
|
|
24514
|
-
filters:
|
|
26524
|
+
filters: allFilters,
|
|
24515
26525
|
getToken,
|
|
24516
26526
|
eventTracking,
|
|
24517
|
-
usePivotTask
|
|
26527
|
+
usePivotTask,
|
|
26528
|
+
overwriteCache: forceCacheToRefresh
|
|
26529
|
+
// usePivotTask: false,
|
|
24518
26530
|
});
|
|
24519
26531
|
if (error) {
|
|
24520
26532
|
console.error(error);
|
|
@@ -24542,9 +26554,10 @@ var useDashboard = (dashboardName, config) => {
|
|
|
24542
26554
|
reportId,
|
|
24543
26555
|
client,
|
|
24544
26556
|
tenants,
|
|
24545
|
-
filters:
|
|
26557
|
+
filters: allFilters,
|
|
24546
26558
|
getToken,
|
|
24547
|
-
additionalProcessing
|
|
26559
|
+
additionalProcessing,
|
|
26560
|
+
overwriteCache: forceCacheToRefresh
|
|
24548
26561
|
}).then(({ rows, rowCount, columns, fields }) => {
|
|
24549
26562
|
if (reportRequestIds.current[reportId] !== requestId) {
|
|
24550
26563
|
return;
|
|
@@ -24568,19 +26581,30 @@ var useDashboard = (dashboardName, config) => {
|
|
|
24568
26581
|
}
|
|
24569
26582
|
});
|
|
24570
26583
|
}).catch((e) => {
|
|
24571
|
-
if (e instanceof Error && e.name === "AbortError")
|
|
26584
|
+
if (e instanceof Error && e.name === "AbortError") {
|
|
26585
|
+
return;
|
|
26586
|
+
}
|
|
24572
26587
|
console.error("Failed to fetch background rows", e);
|
|
24573
26588
|
});
|
|
24574
26589
|
}
|
|
24575
26590
|
return report;
|
|
24576
26591
|
})
|
|
24577
26592
|
);
|
|
26593
|
+
if (!loadedDashes.includes(dashboardName) || !cacheEnabled || forceCacheToRefresh) {
|
|
26594
|
+
setLoadedDashes((prev) => prev.includes(dashboardName) ? prev : [...prev, dashboardName]);
|
|
26595
|
+
setLastUpdatedDict((prev) => ({ ...prev, [dashboardName]: Date.now() }));
|
|
26596
|
+
}
|
|
26597
|
+
if (logCacheStatistics) {
|
|
26598
|
+
console.log(`Dashboard "${dashboardName}": Cache Rate: ${(100 * totalCached / allReports.length).toFixed(1)}%, load time: ${((Date.now() - fetchStartTime) / 1e3).toFixed(2)} secs`);
|
|
26599
|
+
}
|
|
24578
26600
|
};
|
|
24579
26601
|
return {
|
|
24580
26602
|
isLoading: !!isLoading || !sections,
|
|
24581
26603
|
sections: isLoading ? null : sections,
|
|
24582
26604
|
filters,
|
|
24583
|
-
applyFilters
|
|
26605
|
+
applyFilters,
|
|
26606
|
+
lastUpdated,
|
|
26607
|
+
forceCacheRefresh
|
|
24584
26608
|
};
|
|
24585
26609
|
};
|
|
24586
26610
|
var useDashboardReportInternal = (reportId, config) => {
|
|
@@ -24604,15 +26628,6 @@ var useDashboardReportInternal = (reportId, config) => {
|
|
|
24604
26628
|
} = useDashboardInternal(reports[reportId]?.dashboardName ?? null);
|
|
24605
26629
|
const [pageLoading, setPageLoading] = useState2(false);
|
|
24606
26630
|
const [maxPage, setMaxPage] = useState2(0);
|
|
24607
|
-
useEffect2(() => {
|
|
24608
|
-
if (config?.initialFilters) {
|
|
24609
|
-
customReportFiltersDispatch({
|
|
24610
|
-
type: "ADD_CUSTOM_REPORT_FILTERS",
|
|
24611
|
-
reportId,
|
|
24612
|
-
data: config.initialFilters.map(convertCustomFilter)
|
|
24613
|
-
});
|
|
24614
|
-
}
|
|
24615
|
-
}, []);
|
|
24616
26631
|
const processedReport = useMemo2(() => {
|
|
24617
26632
|
if (!reports[reportId]) return null;
|
|
24618
26633
|
const dashboardName = reports[reportId].dashboardName;
|
|
@@ -24817,6 +26832,7 @@ var useDashboardReportInternal = (reportId, config) => {
|
|
|
24817
26832
|
};
|
|
24818
26833
|
var useDashboardReport = (reportId, config) => {
|
|
24819
26834
|
const { report, loading, applyFilters, deleteReport, nextPage } = useDashboardReportInternal(reportId, config);
|
|
26835
|
+
const { customReportFiltersDispatch } = useContext(ReportFiltersContext);
|
|
24820
26836
|
const fetchingRef = useRef2(false);
|
|
24821
26837
|
const fetchNextPage = async () => {
|
|
24822
26838
|
if (fetchingRef.current) {
|
|
@@ -24831,6 +26847,15 @@ var useDashboardReport = (reportId, config) => {
|
|
|
24831
26847
|
fetchingRef.current = false;
|
|
24832
26848
|
}
|
|
24833
26849
|
};
|
|
26850
|
+
useEffect2(() => {
|
|
26851
|
+
if (config?.initialFilters) {
|
|
26852
|
+
customReportFiltersDispatch({
|
|
26853
|
+
type: "ADD_CUSTOM_REPORT_FILTERS",
|
|
26854
|
+
reportId,
|
|
26855
|
+
data: config.initialFilters.map(convertCustomFilter)
|
|
26856
|
+
});
|
|
26857
|
+
}
|
|
26858
|
+
}, []);
|
|
24834
26859
|
return {
|
|
24835
26860
|
report,
|
|
24836
26861
|
isLoading: loading || fetchingRef.current,
|
|
@@ -27995,19 +30020,23 @@ var RenderLegend = ({
|
|
|
27995
30020
|
const seeAllMeasureRef = useRef5(null);
|
|
27996
30021
|
const seeAllTriggerRef = useRef5(null);
|
|
27997
30022
|
const itemRefs = useRef5([]);
|
|
27998
|
-
|
|
27999
|
-
const maxItems = limit ??
|
|
30023
|
+
const safePayload = payload ?? [];
|
|
30024
|
+
const maxItems = limit ?? safePayload.length;
|
|
28000
30025
|
const measuredLimit = visibleCount ?? maxItems;
|
|
28001
|
-
const visiblePayload =
|
|
30026
|
+
const visiblePayload = safePayload.slice(0, Math.min(maxItems, measuredLimit));
|
|
28002
30027
|
const handleOpen = () => setIsOpen(true);
|
|
28003
30028
|
const handleClose = () => setIsOpen(false);
|
|
28004
30029
|
useLayoutEffect2(() => {
|
|
28005
30030
|
if (!containerRef.current) return;
|
|
28006
|
-
if (!
|
|
30031
|
+
if (!safePayload.length) {
|
|
30032
|
+
setShowSeeAll(false);
|
|
30033
|
+
setVisibleCount(null);
|
|
30034
|
+
return;
|
|
30035
|
+
}
|
|
28007
30036
|
const updateVisibleCount = () => {
|
|
28008
30037
|
const containerWidth = containerRef.current?.offsetWidth ?? 0;
|
|
28009
30038
|
if (!containerWidth) return;
|
|
28010
|
-
const maxCount = Math.min(maxItems,
|
|
30039
|
+
const maxCount = Math.min(maxItems, safePayload.length);
|
|
28011
30040
|
const seeAllWidth = getOuterWidth(seeAllMeasureRef.current);
|
|
28012
30041
|
const computeCount = (reserveSeeAll) => {
|
|
28013
30042
|
const availableWidth = containerWidth - (reserveSeeAll ? seeAllWidth : 0);
|
|
@@ -28023,7 +30052,7 @@ var RenderLegend = ({
|
|
|
28023
30052
|
return Math.max(1, nextCount);
|
|
28024
30053
|
};
|
|
28025
30054
|
const countWithSeeAll = computeCount(true);
|
|
28026
|
-
const shouldShowSeeAll =
|
|
30055
|
+
const shouldShowSeeAll = safePayload.length > countWithSeeAll;
|
|
28027
30056
|
const finalCount = shouldShowSeeAll ? countWithSeeAll : computeCount(false);
|
|
28028
30057
|
setShowSeeAll(shouldShowSeeAll);
|
|
28029
30058
|
setVisibleCount(finalCount);
|
|
@@ -28032,7 +30061,8 @@ var RenderLegend = ({
|
|
|
28032
30061
|
const observer = new ResizeObserver(updateVisibleCount);
|
|
28033
30062
|
observer.observe(containerRef.current);
|
|
28034
30063
|
return () => observer.disconnect();
|
|
28035
|
-
}, [
|
|
30064
|
+
}, [safePayload.length, maxItems]);
|
|
30065
|
+
if (!safePayload.length) return null;
|
|
28036
30066
|
return /* @__PURE__ */ jsxs19(
|
|
28037
30067
|
"div",
|
|
28038
30068
|
{
|
|
@@ -28072,7 +30102,7 @@ var RenderLegend = ({
|
|
|
28072
30102
|
justifyContent: "flex-start",
|
|
28073
30103
|
flexWrap: "nowrap"
|
|
28074
30104
|
},
|
|
28075
|
-
children:
|
|
30105
|
+
children: safePayload.slice(0, maxItems).map((entry, index) => /* @__PURE__ */ jsx27(
|
|
28076
30106
|
"div",
|
|
28077
30107
|
{
|
|
28078
30108
|
ref: (element) => {
|
|
@@ -28161,7 +30191,7 @@ var RenderLegend = ({
|
|
|
28161
30191
|
maxWidth: 520,
|
|
28162
30192
|
gap: "0.5rem"
|
|
28163
30193
|
},
|
|
28164
|
-
children:
|
|
30194
|
+
children: safePayload.map((entry, index) => /* @__PURE__ */ jsx27(
|
|
28165
30195
|
LegendItem,
|
|
28166
30196
|
{
|
|
28167
30197
|
entry,
|
|
@@ -28511,8 +30541,8 @@ var PieChartWrapper = React4.forwardRef(
|
|
|
28511
30541
|
cy: "50%",
|
|
28512
30542
|
startAngle: 90,
|
|
28513
30543
|
endAngle: -270,
|
|
28514
|
-
innerRadius: isDonut ?
|
|
28515
|
-
outerRadius:
|
|
30544
|
+
innerRadius: isDonut ? "70%" : "0%",
|
|
30545
|
+
outerRadius: "100%",
|
|
28516
30546
|
paddingAngle: 0,
|
|
28517
30547
|
dataKey: category,
|
|
28518
30548
|
nameKey: index,
|
|
@@ -29115,8 +31145,8 @@ import {
|
|
|
29115
31145
|
} from "recharts";
|
|
29116
31146
|
|
|
29117
31147
|
// src/utils/axisFormatter.ts
|
|
29118
|
-
import { endOfWeek as endOfWeek2, format as format5, getWeek as getWeek2, isValid as
|
|
29119
|
-
import { utcToZonedTime as
|
|
31148
|
+
import { endOfWeek as endOfWeek2, format as format5, getWeek as getWeek2, isValid as isValid5, startOfWeek as startOfWeek5 } from "date-fns";
|
|
31149
|
+
import { utcToZonedTime as utcToZonedTime4 } from "date-fns-tz";
|
|
29120
31150
|
var axisFormatter = ({ value, field, fields }) => {
|
|
29121
31151
|
if (field === void 0 || field === null) return "";
|
|
29122
31152
|
if (value === void 0 || value === null) return "";
|
|
@@ -29232,8 +31262,8 @@ var formatPercent2 = (value) => {
|
|
|
29232
31262
|
return formatter.format(Number(value));
|
|
29233
31263
|
};
|
|
29234
31264
|
var _getUTCDateHelper2 = (value, fmt) => {
|
|
29235
|
-
const utcDate =
|
|
29236
|
-
if (!
|
|
31265
|
+
const utcDate = utcToZonedTime4(new Date(value), "UTC");
|
|
31266
|
+
if (!isValid5(utcDate)) return "Invalid date";
|
|
29237
31267
|
return format5(utcDate, fmt);
|
|
29238
31268
|
};
|
|
29239
31269
|
var format_YYYY2 = (value) => _getUTCDateHelper2(value, "yyyy");
|
|
@@ -29242,9 +31272,9 @@ var format_MMM_yyyy2 = (value) => _getUTCDateHelper2(value, "MMM yyyy");
|
|
|
29242
31272
|
var format_hh_ap_pm2 = (value) => _getUTCDateHelper2(value, "hh:mm aa");
|
|
29243
31273
|
var format_MMM_dd_yyyy2 = (value) => _getUTCDateHelper2(value, "dd MMM yyyy");
|
|
29244
31274
|
var format_MMM_dd_MMM_dd = (value) => {
|
|
29245
|
-
const utcDate =
|
|
29246
|
-
if (!
|
|
29247
|
-
const monday =
|
|
31275
|
+
const utcDate = utcToZonedTime4(new Date(value), "UTC");
|
|
31276
|
+
if (!isValid5(utcDate)) return "Invalid date";
|
|
31277
|
+
const monday = startOfWeek5(utcDate, { weekStartsOn: 1 });
|
|
29248
31278
|
const sunday = endOfWeek2(utcDate, { weekStartsOn: 1 });
|
|
29249
31279
|
if (format5(monday, "MMM") === format5(sunday, "MMM")) {
|
|
29250
31280
|
return `${format5(monday, "MMM dd")} - ${format5(sunday, "dd")}`;
|
|
@@ -29253,20 +31283,20 @@ var format_MMM_dd_MMM_dd = (value) => {
|
|
|
29253
31283
|
}
|
|
29254
31284
|
};
|
|
29255
31285
|
var format_MMM_dd_hh_mm_ap_pm2 = (value) => {
|
|
29256
|
-
const utcDate =
|
|
29257
|
-
if (!
|
|
31286
|
+
const utcDate = utcToZonedTime4(new Date(value), "UTC");
|
|
31287
|
+
if (!isValid5(utcDate)) return "Invalid date";
|
|
29258
31288
|
const formatStr = utcDate.getMinutes() === 0 ? "MMM do h a" : "MMM do h:mm a";
|
|
29259
31289
|
const res = format5(utcDate, formatStr);
|
|
29260
31290
|
return res.slice(0, -2) + res.slice(-2).toLowerCase();
|
|
29261
31291
|
};
|
|
29262
31292
|
var format_wo_yyyy2 = (value) => {
|
|
29263
|
-
const utcDate =
|
|
29264
|
-
if (!
|
|
31293
|
+
const utcDate = utcToZonedTime4(new Date(value), "UTC");
|
|
31294
|
+
if (!isValid5(utcDate)) return "Invalid date";
|
|
29265
31295
|
return `${getWeek2(utcDate)},${utcDate.getFullYear()}`;
|
|
29266
31296
|
};
|
|
29267
31297
|
|
|
29268
31298
|
// src/components/Chart/ChartTooltip.tsx
|
|
29269
|
-
import { format as format6, subDays as
|
|
31299
|
+
import { format as format6, subDays as subDays3 } from "date-fns";
|
|
29270
31300
|
|
|
29271
31301
|
// src/components/Chart/ChartTooltipFrame.tsx
|
|
29272
31302
|
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
@@ -29510,7 +31540,7 @@ function reformatComparisonPayload(props, primaryLabel, comparisonLabel) {
|
|
|
29510
31540
|
const nameKey = isComparison ? `comparison_${props.xAxisField}` : props.xAxisField;
|
|
29511
31541
|
const days = LABEL_TO_DAYS[primaryLabel] ?? 0;
|
|
29512
31542
|
const primaryDate = item.payload[props.xAxisField] ?? 0;
|
|
29513
|
-
const compDate =
|
|
31543
|
+
const compDate = subDays3(new Date(primaryDate), days + 1);
|
|
29514
31544
|
const date = item.payload[nameKey] ?? format6(compDate, props.xAxisFormat);
|
|
29515
31545
|
const name2 = props.dateFormatter(date);
|
|
29516
31546
|
const color2 = item.color;
|
|
@@ -30576,16 +32606,16 @@ import {
|
|
|
30576
32606
|
useState as useState12
|
|
30577
32607
|
} from "react";
|
|
30578
32608
|
import {
|
|
30579
|
-
startOfMonth as
|
|
32609
|
+
startOfMonth as startOfMonth4,
|
|
30580
32610
|
endOfMonth as endOfMonth2,
|
|
30581
32611
|
format as format7,
|
|
30582
32612
|
eachDayOfInterval,
|
|
30583
|
-
subMonths as
|
|
30584
|
-
startOfWeek as
|
|
32613
|
+
subMonths as subMonths5,
|
|
32614
|
+
startOfWeek as startOfWeek6,
|
|
30585
32615
|
endOfWeek as endOfWeek3,
|
|
30586
32616
|
differenceInDays as differenceInDays3,
|
|
30587
|
-
startOfDay as
|
|
30588
|
-
addMonths,
|
|
32617
|
+
startOfDay as startOfDay6,
|
|
32618
|
+
addMonths as addMonths2,
|
|
30589
32619
|
isBefore as isBefore2,
|
|
30590
32620
|
isAfter as isAfter2
|
|
30591
32621
|
} from "date-fns";
|
|
@@ -31110,20 +33140,20 @@ function CalendarRow({
|
|
|
31110
33140
|
setLocalPreset
|
|
31111
33141
|
}) {
|
|
31112
33142
|
const firstMonthDisplayedDates = eachDayOfInterval({
|
|
31113
|
-
start:
|
|
33143
|
+
start: startOfWeek6(anchorStartDate),
|
|
31114
33144
|
end: endOfWeek3(endOfMonth2(anchorStartDate))
|
|
31115
33145
|
});
|
|
31116
33146
|
const secondMonthDisplayedDates = eachDayOfInterval({
|
|
31117
|
-
start:
|
|
33147
|
+
start: startOfWeek6(startOfMonth4(anchorEndDate)),
|
|
31118
33148
|
end: endOfWeek3(anchorEndDate)
|
|
31119
33149
|
});
|
|
31120
33150
|
const incrementAnchorDates = () => {
|
|
31121
|
-
setAnchorStartDate(
|
|
31122
|
-
setAnchorEndDate(endOfMonth2(
|
|
33151
|
+
setAnchorStartDate(startOfMonth4(addMonths2(anchorStartDate, 1)));
|
|
33152
|
+
setAnchorEndDate(endOfMonth2(addMonths2(anchorEndDate, 1)));
|
|
31123
33153
|
};
|
|
31124
33154
|
const decrementAnchorDates = () => {
|
|
31125
|
-
setAnchorStartDate(
|
|
31126
|
-
setAnchorEndDate(endOfMonth2(
|
|
33155
|
+
setAnchorStartDate(startOfMonth4(subMonths5(anchorStartDate, 1)));
|
|
33156
|
+
setAnchorEndDate(endOfMonth2(subMonths5(anchorEndDate, 1)));
|
|
31127
33157
|
};
|
|
31128
33158
|
return /* @__PURE__ */ jsx40("div", { style: { position: "absolute", zIndex: 100, marginTop: 12 }, children: /* @__PURE__ */ jsxs30(
|
|
31129
33159
|
"div",
|
|
@@ -31377,10 +33407,10 @@ function DayPicker({
|
|
|
31377
33407
|
setLocalPreset,
|
|
31378
33408
|
theme
|
|
31379
33409
|
}) {
|
|
31380
|
-
const isStartDate = differenceInDays3(
|
|
31381
|
-
const isEndDate = differenceInDays3(
|
|
33410
|
+
const isStartDate = differenceInDays3(startOfDay6(date), startOfDay6(localStartDate || 0)) === 0;
|
|
33411
|
+
const isEndDate = differenceInDays3(startOfDay6(date), startOfDay6(localEndDate || 0)) === 0;
|
|
31382
33412
|
const isBetweenStartAndEnd = isBefore2(date, localEndDate || 0) && isAfter2(date, localStartDate || 0);
|
|
31383
|
-
const isBeginningOfWeek = differenceInDays3(
|
|
33413
|
+
const isBeginningOfWeek = differenceInDays3(startOfWeek6(date), date) === 0;
|
|
31384
33414
|
const isEndOfWeek = differenceInDays3(endOfWeek3(date), date) === 0;
|
|
31385
33415
|
return /* @__PURE__ */ jsx40(
|
|
31386
33416
|
"button",
|
|
@@ -31429,7 +33459,7 @@ function DayPicker({
|
|
|
31429
33459
|
});
|
|
31430
33460
|
setLocalPreset("");
|
|
31431
33461
|
}
|
|
31432
|
-
if (localStartDate && localEndDate && differenceInDays3(
|
|
33462
|
+
if (localStartDate && localEndDate && differenceInDays3(startOfDay6(date), startOfDay6(localStartDate)) === 0) {
|
|
31433
33463
|
setLocalStartDate(void 0);
|
|
31434
33464
|
setLocalEndDate(void 0);
|
|
31435
33465
|
}
|
|
@@ -31440,16 +33470,16 @@ function DayPicker({
|
|
|
31440
33470
|
}
|
|
31441
33471
|
function getAnchorStartDate(startDate, endDate) {
|
|
31442
33472
|
if (!startDate && !endDate) {
|
|
31443
|
-
return
|
|
33473
|
+
return startOfMonth4(subMonths5(/* @__PURE__ */ new Date(), 1));
|
|
31444
33474
|
}
|
|
31445
33475
|
if (startDate && !endDate) {
|
|
31446
|
-
return
|
|
33476
|
+
return startOfMonth4(startDate);
|
|
31447
33477
|
}
|
|
31448
33478
|
if (!startDate && endDate) {
|
|
31449
|
-
return
|
|
33479
|
+
return startOfMonth4(subMonths5(endDate, 1));
|
|
31450
33480
|
}
|
|
31451
33481
|
if (startDate && endDate) {
|
|
31452
|
-
return
|
|
33482
|
+
return startOfMonth4(startDate);
|
|
31453
33483
|
}
|
|
31454
33484
|
return /* @__PURE__ */ new Date();
|
|
31455
33485
|
}
|
|
@@ -31458,13 +33488,13 @@ function getAnchorEndDate(startDate, endDate) {
|
|
|
31458
33488
|
return endOfMonth2(/* @__PURE__ */ new Date());
|
|
31459
33489
|
}
|
|
31460
33490
|
if (startDate && !endDate) {
|
|
31461
|
-
return endOfMonth2(
|
|
33491
|
+
return endOfMonth2(addMonths2(startDate, 1));
|
|
31462
33492
|
}
|
|
31463
33493
|
if (!startDate && endDate) {
|
|
31464
33494
|
return endOfMonth2(endDate);
|
|
31465
33495
|
}
|
|
31466
33496
|
if (startDate && endDate) {
|
|
31467
|
-
return endOfMonth2(
|
|
33497
|
+
return endOfMonth2(addMonths2(startDate, 1));
|
|
31468
33498
|
}
|
|
31469
33499
|
return /* @__PURE__ */ new Date();
|
|
31470
33500
|
}
|
|
@@ -32659,6 +34689,164 @@ function DashboardFilter2({
|
|
|
32659
34689
|
// src/Chart.tsx
|
|
32660
34690
|
init_paginationProcessing();
|
|
32661
34691
|
|
|
34692
|
+
// src/utils/cloudCacheValidation.ts
|
|
34693
|
+
var LIMIT_CLAUSE_REGEX = /^limit\b\s+(?:all|\d+|\$\d+|:[a-zA-Z_][a-zA-Z0-9_]*|\?)/i;
|
|
34694
|
+
var SQL_CONTENT_TO_IGNORE_REGEX = /'(?:''|[^'])*'|"(?:[^"]|"")*"|`[^`]*`|\[[^\]]*\]|--[^\n]*|\/\*[\s\S]*?\*\//g;
|
|
34695
|
+
function isWordChar(char) {
|
|
34696
|
+
if (!char) {
|
|
34697
|
+
return false;
|
|
34698
|
+
}
|
|
34699
|
+
return /[A-Za-z0-9_]/.test(char);
|
|
34700
|
+
}
|
|
34701
|
+
function getFinalSqlStatement(query) {
|
|
34702
|
+
const statements = query.split(";").map((statement) => statement.trim()).filter((statement) => statement.length > 0);
|
|
34703
|
+
return statements[statements.length - 1] ?? "";
|
|
34704
|
+
}
|
|
34705
|
+
function hasTopLevelLimitClause(statement) {
|
|
34706
|
+
let depth = 0;
|
|
34707
|
+
for (let i = 0; i < statement.length; i += 1) {
|
|
34708
|
+
const char = statement[i];
|
|
34709
|
+
if (char === "(") {
|
|
34710
|
+
depth += 1;
|
|
34711
|
+
continue;
|
|
34712
|
+
}
|
|
34713
|
+
if (char === ")") {
|
|
34714
|
+
depth = Math.max(0, depth - 1);
|
|
34715
|
+
continue;
|
|
34716
|
+
}
|
|
34717
|
+
if (depth !== 0) {
|
|
34718
|
+
continue;
|
|
34719
|
+
}
|
|
34720
|
+
const previousChar = i > 0 ? statement[i - 1] : void 0;
|
|
34721
|
+
if (isWordChar(previousChar)) {
|
|
34722
|
+
continue;
|
|
34723
|
+
}
|
|
34724
|
+
if (!LIMIT_CLAUSE_REGEX.test(statement.slice(i))) {
|
|
34725
|
+
continue;
|
|
34726
|
+
}
|
|
34727
|
+
return true;
|
|
34728
|
+
}
|
|
34729
|
+
return false;
|
|
34730
|
+
}
|
|
34731
|
+
function unwrapIdentifier(identifier) {
|
|
34732
|
+
if (!identifier) {
|
|
34733
|
+
return "";
|
|
34734
|
+
}
|
|
34735
|
+
const trimmed = identifier.trim();
|
|
34736
|
+
if (trimmed.length < 2) {
|
|
34737
|
+
return trimmed;
|
|
34738
|
+
}
|
|
34739
|
+
const startsAndEndsWithDoubleQuote = trimmed.startsWith('"') && trimmed.endsWith('"');
|
|
34740
|
+
const startsAndEndsWithSingleQuote = trimmed.startsWith("'") && trimmed.endsWith("'");
|
|
34741
|
+
const startsAndEndsWithBackticks = trimmed.startsWith("`") && trimmed.endsWith("`");
|
|
34742
|
+
const startsAndEndsWithBrackets = trimmed.startsWith("[") && trimmed.endsWith("]");
|
|
34743
|
+
if (startsAndEndsWithDoubleQuote || startsAndEndsWithSingleQuote || startsAndEndsWithBackticks || startsAndEndsWithBrackets) {
|
|
34744
|
+
return trimmed.slice(1, -1);
|
|
34745
|
+
}
|
|
34746
|
+
return trimmed;
|
|
34747
|
+
}
|
|
34748
|
+
function normalizeIdentifier(identifier) {
|
|
34749
|
+
return unwrapIdentifier(identifier).toLowerCase();
|
|
34750
|
+
}
|
|
34751
|
+
function hasRowFieldWithIdentifier(row, normalizedField) {
|
|
34752
|
+
if (!row || !normalizedField) {
|
|
34753
|
+
return false;
|
|
34754
|
+
}
|
|
34755
|
+
return Object.keys(row).some(
|
|
34756
|
+
(fieldName) => normalizeIdentifier(fieldName) === normalizedField
|
|
34757
|
+
);
|
|
34758
|
+
}
|
|
34759
|
+
function reportReferencesField(report, field, table) {
|
|
34760
|
+
const normalizedField = normalizeIdentifier(field);
|
|
34761
|
+
if (!normalizedField) {
|
|
34762
|
+
return false;
|
|
34763
|
+
}
|
|
34764
|
+
const referencedColumns = report?.referencedColumns ?? {};
|
|
34765
|
+
let entries = Object.entries(referencedColumns);
|
|
34766
|
+
if (entries.length === 0) {
|
|
34767
|
+
return false;
|
|
34768
|
+
}
|
|
34769
|
+
const normalizedTable = normalizeIdentifier(table);
|
|
34770
|
+
if (normalizedTable) {
|
|
34771
|
+
entries = entries.filter(
|
|
34772
|
+
([tableName]) => normalizeIdentifier(tableName) === normalizedTable
|
|
34773
|
+
);
|
|
34774
|
+
}
|
|
34775
|
+
const referencedFields = entries.flatMap(([, fields]) => fields ?? []);
|
|
34776
|
+
if (referencedFields.length === 0) {
|
|
34777
|
+
return false;
|
|
34778
|
+
}
|
|
34779
|
+
return referencedFields.some((referencedField) => {
|
|
34780
|
+
const normalizedReferencedField = normalizeIdentifier(referencedField);
|
|
34781
|
+
return normalizedReferencedField === normalizedField || normalizedReferencedField === "*";
|
|
34782
|
+
});
|
|
34783
|
+
}
|
|
34784
|
+
function isDateFieldMissingInReport(report) {
|
|
34785
|
+
if (!report?.dateField?.field || !report.dateField.table) {
|
|
34786
|
+
return false;
|
|
34787
|
+
}
|
|
34788
|
+
const dateField = report.dateField;
|
|
34789
|
+
if (!reportReferencesField(report, dateField.field, dateField.table)) {
|
|
34790
|
+
return true;
|
|
34791
|
+
}
|
|
34792
|
+
const firstRow = report.rows?.[0];
|
|
34793
|
+
if (!firstRow) {
|
|
34794
|
+
return false;
|
|
34795
|
+
}
|
|
34796
|
+
const normalizedDateField = normalizeIdentifier(dateField.field);
|
|
34797
|
+
const dateFieldExistsInFirstRow = hasRowFieldWithIdentifier(
|
|
34798
|
+
firstRow,
|
|
34799
|
+
normalizedDateField
|
|
34800
|
+
);
|
|
34801
|
+
return !dateFieldExistsInFirstRow;
|
|
34802
|
+
}
|
|
34803
|
+
function hasLimitClause(query) {
|
|
34804
|
+
if (!query) {
|
|
34805
|
+
return false;
|
|
34806
|
+
}
|
|
34807
|
+
const sanitizedQuery = query.replace(SQL_CONTENT_TO_IGNORE_REGEX, " ");
|
|
34808
|
+
const finalStatement = getFinalSqlStatement(sanitizedQuery);
|
|
34809
|
+
if (!finalStatement) {
|
|
34810
|
+
return false;
|
|
34811
|
+
}
|
|
34812
|
+
return hasTopLevelLimitClause(finalStatement);
|
|
34813
|
+
}
|
|
34814
|
+
function reportUsesLimitClause(report) {
|
|
34815
|
+
const queriesToInspect = report?.itemQuery && report.itemQuery.length > 0 ? report.itemQuery : report?.queryString ? [report.queryString] : [];
|
|
34816
|
+
return queriesToInspect.some(hasLimitClause);
|
|
34817
|
+
}
|
|
34818
|
+
function getMissingDashboardFilterFields({
|
|
34819
|
+
rows = [],
|
|
34820
|
+
dashboardFilters = []
|
|
34821
|
+
}) {
|
|
34822
|
+
const dateIndex = dashboardFilters.findIndex(
|
|
34823
|
+
(filter) => filter.filterType === "date_range"
|
|
34824
|
+
);
|
|
34825
|
+
const requiredFields = dashboardFilters.flatMap((filter, index) => {
|
|
34826
|
+
if (index === dateIndex || !filter.field) {
|
|
34827
|
+
return [];
|
|
34828
|
+
}
|
|
34829
|
+
const normalizedField = normalizeIdentifier(filter.field);
|
|
34830
|
+
if (!normalizedField) {
|
|
34831
|
+
return [];
|
|
34832
|
+
}
|
|
34833
|
+
return [
|
|
34834
|
+
{
|
|
34835
|
+
displayField: unwrapIdentifier(filter.field),
|
|
34836
|
+
normalizedField
|
|
34837
|
+
}
|
|
34838
|
+
];
|
|
34839
|
+
});
|
|
34840
|
+
const dedupedRequiredFields = requiredFields.filter(
|
|
34841
|
+
(field, index, fields) => fields.findIndex(
|
|
34842
|
+
(candidate) => candidate.normalizedField === field.normalizedField
|
|
34843
|
+
) === index
|
|
34844
|
+
);
|
|
34845
|
+
return dedupedRequiredFields.filter(
|
|
34846
|
+
({ normalizedField }) => rows.some((row) => !hasRowFieldWithIdentifier(row, normalizedField))
|
|
34847
|
+
).map(({ displayField }) => displayField);
|
|
34848
|
+
}
|
|
34849
|
+
|
|
32662
34850
|
// src/components/Dashboard/MetricComponent.tsx
|
|
32663
34851
|
init_dateRangePickerUtils();
|
|
32664
34852
|
import { useContext as useContext12 } from "react";
|
|
@@ -32766,7 +34954,7 @@ function QuillMetricComponent({
|
|
|
32766
34954
|
width: "100%"
|
|
32767
34955
|
}
|
|
32768
34956
|
}
|
|
32769
|
-
) : !report?.rows || report?.rows?.length === 0
|
|
34957
|
+
) : !report?.rows || report?.rows?.length === 0 ? /* @__PURE__ */ jsx44(
|
|
32770
34958
|
"div",
|
|
32771
34959
|
{
|
|
32772
34960
|
style: {
|
|
@@ -36285,6 +38473,7 @@ function QuillTableDashboardComponent({
|
|
|
36285
38473
|
}
|
|
36286
38474
|
|
|
36287
38475
|
// src/Chart.tsx
|
|
38476
|
+
init_valueFormatter();
|
|
36288
38477
|
import { Fragment as Fragment5, jsx as jsx49, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
36289
38478
|
var MAX_ROWS_FOR_GENERIC_TABLE = 500;
|
|
36290
38479
|
function sumByKey(arr, key) {
|
|
@@ -36321,7 +38510,8 @@ function Chart({
|
|
|
36321
38510
|
filters,
|
|
36322
38511
|
onClickChartElement,
|
|
36323
38512
|
dateBucket,
|
|
36324
|
-
propagateChanges
|
|
38513
|
+
propagateChanges,
|
|
38514
|
+
isAdmin = false
|
|
36325
38515
|
}) {
|
|
36326
38516
|
const [schemaData] = useContext16(SchemaDataContext);
|
|
36327
38517
|
const { reload } = useReportInternal(reportId);
|
|
@@ -36443,6 +38633,25 @@ function Chart({
|
|
|
36443
38633
|
}
|
|
36444
38634
|
}, [report, theme]);
|
|
36445
38635
|
const [client, clientLoading] = useContext16(ClientContext);
|
|
38636
|
+
const cloudCacheEnabled = useMemo13(() => {
|
|
38637
|
+
return !!client?.features?.cloudCache;
|
|
38638
|
+
}, [client]);
|
|
38639
|
+
const shouldShowCloudCacheValidationErrors = isAdmin && cloudCacheEnabled;
|
|
38640
|
+
const isMissingDateField = useMemo13(() => {
|
|
38641
|
+
if (!shouldShowCloudCacheValidationErrors) return false;
|
|
38642
|
+
return isDateFieldMissingInReport(report);
|
|
38643
|
+
}, [report, shouldShowCloudCacheValidationErrors]);
|
|
38644
|
+
const usesLimitInQuery = useMemo13(() => {
|
|
38645
|
+
if (!shouldShowCloudCacheValidationErrors) return false;
|
|
38646
|
+
return reportUsesLimitClause(report);
|
|
38647
|
+
}, [report, shouldShowCloudCacheValidationErrors]);
|
|
38648
|
+
const missingDashboardFilterFields = useMemo13(() => {
|
|
38649
|
+
if (!shouldShowCloudCacheValidationErrors || !report) return [];
|
|
38650
|
+
return getMissingDashboardFilterFields({
|
|
38651
|
+
rows: report.rows,
|
|
38652
|
+
dashboardFilters
|
|
38653
|
+
});
|
|
38654
|
+
}, [report, dashboardFilters, shouldShowCloudCacheValidationErrors]);
|
|
36446
38655
|
const [error, setError] = useState19(void 0);
|
|
36447
38656
|
const updateFilter = (filter, value, comparison) => {
|
|
36448
38657
|
let filterValue = {};
|
|
@@ -36583,6 +38792,15 @@ function Chart({
|
|
|
36583
38792
|
if (report?.error || error) {
|
|
36584
38793
|
return /* @__PURE__ */ jsx49("div", { style: containerStyle, className, children: /* @__PURE__ */ jsx49(ChartError, { errorMessage: report?.error ?? error }) });
|
|
36585
38794
|
}
|
|
38795
|
+
if (isMissingDateField) {
|
|
38796
|
+
return /* @__PURE__ */ jsx49("div", { style: containerStyle, className, children: /* @__PURE__ */ jsx49(ChartError, { errorMessage: `The query for this report is missing dashboard date filter field ${report?.dateField?.field}, which is necessary for date filtering on this dashboard when the cache is enabled.` }) });
|
|
38797
|
+
}
|
|
38798
|
+
if (usesLimitInQuery) {
|
|
38799
|
+
return /* @__PURE__ */ jsx49("div", { style: containerStyle, className, children: /* @__PURE__ */ jsx49(ChartError, { errorMessage: `The query for this report uses the LIMIT keyword, which is not supported when the cache is enabled.` }) });
|
|
38800
|
+
}
|
|
38801
|
+
if (missingDashboardFilterFields.length) {
|
|
38802
|
+
return /* @__PURE__ */ jsx49("div", { style: containerStyle, className, children: /* @__PURE__ */ jsx49(ChartError, { errorMessage: `The query for this report is missing dashboard filter fields: ${missingDashboardFilterFields.join(", ")}` }) });
|
|
38803
|
+
}
|
|
36586
38804
|
return /* @__PURE__ */ jsxs37(
|
|
36587
38805
|
"div",
|
|
36588
38806
|
{
|
|
@@ -36913,7 +39131,7 @@ var ChartDisplay = ({
|
|
|
36913
39131
|
);
|
|
36914
39132
|
}
|
|
36915
39133
|
if (config?.chartType?.toLowerCase() === "metric") {
|
|
36916
|
-
if (!config?.rows || config?.rows?.length === 0
|
|
39134
|
+
if (!config?.rows || config?.rows?.length === 0) {
|
|
36917
39135
|
return /* @__PURE__ */ jsx49(
|
|
36918
39136
|
"div",
|
|
36919
39137
|
{
|
|
@@ -36951,6 +39169,36 @@ var ChartDisplay = ({
|
|
|
36951
39169
|
}
|
|
36952
39170
|
);
|
|
36953
39171
|
}
|
|
39172
|
+
if (config?.pivotRows && config?.pivotRows?.length > 0) {
|
|
39173
|
+
return /* @__PURE__ */ jsx49(
|
|
39174
|
+
"div",
|
|
39175
|
+
{
|
|
39176
|
+
style: {
|
|
39177
|
+
fontFamily: theme?.fontFamily,
|
|
39178
|
+
fontSize: 32,
|
|
39179
|
+
color: theme?.primaryTextColor,
|
|
39180
|
+
fontWeight: "600",
|
|
39181
|
+
textOverflow: "ellipsis",
|
|
39182
|
+
margin: 0,
|
|
39183
|
+
whiteSpace: "nowrap",
|
|
39184
|
+
boxSizing: "content-box",
|
|
39185
|
+
maxWidth: "100%",
|
|
39186
|
+
textAlign: "left",
|
|
39187
|
+
overflow: "hidden",
|
|
39188
|
+
height: containerStyle?.height || "100%",
|
|
39189
|
+
display: "flex",
|
|
39190
|
+
width: "100%",
|
|
39191
|
+
flexDirection: "row",
|
|
39192
|
+
...containerStyle
|
|
39193
|
+
},
|
|
39194
|
+
className,
|
|
39195
|
+
children: /* @__PURE__ */ jsx49(QuillMetricComponent, { report: config ?? EMPTY_REPORT, children: quillFormat({
|
|
39196
|
+
value: config?.pivotRows?.[0]?.[config?.xAxisField],
|
|
39197
|
+
format: config?.xAxisFormat
|
|
39198
|
+
}) ?? "No results" })
|
|
39199
|
+
}
|
|
39200
|
+
);
|
|
39201
|
+
}
|
|
36954
39202
|
return /* @__PURE__ */ jsx49(
|
|
36955
39203
|
"div",
|
|
36956
39204
|
{
|
|
@@ -37899,7 +40147,7 @@ init_Filter();
|
|
|
37899
40147
|
import { useState as useState22, useEffect as useEffect18, useMemo as useMemo15 } from "react";
|
|
37900
40148
|
init_textProcessing();
|
|
37901
40149
|
init_filterProcessing();
|
|
37902
|
-
import { format as format8, isValid as
|
|
40150
|
+
import { format as format8, isValid as isValid6, parse as parse4, startOfToday as startOfToday2 } from "date-fns";
|
|
37903
40151
|
import { Fragment as Fragment8, jsx as jsx55, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
37904
40152
|
function FilterModal({
|
|
37905
40153
|
schema,
|
|
@@ -38100,7 +40348,7 @@ function FilterModal({
|
|
|
38100
40348
|
DateOperator.LessThan,
|
|
38101
40349
|
DateOperator.LessThanOrEqualTo,
|
|
38102
40350
|
DateOperator.NotEqualTo
|
|
38103
|
-
].includes(operator2) && !
|
|
40351
|
+
].includes(operator2) && !isValid6(parse4(value, "yyyy-mm-dd", /* @__PURE__ */ new Date())) && (filterInitialized || !filter)) {
|
|
38104
40352
|
setValue(startOfToday2().toISOString().substring(0, 10));
|
|
38105
40353
|
} else if (type === FieldType.Date && [
|
|
38106
40354
|
DateOperator.InTheLast,
|
|
@@ -38290,7 +40538,7 @@ function FilterModal({
|
|
|
38290
40538
|
case DateOperator.GreaterThanOrEqualTo:
|
|
38291
40539
|
case DateOperator.LessThanOrEqualTo: {
|
|
38292
40540
|
const parsedDate = parse4(value, "yyyy-mm-dd", /* @__PURE__ */ new Date());
|
|
38293
|
-
if (!
|
|
40541
|
+
if (!isValid6(parsedDate)) {
|
|
38294
40542
|
alert("Please specify a valid date in yyyy-mm-dd");
|
|
38295
40543
|
return;
|
|
38296
40544
|
}
|
|
@@ -38818,6 +41066,9 @@ function validateTemplatesAgainstFilters(filters, templates) {
|
|
|
38818
41066
|
}
|
|
38819
41067
|
async function addTemplatesToDashboard(name2, newTemplates, client, dashboardData, getToken, eventTracking) {
|
|
38820
41068
|
try {
|
|
41069
|
+
if (!newTemplates?.length) {
|
|
41070
|
+
return null;
|
|
41071
|
+
}
|
|
38821
41072
|
const { publicKey, tenants } = client;
|
|
38822
41073
|
if (tenants) {
|
|
38823
41074
|
throw new Error("Adding from template not yet supported for tenants");
|
|
@@ -38870,6 +41121,7 @@ async function addTemplatesToDashboard(name2, newTemplates, client, dashboardDat
|
|
|
38870
41121
|
function: "addTemplatesToDashboard"
|
|
38871
41122
|
}
|
|
38872
41123
|
});
|
|
41124
|
+
return null;
|
|
38873
41125
|
}
|
|
38874
41126
|
}
|
|
38875
41127
|
|
|
@@ -40366,7 +42618,7 @@ import {
|
|
|
40366
42618
|
useEffect as useEffect25,
|
|
40367
42619
|
useRef as useRef20,
|
|
40368
42620
|
useMemo as useMemo22,
|
|
40369
|
-
useCallback as
|
|
42621
|
+
useCallback as useCallback5
|
|
40370
42622
|
} from "react";
|
|
40371
42623
|
import MonacoEditor from "@monaco-editor/react";
|
|
40372
42624
|
|
|
@@ -40377,7 +42629,7 @@ import {
|
|
|
40377
42629
|
useState as useState30,
|
|
40378
42630
|
useContext as useContext26,
|
|
40379
42631
|
useMemo as useMemo21,
|
|
40380
|
-
useCallback as
|
|
42632
|
+
useCallback as useCallback4
|
|
40381
42633
|
} from "react";
|
|
40382
42634
|
import {
|
|
40383
42635
|
closestCenter,
|
|
@@ -40398,7 +42650,7 @@ import { CSS as DND_CSS } from "@dnd-kit/utilities";
|
|
|
40398
42650
|
|
|
40399
42651
|
// src/internals/ReportBuilder/PivotModal.tsx
|
|
40400
42652
|
import {
|
|
40401
|
-
useCallback as
|
|
42653
|
+
useCallback as useCallback3,
|
|
40402
42654
|
useContext as useContext23,
|
|
40403
42655
|
useMemo as useMemo18,
|
|
40404
42656
|
useState as useState27,
|
|
@@ -40793,7 +43045,7 @@ import {
|
|
|
40793
43045
|
eachMonthOfInterval,
|
|
40794
43046
|
eachWeekOfInterval,
|
|
40795
43047
|
eachYearOfInterval,
|
|
40796
|
-
isValid as
|
|
43048
|
+
isValid as isValid7,
|
|
40797
43049
|
parseISO as parseISO3
|
|
40798
43050
|
} from "date-fns";
|
|
40799
43051
|
init_pivotProcessing();
|
|
@@ -41281,7 +43533,7 @@ var PivotModal = ({
|
|
|
41281
43533
|
setIsOpen(false);
|
|
41282
43534
|
setPopUpTitle("Add pivot");
|
|
41283
43535
|
};
|
|
41284
|
-
const onCommitPivot =
|
|
43536
|
+
const onCommitPivot = useCallback3(() => {
|
|
41285
43537
|
const errors2 = [];
|
|
41286
43538
|
if ((pivotAggregations?.length ?? 0) === 0) {
|
|
41287
43539
|
errors2.push("You must have at least one aggregation");
|
|
@@ -41423,7 +43675,7 @@ var PivotModal = ({
|
|
|
41423
43675
|
const onEditRecommendedPivot = (pivot) => {
|
|
41424
43676
|
onEditPivot(pivot, null);
|
|
41425
43677
|
};
|
|
41426
|
-
const refreshPivots =
|
|
43678
|
+
const refreshPivots = useCallback3(async () => {
|
|
41427
43679
|
if (!client) {
|
|
41428
43680
|
return;
|
|
41429
43681
|
}
|
|
@@ -44474,7 +46726,7 @@ function ChartBuilder({
|
|
|
44474
46726
|
template: true,
|
|
44475
46727
|
referenceLines: []
|
|
44476
46728
|
};
|
|
44477
|
-
const
|
|
46729
|
+
const updateDashboardFilters2 = async (dashboardName) => {
|
|
44478
46730
|
if (dashboardConfig && dashboardConfig[dashboardName]) {
|
|
44479
46731
|
return dashboardConfig[dashboardName];
|
|
44480
46732
|
}
|
|
@@ -44796,7 +47048,7 @@ function ChartBuilder({
|
|
|
44796
47048
|
if (destinationDashboardName) {
|
|
44797
47049
|
dashboardName = destinationDashboardName;
|
|
44798
47050
|
}
|
|
44799
|
-
const curDashboard = await
|
|
47051
|
+
const curDashboard = await updateDashboardFilters2(dashboardName);
|
|
44800
47052
|
setDashboardOptions(dashboardOptions2);
|
|
44801
47053
|
curFormData.dashboardName = dashboardName;
|
|
44802
47054
|
const curSchemaData = schemaData.schemaWithCustomFields;
|
|
@@ -44940,7 +47192,7 @@ function ChartBuilder({
|
|
|
44940
47192
|
) ?? {};
|
|
44941
47193
|
}, [client?.allTenantTypes]);
|
|
44942
47194
|
const [selectedPivotTable, setSelectedPivotTable] = useState30(pivotData);
|
|
44943
|
-
const getDefaultXAxisFormat =
|
|
47195
|
+
const getDefaultXAxisFormat = useCallback4(
|
|
44944
47196
|
(form) => {
|
|
44945
47197
|
if (form.pivot?.rowField) {
|
|
44946
47198
|
if (isDateField(form.pivot.rowFieldType ?? "")) {
|
|
@@ -46083,7 +48335,7 @@ function ChartBuilder({
|
|
|
46083
48335
|
value: formData.dashboardName || "",
|
|
46084
48336
|
onChange: async (e) => {
|
|
46085
48337
|
handleChange(e.target.value, "dashboardName");
|
|
46086
|
-
await
|
|
48338
|
+
await updateDashboardFilters2(e.target.value);
|
|
46087
48339
|
},
|
|
46088
48340
|
options: dashboardOptions.map((elem) => ({
|
|
46089
48341
|
label: elem.label,
|
|
@@ -48316,7 +50568,7 @@ function SQLEditor({
|
|
|
48316
50568
|
onCloseChartBuilder && onCloseChartBuilder();
|
|
48317
50569
|
}
|
|
48318
50570
|
}, [isChartBuilderOpen]);
|
|
48319
|
-
const handleRunSqlPrompt =
|
|
50571
|
+
const handleRunSqlPrompt = useCallback5(async () => {
|
|
48320
50572
|
if (!client || sqlResponseLoading) {
|
|
48321
50573
|
return;
|
|
48322
50574
|
}
|
|
@@ -48335,7 +50587,7 @@ function SQLEditor({
|
|
|
48335
50587
|
setQuery(resp.message);
|
|
48336
50588
|
setSqlResponseLoading(false);
|
|
48337
50589
|
}, [sqlPrompt, sqlResponseLoading]);
|
|
48338
|
-
const debounceRunSqlPrompt =
|
|
50590
|
+
const debounceRunSqlPrompt = useCallback5(
|
|
48339
50591
|
createDebounce(handleRunSqlPrompt, 500),
|
|
48340
50592
|
[handleRunSqlPrompt]
|
|
48341
50593
|
);
|
|
@@ -54450,7 +56702,7 @@ function StaticChart(props) {
|
|
|
54450
56702
|
pageLoading,
|
|
54451
56703
|
nextPage,
|
|
54452
56704
|
prevPage,
|
|
54453
|
-
sortRows
|
|
56705
|
+
sortRows: sortRows2
|
|
54454
56706
|
} = useDashboardReportInternal(reportId);
|
|
54455
56707
|
const baseStyle = report?.chartType && CHART_TYPE_STYLES[report.chartType] ? CHART_TYPE_STYLES[report.chartType] : DEFAULT_STYLE;
|
|
54456
56708
|
const mergedStyle = className ? { ...containerStyle ?? {} } : { ...baseStyle, ...containerStyle ?? {} };
|
|
@@ -54470,7 +56722,7 @@ function StaticChart(props) {
|
|
|
54470
56722
|
}
|
|
54471
56723
|
};
|
|
54472
56724
|
const onSortChange = (sort) => {
|
|
54473
|
-
|
|
56725
|
+
sortRows2({
|
|
54474
56726
|
field: sort.field,
|
|
54475
56727
|
direction: sort.direction
|
|
54476
56728
|
});
|
|
@@ -54479,29 +56731,10 @@ function StaticChart(props) {
|
|
|
54479
56731
|
...report,
|
|
54480
56732
|
...report.pivot ? formattedPivotRowsAndColumns(report) : {}
|
|
54481
56733
|
} : void 0;
|
|
54482
|
-
const patchedConfig = config && config.pivot ? {
|
|
54483
|
-
...config,
|
|
54484
|
-
yAxisFields: config.columns?.slice(1).map((col) => ({
|
|
54485
|
-
field: col.field,
|
|
54486
|
-
label: col.label ?? col.field,
|
|
54487
|
-
format: col.format ?? "number"
|
|
54488
|
-
})) ?? config.yAxisFields
|
|
54489
|
-
} : config;
|
|
54490
|
-
if (patchedConfig) {
|
|
54491
|
-
const sample = (patchedConfig.pivotRows ?? patchedConfig.rows ?? []).slice(0, 1).map((row) => {
|
|
54492
|
-
const field = patchedConfig.yAxisFields?.[0]?.field;
|
|
54493
|
-
return {
|
|
54494
|
-
...row,
|
|
54495
|
-
_firstField: field,
|
|
54496
|
-
_firstFieldType: field ? typeof row[field] : void 0
|
|
54497
|
-
};
|
|
54498
|
-
});
|
|
54499
|
-
}
|
|
54500
56734
|
return /* @__PURE__ */ jsx84(
|
|
54501
56735
|
ChartDisplay,
|
|
54502
56736
|
{
|
|
54503
|
-
|
|
54504
|
-
config: patchedConfig,
|
|
56737
|
+
config,
|
|
54505
56738
|
onClickChartElement,
|
|
54506
56739
|
loading,
|
|
54507
56740
|
className,
|