@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 CHANGED
@@ -1537,6 +1537,7 @@ var init_dateRangePickerUtils = __esm({
1537
1537
  }
1538
1538
  });
1539
1539
  const defaultCustomIntervals = defaultIntervals.flatMap((interval2) => {
1540
+ const normalizedLabel = interval2.label?.toLowerCase().trim();
1540
1541
  let createdIntervals = [];
1541
1542
  if (interval2.label === "This week") {
1542
1543
  createdIntervals = [
@@ -1686,13 +1687,13 @@ var init_dateRangePickerUtils = __esm({
1686
1687
  unit: "months"
1687
1688
  }
1688
1689
  ];
1689
- } else if (interval2.label === "Last month") {
1690
+ } else if (normalizedLabel === "last month") {
1690
1691
  createdIntervals = [
1691
1692
  {
1692
1693
  type: "previous_month"
1693
1694
  }
1694
1695
  ];
1695
- } else if (interval2.label === "Last quarter") {
1696
+ } else if (normalizedLabel === "previous quarter" || normalizedLabel === "last quarter") {
1696
1697
  createdIntervals = [
1697
1698
  {
1698
1699
  type: "previous_quarter"
@@ -2086,13 +2087,13 @@ var init_Filter = __esm({
2086
2087
  TimeUnit2[TimeUnit2["Hour"] = HOUR] = "Hour";
2087
2088
  return TimeUnit2;
2088
2089
  })(TimeUnit || {});
2089
- FieldType = /* @__PURE__ */ ((FieldType2) => {
2090
- FieldType2[FieldType2["String"] = STRING] = "String";
2091
- FieldType2[FieldType2["Number"] = NUMBER] = "Number";
2092
- FieldType2[FieldType2["Date"] = DATE] = "Date";
2093
- FieldType2[FieldType2["Null"] = NULL] = "Null";
2094
- FieldType2[FieldType2["Boolean"] = BOOLEAN] = "Boolean";
2095
- return FieldType2;
2090
+ FieldType = /* @__PURE__ */ ((FieldType3) => {
2091
+ FieldType3[FieldType3["String"] = STRING] = "String";
2092
+ FieldType3[FieldType3["Number"] = NUMBER] = "Number";
2093
+ FieldType3[FieldType3["Date"] = DATE] = "Date";
2094
+ FieldType3[FieldType3["Null"] = NULL] = "Null";
2095
+ FieldType3[FieldType3["Boolean"] = BOOLEAN] = "Boolean";
2096
+ return FieldType3;
2096
2097
  })(FieldType || {});
2097
2098
  InternalFilterType = /* @__PURE__ */ ((InternalFilterType2) => {
2098
2099
  InternalFilterType2["StringFilter"] = "string-filter";
@@ -2238,7 +2239,7 @@ var init_Filter = __esm({
2238
2239
  fieldType = FieldType.Boolean;
2239
2240
  operator = filter.operator;
2240
2241
  field = filter.field;
2241
- value = null;
2242
+ value = filter.value;
2242
2243
  table = filter.table;
2243
2244
  return {
2244
2245
  filterType,
@@ -2249,7 +2250,7 @@ var init_Filter = __esm({
2249
2250
  operator
2250
2251
  };
2251
2252
  case "date" /* Date */:
2252
- if (typeof filter.value === "object" && filter.value && "value" in filter.value && filter.value.unit) {
2253
+ if (typeof filter.value === "object" && filter.value && "unit" in filter.value) {
2253
2254
  if (filter.value.value && typeof filter.value.value !== "number" || typeof filter.value.unit !== "string") {
2254
2255
  throw new Error(
2255
2256
  `Invalid value for DateFilter, expected { value: number, unit: string }, got ${filter.value}`
@@ -2305,7 +2306,7 @@ var init_Filter = __esm({
2305
2306
  table = filter.table;
2306
2307
  } else {
2307
2308
  throw new Error(
2308
- `Invalid value for DateFilter, expected { value: number, unit: string }, { startDate: string, endDate: string}, or string, got ${filter.value}`
2309
+ `Invalid value for DateFilter, expected { value?: number, unit: string }, { startDate: string, endDate: string}, or string, got ${filter.value}`
2309
2310
  );
2310
2311
  }
2311
2312
  return {
@@ -15908,7 +15909,7 @@ var init_dataProcessing = __esm({
15908
15909
  } else {
15909
15910
  if (data.dateField && data.dateField.field) {
15910
15911
  const dateField = data.dateField.field.replaceAll('"', "");
15911
- const maxDate = new Date(
15912
+ const maxDate2 = new Date(
15912
15913
  data.rows.reduce((acc, row) => {
15913
15914
  const rowValue = row[dateField];
15914
15915
  if (rowValue) {
@@ -15917,7 +15918,7 @@ var init_dataProcessing = __esm({
15917
15918
  return Math.max(acc, 0);
15918
15919
  }, 0)
15919
15920
  );
15920
- const minDate = new Date(
15921
+ const minDate2 = new Date(
15921
15922
  data.rows.reduce((acc, row) => {
15922
15923
  const rowValue = row[dateField];
15923
15924
  if (rowValue) {
@@ -15927,16 +15928,16 @@ var init_dataProcessing = __esm({
15927
15928
  }, (/* @__PURE__ */ new Date("3022-01-01")).getTime())
15928
15929
  );
15929
15930
  const dateBucket = getDateBucketFromRange({
15930
- start: minDate,
15931
- end: maxDate
15931
+ start: minDate2,
15932
+ end: maxDate2
15932
15933
  });
15933
15934
  const minDateBucket = getDateString(
15934
- minDate.toISOString(),
15935
+ minDate2.toISOString(),
15935
15936
  void 0,
15936
15937
  dateBucket
15937
15938
  );
15938
15939
  const maxDateBucket = getDateString(
15939
- maxDate.toISOString(),
15940
+ maxDate2.toISOString(),
15940
15941
  void 0,
15941
15942
  dateBucket
15942
15943
  );
@@ -16053,8 +16054,9 @@ async function generatePivotWithSQL({
16053
16054
  getPivotRowCount = true,
16054
16055
  caller,
16055
16056
  getToken,
16056
- reportBuilderState
16057
+ reportBuilderState,
16057
16058
  // Add reportBuilderState parameter
16059
+ overwriteCache = false
16058
16060
  }) {
16059
16061
  const databaseType = client.databaseType || "postgresql";
16060
16062
  if (!pivot.aggregations?.length && pivot.aggregationType) {
@@ -16103,7 +16105,8 @@ async function generatePivotWithSQL({
16103
16105
  })),
16104
16106
  // Only pass dashboard filters in Dashboard context, not ReportBuilder
16105
16107
  tenants,
16106
- additionalProcessing
16108
+ additionalProcessing,
16109
+ overwriteCache
16107
16110
  },
16108
16111
  getToken
16109
16112
  });
@@ -16277,8 +16280,9 @@ async function generatePivotTable({
16277
16280
  additionalProcessing,
16278
16281
  caller,
16279
16282
  pivotQuery,
16280
- reportBuilderState
16283
+ reportBuilderState,
16281
16284
  // Add reportBuilderState parameter
16285
+ overwriteCache
16282
16286
  }) {
16283
16287
  try {
16284
16288
  if (report && client) {
@@ -16295,8 +16299,9 @@ async function generatePivotTable({
16295
16299
  additionalProcessing,
16296
16300
  caller,
16297
16301
  getToken,
16298
- reportBuilderState
16302
+ reportBuilderState,
16299
16303
  // Pass reportBuilderState
16304
+ overwriteCache
16300
16305
  });
16301
16306
  return pivotTable;
16302
16307
  }
@@ -18182,7 +18187,7 @@ var init_tableProcessing = __esm({
18182
18187
  try {
18183
18188
  let data;
18184
18189
  if (reportBuilderState) {
18185
- let { data: data2 } = await quillFetch({
18190
+ ({ data } = await quillFetch({
18186
18191
  client,
18187
18192
  task: "report-builder-counts",
18188
18193
  metadata: {
@@ -18196,9 +18201,9 @@ var init_tableProcessing = __esm({
18196
18201
  tenants
18197
18202
  },
18198
18203
  getToken
18199
- });
18204
+ }));
18200
18205
  } else {
18201
- let { data: data2 } = await quillFetch({
18206
+ ({ data } = await quillFetch({
18202
18207
  client,
18203
18208
  task: "query",
18204
18209
  metadata: {
@@ -18212,7 +18217,7 @@ var init_tableProcessing = __esm({
18212
18217
  },
18213
18218
  urlParameters: `caller=getCounts&task=query`,
18214
18219
  getToken
18215
- });
18220
+ }));
18216
18221
  }
18217
18222
  if (data.errorMessage) {
18218
18223
  return { filteredColumns: columns, exceededColumns: void 0 };
@@ -19202,9 +19207,9 @@ var init_dataFetcher = __esm({
19202
19207
  return { error: "Failed to fetch data" };
19203
19208
  }
19204
19209
  };
19205
- parseFetchResponse = async (client, task, response, getToken) => {
19210
+ parseFetchResponse = async (client, task, response, getToken, useInMemory = false) => {
19206
19211
  try {
19207
- if (response.status === "error" || response.data?.error) {
19212
+ if (response.status === "error" || response.data?.error && !useInMemory) {
19208
19213
  let errorPrefix = "Error: ";
19209
19214
  let errorMessage = "Failed to fetch report: " + (response.error || response.data?.error);
19210
19215
  if (task === "query" || task === "report-builder") {
@@ -19817,7 +19822,8 @@ async function cleanDashboardItem({
19817
19822
  additionalProcessing,
19818
19823
  customFields,
19819
19824
  skipPivotFetch,
19820
- tenants
19825
+ tenants,
19826
+ overwriteCache
19821
19827
  }) {
19822
19828
  if (!item) return defaultDashboardItem;
19823
19829
  if (!item.rows) {
@@ -19921,7 +19927,8 @@ async function cleanDashboardItem({
19921
19927
  dateBucket,
19922
19928
  shouldPaginatePivotAsTable ? additionalProcessing : pivotChartProcessing,
19923
19929
  tenants,
19924
- customFields
19930
+ customFields,
19931
+ overwriteCache
19925
19932
  );
19926
19933
  }
19927
19934
  } catch (e) {
@@ -20026,7 +20033,7 @@ async function cleanDashboardItem({
20026
20033
  referenceLines: item.referenceLines
20027
20034
  };
20028
20035
  }
20029
- async function getPivotTable(report, dashboardFilters, dashboardName, getToken, client, eventTracking, dateBucketInitial, additionalProcessing, tenants, customFields) {
20036
+ async function getPivotTable(report, dashboardFilters, dashboardName, getToken, client, eventTracking, dateBucketInitial, additionalProcessing, tenants, customFields, overwriteCache) {
20030
20037
  if (!report) return void 0;
20031
20038
  const dateFilter = Object.values(dashboardFilters ?? {}).find(
20032
20039
  (filter) => filter.filterType === "date_range" || filter.operator === "BETWEEN"
@@ -20094,7 +20101,8 @@ async function getPivotTable(report, dashboardFilters, dashboardName, getToken,
20094
20101
  dashboardFilters,
20095
20102
  tenants,
20096
20103
  additionalProcessing,
20097
- getToken
20104
+ getToken,
20105
+ overwriteCache
20098
20106
  });
20099
20107
  return pivotTable;
20100
20108
  } catch (e) {
@@ -20342,7 +20350,8 @@ async function fetchReportRows({
20342
20350
  filters = [],
20343
20351
  getToken,
20344
20352
  abortSignal,
20345
- additionalProcessing
20353
+ additionalProcessing,
20354
+ overwriteCache = false
20346
20355
  }) {
20347
20356
  const fetchResp = await quillFetch({
20348
20357
  client,
@@ -20354,7 +20363,8 @@ async function fetchReportRows({
20354
20363
  filters: filters.map((filter) => ({ ...filter, options: void 0 })),
20355
20364
  useNewNodeSql: true,
20356
20365
  tenants,
20357
- additionalProcessing
20366
+ additionalProcessing,
20367
+ overwriteCache
20358
20368
  },
20359
20369
  abortSignal,
20360
20370
  getToken
@@ -20385,7 +20395,8 @@ async function fetchReport({
20385
20395
  abortSignal,
20386
20396
  getToken,
20387
20397
  eventTracking,
20388
- usePivotTask = false
20398
+ usePivotTask = false,
20399
+ overwriteCache = false
20389
20400
  }) {
20390
20401
  let reportInfo = void 0;
20391
20402
  let errorMessage = void 0;
@@ -20405,7 +20416,8 @@ async function fetchReport({
20405
20416
  rowsOnly,
20406
20417
  rowCountOnly,
20407
20418
  tenants,
20408
- flags
20419
+ flags,
20420
+ overwriteCache
20409
20421
  },
20410
20422
  abortSignal,
20411
20423
  getToken
@@ -20426,7 +20438,9 @@ async function fetchReport({
20426
20438
  getToken,
20427
20439
  eventTracking,
20428
20440
  tenants,
20429
- skipPivotFetch: usePivotTask
20441
+ // When not using pivot-template, avoid fallback pivot-template fetches.
20442
+ skipPivotFetch: !usePivotTask,
20443
+ overwriteCache
20430
20444
  });
20431
20445
  } catch (error) {
20432
20446
  if (error instanceof Error && error.name === "AbortError") {
@@ -20476,7 +20490,8 @@ async function processReportResponse({
20476
20490
  getToken,
20477
20491
  eventTracking,
20478
20492
  tenants,
20479
- skipPivotFetch = false
20493
+ skipPivotFetch = false,
20494
+ overwriteCache
20480
20495
  }) {
20481
20496
  const shouldSkipPivotFetch = skipPivotFetch || !!resp?.pivotRows && !!resp?.fields;
20482
20497
  const dashboardItem = {
@@ -20509,7 +20524,8 @@ async function processReportResponse({
20509
20524
  getToken,
20510
20525
  tenants,
20511
20526
  eventTracking,
20512
- skipPivotFetch: shouldSkipPivotFetch
20527
+ skipPivotFetch: shouldSkipPivotFetch,
20528
+ overwriteCache
20513
20529
  });
20514
20530
  if (additionalProcessing) {
20515
20531
  reportInfo.pagination = additionalProcessing.page;
@@ -21586,6 +21602,1799 @@ async function getClientTenantIds({
21586
21602
 
21587
21603
  // src/Context.tsx
21588
21604
  init_columnProcessing();
21605
+
21606
+ // src/utils/cacheCab.ts
21607
+ init_dataFetcher();
21608
+
21609
+ // src/utils/inMemoryFilterEngine.ts
21610
+ init_Filter();
21611
+ var import_date_fns8 = require("date-fns");
21612
+ init_dateRangePickerUtils();
21613
+ var UNSET = Symbol("unset");
21614
+ var isFilter = (f) => {
21615
+ return f && typeof f === "object" && "filterType" in f && !("id" in f);
21616
+ };
21617
+ var isDashboardFilterUpdate = (f) => {
21618
+ return f && typeof f === "object" && "label" in f;
21619
+ };
21620
+ var normalizeFilterString = (value) => value.replaceAll("%", "").toLowerCase();
21621
+ var normalizeRowString = (value) => value.toLowerCase();
21622
+ var resolveFieldKeys = (field, table, resolver) => {
21623
+ if (!field) return [];
21624
+ const resolved = resolver?.(field, table);
21625
+ if (Array.isArray(resolved)) return resolved;
21626
+ if (typeof resolved === "string") return [resolved];
21627
+ return [field];
21628
+ };
21629
+ var getRowValue = (row, fieldKeys, cache) => {
21630
+ if (fieldKeys.length === 0) return void 0;
21631
+ const cacheKey = fieldKeys.join("|");
21632
+ if (Object.prototype.hasOwnProperty.call(cache, cacheKey)) {
21633
+ return cache[cacheKey];
21634
+ }
21635
+ for (const key of fieldKeys) {
21636
+ if (Object.prototype.hasOwnProperty.call(row, key)) {
21637
+ cache[cacheKey] = row[key];
21638
+ return row[key];
21639
+ }
21640
+ }
21641
+ cache[cacheKey] = void 0;
21642
+ return void 0;
21643
+ };
21644
+ var coerceNumber = (value) => {
21645
+ if (typeof value === "number" && Number.isFinite(value)) return value;
21646
+ if (typeof value === "string" && value !== "") {
21647
+ const parsed = Number(value);
21648
+ return Number.isFinite(parsed) ? parsed : null;
21649
+ }
21650
+ return null;
21651
+ };
21652
+ var coerceBoolean = (value) => {
21653
+ if (typeof value === "boolean") return value;
21654
+ if (typeof value === "number") return value !== 0;
21655
+ if (typeof value === "string") {
21656
+ const normalized = value.toLowerCase();
21657
+ if (normalized === "true" || normalized === "1") return true;
21658
+ if (normalized === "false" || normalized === "0") return false;
21659
+ }
21660
+ return null;
21661
+ };
21662
+ var toDateMs = (value) => {
21663
+ if (value instanceof Date) {
21664
+ return (0, import_date_fns8.isValid)(value) ? value.getTime() : null;
21665
+ }
21666
+ if (typeof value === "number") {
21667
+ const date = new Date(value);
21668
+ return (0, import_date_fns8.isValid)(date) ? date.getTime() : null;
21669
+ }
21670
+ if (typeof value === "string") {
21671
+ const date = new Date(value);
21672
+ return (0, import_date_fns8.isValid)(date) ? date.getTime() : null;
21673
+ }
21674
+ return null;
21675
+ };
21676
+ var buildColumnTypeMap = (columns) => {
21677
+ if (!columns?.length) return null;
21678
+ const map = /* @__PURE__ */ Object.create(null);
21679
+ for (const column of columns) {
21680
+ map[column.field] = column.jsType;
21681
+ }
21682
+ return map;
21683
+ };
21684
+ var resolveDashboardField = (filter, options) => {
21685
+ const mapped = options.filterMap?.[filter.label];
21686
+ if (mapped?.field) {
21687
+ return { field: mapped.field, table: mapped.table };
21688
+ }
21689
+ if (filter.filterType === "date_range" /* Date */ && options.dateField?.field) {
21690
+ return { field: options.dateField.field, table: options.dateField.table };
21691
+ }
21692
+ if (filter.field) {
21693
+ return { field: filter.field, table: filter.table };
21694
+ }
21695
+ return null;
21696
+ };
21697
+ var buildRelativeDateRange = (operator, value, now2, weekStartsOn) => {
21698
+ const amount = value.value || 1;
21699
+ const unit = value.unit;
21700
+ const currentStart = (() => {
21701
+ switch (unit) {
21702
+ case TimeUnit.Hour:
21703
+ return (0, import_date_fns8.startOfHour)(now2);
21704
+ case TimeUnit.Day:
21705
+ return (0, import_date_fns8.startOfDay)(now2);
21706
+ case TimeUnit.Week:
21707
+ return (0, import_date_fns8.startOfWeek)(now2, { weekStartsOn });
21708
+ case TimeUnit.Month:
21709
+ return (0, import_date_fns8.startOfMonth)(now2);
21710
+ case TimeUnit.Quarter:
21711
+ return (0, import_date_fns8.startOfQuarter)(now2);
21712
+ case TimeUnit.Year:
21713
+ return (0, import_date_fns8.startOfYear)(now2);
21714
+ default:
21715
+ return (0, import_date_fns8.startOfDay)(now2);
21716
+ }
21717
+ })();
21718
+ const addUnit = (base, multiplier) => {
21719
+ switch (unit) {
21720
+ case TimeUnit.Hour:
21721
+ return (0, import_date_fns8.addHours)(base, multiplier);
21722
+ case TimeUnit.Day:
21723
+ return (0, import_date_fns8.addDays)(base, multiplier);
21724
+ case TimeUnit.Week:
21725
+ return (0, import_date_fns8.addWeeks)(base, multiplier);
21726
+ case TimeUnit.Month:
21727
+ return (0, import_date_fns8.addMonths)(base, multiplier);
21728
+ case TimeUnit.Quarter:
21729
+ return (0, import_date_fns8.addMonths)(base, multiplier * 3);
21730
+ case TimeUnit.Year:
21731
+ return (0, import_date_fns8.addYears)(base, multiplier);
21732
+ default:
21733
+ return (0, import_date_fns8.addDays)(base, multiplier);
21734
+ }
21735
+ };
21736
+ const subUnit = (base, multiplier) => {
21737
+ switch (unit) {
21738
+ case TimeUnit.Hour:
21739
+ return (0, import_date_fns8.subHours)(base, multiplier);
21740
+ case TimeUnit.Day:
21741
+ return (0, import_date_fns8.subDays)(base, multiplier);
21742
+ case TimeUnit.Week:
21743
+ return (0, import_date_fns8.subWeeks)(base, multiplier);
21744
+ case TimeUnit.Month:
21745
+ return (0, import_date_fns8.subMonths)(base, multiplier);
21746
+ case TimeUnit.Quarter:
21747
+ return (0, import_date_fns8.subMonths)(base, multiplier * 3);
21748
+ case TimeUnit.Year:
21749
+ return (0, import_date_fns8.subYears)(base, multiplier);
21750
+ default:
21751
+ return (0, import_date_fns8.subDays)(base, multiplier);
21752
+ }
21753
+ };
21754
+ switch (operator) {
21755
+ case DateOperator.InTheLast: {
21756
+ const start2 = subUnit(now2, amount);
21757
+ return { start: start2.getTime() };
21758
+ }
21759
+ case DateOperator.InThePrevious: {
21760
+ const start2 = subUnit(currentStart, amount);
21761
+ return { start: start2.getTime(), end: currentStart.getTime(), endExclusive: true };
21762
+ }
21763
+ case DateOperator.InTheCurrent: {
21764
+ const end = addUnit(currentStart, 1);
21765
+ return {
21766
+ start: currentStart.getTime(),
21767
+ end: end.getTime(),
21768
+ endExclusive: true
21769
+ };
21770
+ }
21771
+ default:
21772
+ return null;
21773
+ }
21774
+ };
21775
+ var buildStringPredicate = (operator, value, fieldKeys) => {
21776
+ if (value === void 0 || value === null) return null;
21777
+ const normalizedValue = Array.isArray(value) ? value.map((v) => normalizeFilterString(String(v))) : normalizeFilterString(String(value));
21778
+ if (Array.isArray(normalizedValue)) {
21779
+ if (normalizedValue.length === 0) return null;
21780
+ } else if (normalizedValue === "") {
21781
+ return null;
21782
+ }
21783
+ if (operator === StringOperator.Is || operator === StringOperator.IsNot) {
21784
+ const values = Array.isArray(normalizedValue) ? normalizedValue : [normalizedValue];
21785
+ const valueSet = new Set(values);
21786
+ return (row, cache) => {
21787
+ const rowValue = getRowValue(row, fieldKeys, cache);
21788
+ if (rowValue === null || rowValue === void 0) return false;
21789
+ const normalized = normalizeRowString(String(rowValue));
21790
+ const hasValue = valueSet.has(normalized);
21791
+ return operator === StringOperator.Is ? hasValue : !hasValue;
21792
+ };
21793
+ }
21794
+ if (Array.isArray(normalizedValue)) {
21795
+ return null;
21796
+ }
21797
+ return (row, cache) => {
21798
+ const rowValue = getRowValue(row, fieldKeys, cache);
21799
+ if (rowValue === null || rowValue === void 0) return false;
21800
+ const normalizedRow = normalizeRowString(String(rowValue));
21801
+ switch (operator) {
21802
+ case StringOperator.IsExactly:
21803
+ return normalizedRow === normalizedValue;
21804
+ case StringOperator.IsNotExactly:
21805
+ return normalizedRow !== normalizedValue;
21806
+ case StringOperator.Contains:
21807
+ return normalizedRow.includes(normalizedValue);
21808
+ default:
21809
+ return false;
21810
+ }
21811
+ };
21812
+ };
21813
+ var buildNumericPredicate = (operator, value, fieldKeys) => {
21814
+ const filterValue = coerceNumber(value);
21815
+ if (filterValue === null) return null;
21816
+ return (row, cache) => {
21817
+ const rowValue = getRowValue(row, fieldKeys, cache);
21818
+ const parsed = coerceNumber(rowValue);
21819
+ if (parsed === null) return false;
21820
+ switch (operator) {
21821
+ case NumberOperator.EqualTo:
21822
+ return parsed === filterValue;
21823
+ case NumberOperator.NotEqualTo:
21824
+ return parsed !== filterValue;
21825
+ case NumberOperator.GreaterThan:
21826
+ return parsed > filterValue;
21827
+ case NumberOperator.LessThan:
21828
+ return parsed < filterValue;
21829
+ case NumberOperator.GreaterThanOrEqualTo:
21830
+ return parsed >= filterValue;
21831
+ case NumberOperator.LessThanOrEqualTo:
21832
+ return parsed <= filterValue;
21833
+ default:
21834
+ return false;
21835
+ }
21836
+ };
21837
+ };
21838
+ var buildNullPredicate = (operator, fieldKeys) => {
21839
+ return (row, cache) => {
21840
+ const rowValue = getRowValue(row, fieldKeys, cache);
21841
+ const isNullish = rowValue === null || rowValue === void 0;
21842
+ return operator === NullOperator.IsNull ? isNullish : !isNullish;
21843
+ };
21844
+ };
21845
+ var buildBooleanPredicate = (operator, value, fieldKeys) => {
21846
+ const filterValue = coerceBoolean(value);
21847
+ if (filterValue === null) return null;
21848
+ return (row, cache) => {
21849
+ const rowValue = getRowValue(row, fieldKeys, cache);
21850
+ const parsed = coerceBoolean(rowValue);
21851
+ if (parsed === null) return false;
21852
+ return operator === BoolOperator.EqualTo ? parsed === filterValue : parsed !== filterValue;
21853
+ };
21854
+ };
21855
+ var buildDateComparisonPredicate = (operator, value, fieldKeys) => {
21856
+ const filterDate = toDateMs(value);
21857
+ if (filterDate === null) return null;
21858
+ return (row, cache) => {
21859
+ const rowValue = getRowValue(row, fieldKeys, cache);
21860
+ const rowDate = toDateMs(rowValue);
21861
+ if (rowDate === null) return false;
21862
+ switch (operator) {
21863
+ case DateOperator.EqualTo:
21864
+ return rowDate === filterDate;
21865
+ case DateOperator.NotEqualTo:
21866
+ return rowDate !== filterDate;
21867
+ case DateOperator.GreaterThan:
21868
+ return rowDate > filterDate;
21869
+ case DateOperator.LessThan:
21870
+ return rowDate < filterDate;
21871
+ case DateOperator.GreaterThanOrEqualTo:
21872
+ return rowDate >= filterDate;
21873
+ case DateOperator.LessThanOrEqualTo:
21874
+ return rowDate <= filterDate;
21875
+ default:
21876
+ return false;
21877
+ }
21878
+ };
21879
+ };
21880
+ var buildDateRangePredicate = (range, fieldKeys) => {
21881
+ if (range.start === void 0 && range.end === void 0) return null;
21882
+ return (row, cache) => {
21883
+ const rowValue = getRowValue(row, fieldKeys, cache);
21884
+ const rowDate = toDateMs(rowValue);
21885
+ if (rowDate === null) return false;
21886
+ if (range.start !== void 0 && rowDate < range.start) return false;
21887
+ if (range.end !== void 0) {
21888
+ if (range.endExclusive) {
21889
+ return rowDate < range.end;
21890
+ }
21891
+ return rowDate <= range.end;
21892
+ }
21893
+ return true;
21894
+ };
21895
+ };
21896
+ var buildCustomDatePredicate = (value, fieldKeys) => {
21897
+ const start2 = value.startDate ? toDateMs(value.startDate) : null;
21898
+ const end = value.endDate ? toDateMs(value.endDate) : null;
21899
+ if (start2 === null && end === null) return null;
21900
+ return buildDateRangePredicate(
21901
+ {
21902
+ start: start2 ?? void 0,
21903
+ end: end ?? void 0,
21904
+ endExclusive: false
21905
+ },
21906
+ fieldKeys
21907
+ );
21908
+ };
21909
+ var compileCustomFilter = (filter, options) => {
21910
+ const fieldKeys = resolveFieldKeys(
21911
+ filter.field,
21912
+ filter.table,
21913
+ options.fieldKeyResolver
21914
+ );
21915
+ if (fieldKeys.length === 0) return null;
21916
+ switch (filter.filterType) {
21917
+ case "string-filter" /* StringFilter */:
21918
+ case "string-in-filter" /* StringInFilter */:
21919
+ return buildStringPredicate(
21920
+ filter.operator,
21921
+ filter.value,
21922
+ fieldKeys
21923
+ );
21924
+ case "numeric-filter" /* NumericFilter */:
21925
+ return buildNumericPredicate(
21926
+ filter.operator,
21927
+ filter.value,
21928
+ fieldKeys
21929
+ );
21930
+ case "null-filter" /* NullFilter */:
21931
+ return buildNullPredicate(
21932
+ filter.operator,
21933
+ fieldKeys
21934
+ );
21935
+ case "boolean-filter" /* BooleanFilter */:
21936
+ return buildBooleanPredicate(
21937
+ filter.operator,
21938
+ filter.value,
21939
+ fieldKeys
21940
+ );
21941
+ case "date-custom-filter" /* DateCustomFilter */:
21942
+ return buildCustomDatePredicate(
21943
+ filter.value,
21944
+ fieldKeys
21945
+ );
21946
+ case "date-comparison-filter" /* DateComparisonFilter */:
21947
+ return buildDateComparisonPredicate(
21948
+ filter.operator,
21949
+ filter.value,
21950
+ fieldKeys
21951
+ );
21952
+ case "date-filter" /* DateFilter */: {
21953
+ const value = filter.value;
21954
+ if (!value?.unit) return null;
21955
+ const now2 = options.now ?? /* @__PURE__ */ new Date();
21956
+ const range = buildRelativeDateRange(
21957
+ filter.operator,
21958
+ value,
21959
+ now2,
21960
+ options.weekStartsOn ?? 0
21961
+ );
21962
+ if (!range) return null;
21963
+ return buildDateRangePredicate(range, fieldKeys);
21964
+ }
21965
+ default:
21966
+ return null;
21967
+ }
21968
+ };
21969
+ var compileDashboardFilter = (filter, options, columnTypeMap) => {
21970
+ const resolved = resolveDashboardField(filter, options);
21971
+ if (!resolved?.field) return null;
21972
+ const fieldKeys = resolveFieldKeys(
21973
+ resolved.field,
21974
+ resolved.table,
21975
+ options.fieldKeyResolver
21976
+ );
21977
+ if (fieldKeys.length === 0) return null;
21978
+ switch (filter.filterType) {
21979
+ case "string" /* String */: {
21980
+ const stringFilter = filter;
21981
+ if (stringFilter.stringFilterType === "multiselect" /* Multiselect */) {
21982
+ if (!stringFilter.values || stringFilter.values.length === 0) {
21983
+ return null;
21984
+ }
21985
+ return buildStringPredicate(
21986
+ StringOperator.Is,
21987
+ stringFilter.values,
21988
+ fieldKeys
21989
+ );
21990
+ }
21991
+ if (!stringFilter.selectedValue) return null;
21992
+ return buildStringPredicate(
21993
+ StringOperator.IsExactly,
21994
+ stringFilter.selectedValue,
21995
+ fieldKeys
21996
+ );
21997
+ }
21998
+ case "date_range" /* Date */: {
21999
+ const dateFilter = filter;
22000
+ const start2 = dateFilter.startDate ? dateFilter.startDate.getTime() : void 0;
22001
+ const end = dateFilter.endDate ? dateFilter.endDate.getTime() : void 0;
22002
+ return buildDateRangePredicate(
22003
+ { start: start2, end, endExclusive: false },
22004
+ fieldKeys
22005
+ );
22006
+ }
22007
+ case "tenant" /* Tenant */: {
22008
+ const tenantFilter = filter;
22009
+ if (!tenantFilter.values || tenantFilter.values.length === 0) {
22010
+ return null;
22011
+ }
22012
+ const normalizedValues = tenantFilter.values.map(
22013
+ (v) => normalizeFilterString(String(v))
22014
+ );
22015
+ const valueSet = new Set(normalizedValues);
22016
+ const fieldType = columnTypeMap?.[resolved.field] ?? "string";
22017
+ return (row, cache) => {
22018
+ const rowValue = getRowValue(row, fieldKeys, cache);
22019
+ if (rowValue === null || rowValue === void 0) return false;
22020
+ if (fieldType === "number") {
22021
+ const numeric = coerceNumber(rowValue);
22022
+ return numeric !== null && valueSet.has(normalizeFilterString(String(numeric)));
22023
+ }
22024
+ return valueSet.has(normalizeRowString(String(rowValue)));
22025
+ };
22026
+ }
22027
+ default:
22028
+ return null;
22029
+ }
22030
+ };
22031
+ var updateDashboardFilters = (filtersToUpdate, dashboardFilters) => {
22032
+ return dashboardFilters.map((filter) => {
22033
+ const update = filtersToUpdate.find((u) => u.label === filter.label);
22034
+ if (!update) return filter;
22035
+ if (filter.filterType === "string" /* String */) {
22036
+ if (filter.stringFilterType === "multiselect" /* Multiselect */) {
22037
+ return {
22038
+ ...filter,
22039
+ values: update.value
22040
+ };
22041
+ }
22042
+ return {
22043
+ ...filter,
22044
+ selectedValue: update.value
22045
+ };
22046
+ }
22047
+ if (filter.filterType === "date_range" /* Date */) {
22048
+ const presetOptions = convertPresetOptionsToSelectableList(
22049
+ filter.presetOptions ?? [],
22050
+ filter.defaultPresetRanges ?? []
22051
+ );
22052
+ const value = update.value;
22053
+ const preset = presetOptions.find((p) => {
22054
+ const pStart = p.startDate ? new Date(p.startDate).toISOString() : void 0;
22055
+ const vStart = value.startDate ? new Date(value.startDate).toISOString() : void 0;
22056
+ const pEnd = p.endDate ? new Date(p.endDate).toISOString() : void 0;
22057
+ const vEnd = value.endDate ? new Date(value.endDate).toISOString() : void 0;
22058
+ return pStart === vStart && pEnd === vEnd;
22059
+ });
22060
+ if (!preset) {
22061
+ return { ...filter, startDate: value.startDate, endDate: value.endDate };
22062
+ }
22063
+ return {
22064
+ ...filter,
22065
+ preset,
22066
+ startDate: value.startDate,
22067
+ endDate: value.endDate
22068
+ };
22069
+ }
22070
+ if (filter.filterType === "tenant" /* Tenant */) {
22071
+ const value = update.value;
22072
+ let values;
22073
+ if (Array.isArray(value)) {
22074
+ values = value;
22075
+ } else if (typeof value === "string") {
22076
+ values = [value];
22077
+ } else {
22078
+ values = [];
22079
+ }
22080
+ return {
22081
+ ...filter,
22082
+ values
22083
+ };
22084
+ }
22085
+ return filter;
22086
+ });
22087
+ };
22088
+ var compileApplyFiltersPredicate = (filters, options) => {
22089
+ const dashboardUpdates = filters.filter(isDashboardFilterUpdate);
22090
+ const customFilters = filters.filter(isFilter);
22091
+ const internalCustomFilters = customFilters.map((filter) => {
22092
+ try {
22093
+ return convertCustomFilter(filter);
22094
+ } catch (error) {
22095
+ return null;
22096
+ }
22097
+ }).concat(options.customFilters ?? []).filter((filter) => filter !== null && filter !== void 0);
22098
+ const dashboardFilters = options.dashboardFilters ?? [];
22099
+ const updatedDashboardFilters = dashboardUpdates.length ? updateDashboardFilters(dashboardUpdates, dashboardFilters) : dashboardFilters;
22100
+ const columnTypeMap = buildColumnTypeMap(options.columns);
22101
+ const predicates = [];
22102
+ for (const filter of internalCustomFilters) {
22103
+ const predicate = compileCustomFilter(filter, options);
22104
+ if (predicate) predicates.push(predicate);
22105
+ }
22106
+ for (const filter of updatedDashboardFilters) {
22107
+ const predicate = compileDashboardFilter(
22108
+ filter,
22109
+ options,
22110
+ columnTypeMap
22111
+ );
22112
+ if (predicate) predicates.push(predicate);
22113
+ }
22114
+ if (predicates.length === 0) {
22115
+ return { predicate: () => true, hasPredicates: false };
22116
+ }
22117
+ return {
22118
+ predicate: (row) => {
22119
+ const cache = /* @__PURE__ */ Object.create(null);
22120
+ for (const predicate of predicates) {
22121
+ if (!predicate(row, cache)) return false;
22122
+ }
22123
+ return true;
22124
+ },
22125
+ hasPredicates: true
22126
+ };
22127
+ };
22128
+ var applyFiltersInMemory = (rows, filters, options) => {
22129
+ if (!rows.length) return rows;
22130
+ const { predicate, hasPredicates } = compileApplyFiltersPredicate(
22131
+ filters,
22132
+ options
22133
+ );
22134
+ if (!hasPredicates) return rows;
22135
+ const results = [];
22136
+ for (let i = 0; i < rows.length; i += 1) {
22137
+ const row = rows[i];
22138
+ if (predicate(row)) {
22139
+ results.push(row);
22140
+ }
22141
+ }
22142
+ return results;
22143
+ };
22144
+
22145
+ // src/utils/inMemoryPivotEngine.ts
22146
+ init_columnType();
22147
+ var MS_IN_DAY = 24 * 60 * 60 * 1e3;
22148
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
22149
+ var INVALID_DATE_KEY = "-2026";
22150
+ function singleAggToMultiAgg(pivot) {
22151
+ if (pivot.aggregations) {
22152
+ return pivot;
22153
+ }
22154
+ const newPivot = { ...pivot };
22155
+ const newAgg = { aggregationType: pivot.aggregationType };
22156
+ const fieldsToCopy = ["valueField", "valueFieldType", "valueField2", "valueField2Type"];
22157
+ fieldsToCopy.forEach((x) => {
22158
+ if (pivot[x]) {
22159
+ newAgg[x] = pivot[x];
22160
+ delete newPivot[x];
22161
+ }
22162
+ });
22163
+ newPivot.aggregations = [newAgg];
22164
+ return newPivot;
22165
+ }
22166
+ function isDateFormat2(xAxisFormat) {
22167
+ const DATE_FORMATS = [
22168
+ "yyyy",
22169
+ "mmm_dd",
22170
+ "mmm_yyyy",
22171
+ "mmm_dd_yyyy",
22172
+ "hh_ap_pm",
22173
+ "mmm_dd-mmm_dd",
22174
+ "mmm_dd_hh:mm_ap_pm",
22175
+ "wo, yyyy"
22176
+ ];
22177
+ const isDate = DATE_FORMATS.includes(xAxisFormat.toLowerCase());
22178
+ return isDate;
22179
+ }
22180
+ function isValidDate3(date) {
22181
+ try {
22182
+ return date instanceof Date && !isNaN(date.getTime());
22183
+ } catch {
22184
+ return false;
22185
+ }
22186
+ }
22187
+ function inferDateBucketFromFilters(pivot, filters) {
22188
+ if (!pivot?.rowFieldType) {
22189
+ return void 0;
22190
+ }
22191
+ const normalizedType = String(pivot.rowFieldType).toLowerCase();
22192
+ if (isDateFormat2(normalizedType)) {
22193
+ switch (normalizedType) {
22194
+ case "mmm_dd-mmm_dd":
22195
+ return "week";
22196
+ case "yyyy":
22197
+ case "wo, yyyy":
22198
+ return "year";
22199
+ case "mmm_dd_hh:mm_ap_pm":
22200
+ case "hh_ap_pm":
22201
+ return "day";
22202
+ default:
22203
+ return "month";
22204
+ }
22205
+ }
22206
+ const isDateLike = isDateType(normalizedType);
22207
+ if (!isDateLike) {
22208
+ return void 0;
22209
+ }
22210
+ let earliest;
22211
+ let latest;
22212
+ const extractTimestamp = (value) => {
22213
+ if (!value) {
22214
+ return void 0;
22215
+ }
22216
+ if (value instanceof Date) {
22217
+ return value.getTime();
22218
+ }
22219
+ const parsed = Date.parse(value);
22220
+ return Number.isNaN(parsed) ? void 0 : parsed;
22221
+ };
22222
+ (Array.isArray(filters) ? filters : []).forEach((filter) => {
22223
+ if (!filter || filter.filterType !== "date_range") {
22224
+ return;
22225
+ }
22226
+ if (filter.primaryRange?.value === "ALL_TIME") {
22227
+ earliest = -1;
22228
+ return;
22229
+ }
22230
+ const possibleStarts = [
22231
+ filter.startDate,
22232
+ filter.start,
22233
+ filter.primaryRange?.startDate,
22234
+ filter.primaryRange?.start,
22235
+ filter.range?.startDate,
22236
+ filter.range?.start
22237
+ ];
22238
+ const possibleEnds = [
22239
+ filter.endDate,
22240
+ filter.end,
22241
+ filter.primaryRange?.endDate,
22242
+ filter.primaryRange?.end,
22243
+ filter.range?.endDate,
22244
+ filter.range?.end
22245
+ ];
22246
+ possibleStarts.forEach((value) => {
22247
+ const timestamp = extractTimestamp(value);
22248
+ if (timestamp === void 0) {
22249
+ return;
22250
+ }
22251
+ earliest = earliest === void 0 ? timestamp : Math.min(earliest, timestamp);
22252
+ });
22253
+ possibleEnds.forEach((value) => {
22254
+ const timestamp = extractTimestamp(value);
22255
+ if (timestamp === void 0) {
22256
+ return;
22257
+ }
22258
+ latest = latest === void 0 ? timestamp : Math.max(latest, timestamp);
22259
+ });
22260
+ });
22261
+ if (earliest === -1) {
22262
+ return "month";
22263
+ }
22264
+ if (earliest === void 0 || latest === void 0) {
22265
+ return void 0;
22266
+ }
22267
+ if (latest < earliest) {
22268
+ [earliest, latest] = [latest, earliest];
22269
+ }
22270
+ const diffInDays = Math.max(1, Math.round((latest - earliest) / MS_IN_DAY));
22271
+ if (diffInDays < 20) {
22272
+ return "day";
22273
+ }
22274
+ if (diffInDays <= 59) {
22275
+ return "week";
22276
+ }
22277
+ if (diffInDays <= 400) {
22278
+ return "month";
22279
+ }
22280
+ return "year";
22281
+ }
22282
+ function getDateRangeFromFilters(filters) {
22283
+ let earliest;
22284
+ let latest;
22285
+ const extractTimestamp = (value) => {
22286
+ if (!value) return void 0;
22287
+ if (value instanceof Date) return value.getTime();
22288
+ const parsed = Date.parse(value);
22289
+ return Number.isNaN(parsed) ? void 0 : parsed;
22290
+ };
22291
+ (Array.isArray(filters) ? filters : []).forEach((filter) => {
22292
+ if (!filter || filter.filterType !== "date_range") return;
22293
+ if (filter.primaryRange?.value === "ALL_TIME") return;
22294
+ const possibleStarts = [
22295
+ filter.startDate,
22296
+ filter.start,
22297
+ filter.primaryRange?.startDate,
22298
+ filter.primaryRange?.start,
22299
+ filter.range?.startDate,
22300
+ filter.range?.start
22301
+ ];
22302
+ const possibleEnds = [
22303
+ filter.endDate,
22304
+ filter.end,
22305
+ filter.primaryRange?.endDate,
22306
+ filter.primaryRange?.end,
22307
+ filter.range?.endDate,
22308
+ filter.range?.end
22309
+ ];
22310
+ possibleStarts.forEach((v) => {
22311
+ const ts = extractTimestamp(v);
22312
+ if (ts === void 0) return;
22313
+ earliest = earliest === void 0 ? ts : Math.min(earliest, ts);
22314
+ });
22315
+ possibleEnds.forEach((v) => {
22316
+ const ts = extractTimestamp(v);
22317
+ if (ts === void 0) return;
22318
+ latest = latest === void 0 ? ts : Math.max(latest, ts);
22319
+ });
22320
+ });
22321
+ if (earliest === void 0 || latest === void 0) return void 0;
22322
+ if (latest < earliest) [earliest, latest] = [latest, earliest];
22323
+ return {
22324
+ start: new Date(earliest),
22325
+ end: new Date(latest)
22326
+ };
22327
+ }
22328
+ function generateBucketKeys(start2, end, bucket) {
22329
+ const keys = /* @__PURE__ */ new Set();
22330
+ const startDay = new Date(Date.UTC(start2.getUTCFullYear(), start2.getUTCMonth(), start2.getUTCDate()));
22331
+ const endDay = new Date(Date.UTC(end.getUTCFullYear(), end.getUTCMonth(), end.getUTCDate()));
22332
+ const cur = new Date(startDay);
22333
+ while (cur <= endDay) {
22334
+ keys.add(getDateKey(cur, bucket));
22335
+ cur.setUTCDate(cur.getUTCDate() + 1);
22336
+ }
22337
+ return Array.from(keys).sort((a, b) => parseInt(a) - parseInt(b));
22338
+ }
22339
+ function buildEmptyAggRow(aggregations) {
22340
+ const multiAgg = aggregations.length > 1;
22341
+ const empty = {};
22342
+ aggregations.forEach((agg) => {
22343
+ const { aggregationType: type, valueField } = agg;
22344
+ const key = !valueField ? `${type}` + (multiAgg ? `_${type}` : "") : `${valueField}` + (multiAgg ? `_${type}` : "");
22345
+ empty[key] = 0;
22346
+ });
22347
+ return empty;
22348
+ }
22349
+ function getBucketRange(dateKey, bucket) {
22350
+ const d = new Date(parseInt(dateKey, 10));
22351
+ let start2 = new Date(d);
22352
+ let end = new Date(d);
22353
+ switch (bucket) {
22354
+ case "day":
22355
+ start2 = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
22356
+ end = new Date(start2);
22357
+ break;
22358
+ case "week":
22359
+ start2 = new Date(d);
22360
+ end = new Date(start2);
22361
+ end.setUTCDate(start2.getUTCDate() + 6);
22362
+ break;
22363
+ case "month":
22364
+ start2 = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1));
22365
+ end = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 0));
22366
+ break;
22367
+ case "year":
22368
+ start2 = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
22369
+ end = new Date(Date.UTC(d.getUTCFullYear(), 11, 31));
22370
+ break;
22371
+ }
22372
+ return { start: start2, end };
22373
+ }
22374
+ function formatBucketNameFromRange(start2, end, bucket) {
22375
+ const pad = (n) => String(n).padStart(2, "0");
22376
+ switch (bucket) {
22377
+ case "day":
22378
+ return `${pad(start2.getUTCDate())} ${MONTHS[start2.getUTCMonth()]} ${start2.getUTCFullYear()}`;
22379
+ case "week": {
22380
+ const sameMonth = start2.getUTCMonth() === end.getUTCMonth();
22381
+ return sameMonth ? `${MONTHS[start2.getUTCMonth()]} ${start2.getUTCDate()} - ${end.getUTCDate()}` : `${MONTHS[start2.getUTCMonth()]} ${start2.getUTCDate()} - ${MONTHS[end.getUTCMonth()]} ${end.getUTCDate()}`;
22382
+ }
22383
+ case "month":
22384
+ return `${MONTHS[start2.getUTCMonth()]} ${start2.getUTCFullYear()}`;
22385
+ case "year":
22386
+ return `${start2.getUTCFullYear()}`;
22387
+ default:
22388
+ return "";
22389
+ }
22390
+ }
22391
+ function getDateKey(date, bucket) {
22392
+ if (!isValidDate3(date)) {
22393
+ return INVALID_DATE_KEY;
22394
+ }
22395
+ switch (bucket) {
22396
+ case "day":
22397
+ return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()).toString();
22398
+ case "week": {
22399
+ const day = date.getUTCDay();
22400
+ const mondayUtc = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate() - (day + 6) % 7);
22401
+ return mondayUtc.toString();
22402
+ }
22403
+ case "month":
22404
+ return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1).toString();
22405
+ case "year":
22406
+ return Date.UTC(date.getUTCFullYear(), 0, 1).toString();
22407
+ default:
22408
+ return INVALID_DATE_KEY;
22409
+ }
22410
+ }
22411
+ function sortRows(rows, pivot) {
22412
+ try {
22413
+ const { sort, sortField, sortFieldType, sortDirection } = pivot;
22414
+ if (!sort || sortField == null || sortFieldType == null) return rows;
22415
+ const sortFunc = isBoolType(sortFieldType) ? (a, b) => a === b ? 0 : a ? 1 : -1 : isDateType(sortFieldType) ? (a, b) => {
22416
+ const ta = new Date(a), tb = new Date(b);
22417
+ const aValid = isValidDate3(ta), bValid = isValidDate3(tb);
22418
+ if (!aValid && !bValid) return 0;
22419
+ if (!aValid) return 1;
22420
+ if (!bValid) return -1;
22421
+ return ta.getTime() - tb.getTime();
22422
+ } : isStringType(sortFieldType) ? (a, b) => a.localeCompare(b) : (a, b) => a - b;
22423
+ const dir = sortDirection === "ASC" ? 1 : -1;
22424
+ rows.sort((a, b) => {
22425
+ const av = a[sortField], bv = b[sortField];
22426
+ if (av == null && bv == null) return 0;
22427
+ if (av == null) return 1;
22428
+ if (bv == null) return -1;
22429
+ return dir * sortFunc(av, bv);
22430
+ });
22431
+ } catch {
22432
+ console.warn(`Sorting failed.`);
22433
+ }
22434
+ return rows;
22435
+ }
22436
+ function assembleFinalRows(seen, rowKey, dateBucket, dateRange) {
22437
+ const allColumns = /* @__PURE__ */ new Set();
22438
+ Object.keys(seen).forEach((rowKeyVal) => {
22439
+ Object.keys(seen[rowKeyVal]).forEach((col) => {
22440
+ allColumns.add(col);
22441
+ });
22442
+ });
22443
+ const filled = {};
22444
+ Object.keys(seen).forEach((rowKeyVal) => {
22445
+ filled[rowKeyVal] = {};
22446
+ allColumns.forEach((col) => {
22447
+ const value = seen[rowKeyVal][col];
22448
+ filled[rowKeyVal][col] = value ?? 0;
22449
+ });
22450
+ });
22451
+ if (dateBucket) {
22452
+ return Object.keys(filled).sort((a, b) => parseInt(a) - parseInt(b)).map((k) => {
22453
+ if (k === INVALID_DATE_KEY) {
22454
+ return { [rowKey]: "Invalid Date", ...filled[k], __quillRawDate: 0 };
22455
+ }
22456
+ const { start: start2, end } = getBucketRange(k, dateBucket);
22457
+ let bucketStart = start2;
22458
+ let bucketEnd = end;
22459
+ if (dateRange) {
22460
+ if (bucketStart < dateRange.start) bucketStart = dateRange.start;
22461
+ if (bucketEnd > dateRange.end) bucketEnd = dateRange.end;
22462
+ }
22463
+ return {
22464
+ [rowKey]: formatBucketNameFromRange(bucketStart, bucketEnd, dateBucket),
22465
+ ...filled[k],
22466
+ __quillRawDate: bucketStart.toISOString()
22467
+ };
22468
+ });
22469
+ }
22470
+ return Object.keys(filled).sort().map((k) => ({ [rowKey]: k, ...filled[k] }));
22471
+ }
22472
+ function anyToNum(valueFieldType, obj) {
22473
+ if (!valueFieldType) {
22474
+ if (typeof obj === "number") return obj;
22475
+ if (typeof obj === "string" && !isNaN(Number(obj))) return Number(obj);
22476
+ return obj ? 1 : 0;
22477
+ }
22478
+ if (isNumberType(valueFieldType)) {
22479
+ return Number(obj);
22480
+ }
22481
+ return obj ? 1 : 0;
22482
+ }
22483
+ function updateAccumulator(acc, row, agg, isOneRow) {
22484
+ const {
22485
+ aggregationType: type,
22486
+ valueField,
22487
+ valueFieldType,
22488
+ valueField2,
22489
+ valueField2Type
22490
+ } = agg;
22491
+ if (!valueField) return;
22492
+ const distinctDenom = !!valueField2 && !!valueField2Type && valueField !== valueField2;
22493
+ const rawVal = row[valueField];
22494
+ if (valueFieldType && (type === "min" || type === "max") && (isDateType(valueFieldType) || isDateFormat2(valueFieldType))) {
22495
+ const dateVal = rawVal instanceof Date ? rawVal : new Date(rawVal);
22496
+ if (!isNaN(dateVal.getTime())) {
22497
+ if (type === "min") {
22498
+ acc.minDate = acc.minDate && acc.minDate.getTime() < dateVal.getTime() ? acc.minDate : dateVal;
22499
+ } else {
22500
+ acc.maxDate = acc.maxDate && acc.maxDate.getTime() > dateVal.getTime() ? acc.maxDate : dateVal;
22501
+ }
22502
+ }
22503
+ return;
22504
+ }
22505
+ const numVal = anyToNum(valueFieldType, rawVal);
22506
+ switch (type) {
22507
+ case "sum":
22508
+ acc.sum += numVal;
22509
+ break;
22510
+ case "average":
22511
+ case "avg":
22512
+ acc.sum += numVal;
22513
+ acc.count++;
22514
+ break;
22515
+ case "min":
22516
+ acc.min = acc.hasVal ? Math.min(acc.min, numVal) : numVal;
22517
+ acc.hasVal = true;
22518
+ break;
22519
+ case "max":
22520
+ acc.max = acc.hasVal ? Math.max(acc.max, numVal) : numVal;
22521
+ acc.hasVal = true;
22522
+ break;
22523
+ case "count":
22524
+ acc.count += numVal;
22525
+ break;
22526
+ case "percentage":
22527
+ acc.sum += numVal;
22528
+ acc.count += distinctDenom ? anyToNum(valueField2Type, row[valueField2]) : isOneRow ? 1 : numVal;
22529
+ break;
22530
+ }
22531
+ }
22532
+ function getFinalAggregationValue({
22533
+ type,
22534
+ valueFieldType,
22535
+ valueField,
22536
+ acc,
22537
+ distinctDenom = false,
22538
+ sumOfDenom,
22539
+ rowsLength,
22540
+ totalRowsForCount
22541
+ }) {
22542
+ if (valueFieldType && (type === "min" || type === "max") && (isDateType(valueFieldType) || isDateFormat2(valueFieldType))) {
22543
+ const dateVal = type === "min" ? acc.minDate : acc.maxDate;
22544
+ return dateVal?.toISOString() ?? "";
22545
+ }
22546
+ if (type === "count") {
22547
+ return totalRowsForCount ?? acc.count;
22548
+ }
22549
+ let final;
22550
+ if (!valueField && type === "percentage" && rowsLength !== void 0) {
22551
+ final = rowsLength ? (totalRowsForCount ?? 0) / rowsLength : 0;
22552
+ } else {
22553
+ switch (type) {
22554
+ case "sum":
22555
+ final = acc.sum;
22556
+ break;
22557
+ case "average":
22558
+ case "avg":
22559
+ final = acc.count ? acc.sum / acc.count : 0;
22560
+ break;
22561
+ case "min":
22562
+ final = acc.hasVal ? acc.min : 0;
22563
+ break;
22564
+ case "max":
22565
+ final = acc.hasVal ? acc.max : 0;
22566
+ break;
22567
+ case "percentage": {
22568
+ const denom = distinctDenom ? acc.count : sumOfDenom ?? acc.count;
22569
+ final = denom ? acc.sum / denom : 0;
22570
+ break;
22571
+ }
22572
+ default:
22573
+ final = 0;
22574
+ }
22575
+ }
22576
+ return final;
22577
+ }
22578
+ function aggregateToOneRow(rows, aggregations) {
22579
+ const multiAgg = aggregations.length > 1;
22580
+ const resultArray = aggregations.map((agg) => {
22581
+ const { aggregationType: type, valueField, valueFieldType } = agg;
22582
+ if (!valueField) {
22583
+ if (type !== "count") {
22584
+ return {};
22585
+ }
22586
+ const finalKey2 = "count" + (multiAgg ? "_count" : "");
22587
+ return { [finalKey2]: rows.length };
22588
+ }
22589
+ const finalKey = `${valueField}` + (multiAgg ? `_${type}` : "");
22590
+ const acc = {
22591
+ sum: 0,
22592
+ count: 0,
22593
+ min: Infinity,
22594
+ max: -Infinity,
22595
+ hasVal: false,
22596
+ minDate: null,
22597
+ maxDate: null
22598
+ };
22599
+ for (const row of rows) {
22600
+ updateAccumulator(acc, row, agg, true);
22601
+ }
22602
+ return {
22603
+ [finalKey]: getFinalAggregationValue({
22604
+ type,
22605
+ valueFieldType,
22606
+ valueField,
22607
+ acc,
22608
+ totalRowsForCount: acc.count
22609
+ })
22610
+ };
22611
+ });
22612
+ return [
22613
+ resultArray.reduce((acc, current) => {
22614
+ return { ...acc, ...current };
22615
+ }, {})
22616
+ ];
22617
+ }
22618
+ function aggregateWithColumn(rows, colKey, aggregations, getGroupKey) {
22619
+ if (!colKey) return;
22620
+ const seen = {};
22621
+ const multiAgg = aggregations.length > 1;
22622
+ aggregations.forEach((agg) => {
22623
+ const { aggregationType: type, valueField, valueFieldType, valueField2, valueField2Type } = agg;
22624
+ if (!valueField) {
22625
+ if (type !== "count" && type !== "percentage") return;
22626
+ }
22627
+ const distinctDenom = !!valueField2 && !!valueField2Type && valueField !== valueField2;
22628
+ const accs = {};
22629
+ rows.forEach((row) => {
22630
+ const groupKey = getGroupKey(row);
22631
+ const colVal = row[colKey];
22632
+ if (!accs[groupKey]) accs[groupKey] = {};
22633
+ if (!accs[groupKey][colVal]) {
22634
+ accs[groupKey][colVal] = {
22635
+ sum: 0,
22636
+ count: 0,
22637
+ min: Infinity,
22638
+ max: -Infinity,
22639
+ hasVal: false,
22640
+ minDate: null,
22641
+ maxDate: null,
22642
+ totalRows: 0
22643
+ };
22644
+ }
22645
+ const acc = accs[groupKey][colVal];
22646
+ acc.totalRows += 1;
22647
+ if (!valueField) {
22648
+ if (type === "count") acc.count += 1;
22649
+ else if (type === "percentage") acc.sum += 1;
22650
+ return;
22651
+ }
22652
+ updateAccumulator(acc, row, agg, false);
22653
+ });
22654
+ Object.keys(accs).forEach((groupKey) => {
22655
+ if (!seen[groupKey]) seen[groupKey] = {};
22656
+ const sumOfDenom = Object.values(accs[groupKey]).reduce((t, a) => t + a.count, 0);
22657
+ Object.keys(accs[groupKey]).forEach((colVal) => {
22658
+ const acc = accs[groupKey][colVal];
22659
+ const finalKey = `${colVal}` + (multiAgg ? `_${type}` : "");
22660
+ seen[groupKey][finalKey] = getFinalAggregationValue({
22661
+ type,
22662
+ valueFieldType,
22663
+ valueField,
22664
+ acc,
22665
+ distinctDenom,
22666
+ sumOfDenom,
22667
+ totalRowsForCount: acc.totalRows
22668
+ });
22669
+ });
22670
+ });
22671
+ });
22672
+ return seen;
22673
+ }
22674
+ function aggregateWithoutColumn(rows, aggregations, getGroupKey) {
22675
+ const seen = {};
22676
+ const multiAgg = aggregations.length > 1;
22677
+ aggregations.forEach((agg) => {
22678
+ const { aggregationType: type, valueField, valueFieldType, valueField2, valueField2Type } = agg;
22679
+ if (!valueField) {
22680
+ if (type !== "count" && type !== "percentage") return;
22681
+ }
22682
+ const finalKey = !valueField ? `${type}` + (multiAgg ? `_${type}` : "") : `${valueField}` + (multiAgg ? `_${type}` : "");
22683
+ const distinctDenom = !!valueField2 && !!valueField2Type && valueField !== valueField2;
22684
+ const accs = {};
22685
+ rows.forEach((row) => {
22686
+ const key = getGroupKey(row);
22687
+ if (!seen[key]) seen[key] = {};
22688
+ if (!accs[key]) {
22689
+ accs[key] = {
22690
+ sum: 0,
22691
+ count: 0,
22692
+ min: Infinity,
22693
+ max: -Infinity,
22694
+ hasVal: false,
22695
+ minDate: null,
22696
+ maxDate: null,
22697
+ totalRows: 0
22698
+ };
22699
+ }
22700
+ const acc = accs[key];
22701
+ acc.totalRows += 1;
22702
+ if (!valueField) {
22703
+ if (type === "count") acc.count += 1;
22704
+ else if (type === "percentage") acc.sum += 1;
22705
+ return;
22706
+ }
22707
+ updateAccumulator(acc, row, agg, false);
22708
+ });
22709
+ const sumOfDenom = Object.values(accs).reduce((t, a) => t + a.count, 0);
22710
+ Object.keys(accs).forEach((k) => {
22711
+ const acc = accs[k];
22712
+ seen[k][finalKey] = getFinalAggregationValue({
22713
+ type,
22714
+ valueFieldType,
22715
+ valueField,
22716
+ acc,
22717
+ distinctDenom,
22718
+ sumOfDenom,
22719
+ rowsLength: rows.length,
22720
+ totalRowsForCount: acc.totalRows
22721
+ });
22722
+ });
22723
+ });
22724
+ return seen;
22725
+ }
22726
+ function applyPivotInMemory(rows, pivot, filters) {
22727
+ if (!pivot) return rows;
22728
+ const multiAggPivot = pivot.aggregations ? pivot : singleAggToMultiAgg(pivot);
22729
+ if (multiAggPivot.rowField === void 0) {
22730
+ return aggregateToOneRow(rows, multiAggPivot.aggregations);
22731
+ }
22732
+ const { rowField, columnField, aggregations } = multiAggPivot;
22733
+ const dateBucket = inferDateBucketFromFilters(pivot, filters);
22734
+ const dateRange = dateBucket ? getDateRangeFromFilters(filters) : void 0;
22735
+ const getRowKey = dateBucket ? (row) => {
22736
+ const rawValue = row[rowField];
22737
+ const rawDateValue = rawValue !== null && typeof rawValue === "object" && rawValue.value ? rawValue.value : rawValue;
22738
+ return getDateKey(new Date(rawDateValue), dateBucket);
22739
+ } : (row) => row[rowField];
22740
+ const aggregated = columnField ? aggregateWithColumn(rows, columnField, aggregations, getRowKey) : aggregateWithoutColumn(rows, aggregations, getRowKey);
22741
+ const aggregatedRows = aggregated || {};
22742
+ if (rows.length === 0 && dateBucket && dateRange && !columnField) {
22743
+ const bucketKeys = generateBucketKeys(dateRange.start, dateRange.end, dateBucket);
22744
+ const emptyAgg = buildEmptyAggRow(aggregations);
22745
+ bucketKeys.forEach((k) => {
22746
+ aggregatedRows[k] = { ...emptyAgg };
22747
+ });
22748
+ }
22749
+ const finalRows = assembleFinalRows(
22750
+ aggregatedRows,
22751
+ rowField,
22752
+ dateBucket,
22753
+ rows.length === 0 ? dateRange : void 0
22754
+ );
22755
+ const sorted = sortRows(finalRows, pivot);
22756
+ if (pivot.rowLimit) {
22757
+ return sorted.slice(0, pivot.rowLimit);
22758
+ }
22759
+ return sorted;
22760
+ }
22761
+
22762
+ // src/utils/cacheCab.ts
22763
+ var import_idb = require("idb");
22764
+ var import_date_fns9 = require("date-fns");
22765
+ var import_date_fns_tz2 = require("date-fns-tz");
22766
+ var TZ = "America/Los_Angeles";
22767
+ var CacheCab = class {
22768
+ fetchedRange = {};
22769
+ cachedReportIds = [];
22770
+ uncacheableReportIDs = [];
22771
+ uncacheableInFlight = /* @__PURE__ */ new Map();
22772
+ storage;
22773
+ META_KEY = "cachecab:meta";
22774
+ DATA_PREFIX = "cachecab:data:";
22775
+ UNCACHEABLE_PREFIX = "cachecab:uncacheable:";
22776
+ constructor({
22777
+ storageType = "memory"
22778
+ } = {}) {
22779
+ this.storage = storageType !== "idb" ? new MemoryStorage() : new IdbStorage();
22780
+ void this.loadMetaFromStorage();
22781
+ }
22782
+ async get(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, pageSize, getToken, eventTracking, forceRefresh) {
22783
+ if (this.isCached(reportId, tenants) && !forceRefresh) {
22784
+ return this.getFromCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking);
22785
+ } else {
22786
+ return this.addToCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, true, forceRefresh);
22787
+ }
22788
+ }
22789
+ isCached(reportId, tenants) {
22790
+ return this.cachedReportIds.includes(this.getCacheKey(reportId, tenants));
22791
+ }
22792
+ isCacheable(reportId) {
22793
+ return !this.uncacheableReportIDs.includes(reportId);
22794
+ }
22795
+ async getUncacheableResult(reportId, client, tenants, flags, filters, additionalProcessing, pivot) {
22796
+ const key = this.getUncacheableRequestKey(
22797
+ reportId,
22798
+ client,
22799
+ tenants,
22800
+ flags,
22801
+ filters,
22802
+ additionalProcessing,
22803
+ pivot
22804
+ );
22805
+ try {
22806
+ const raw = await this.storage.getItem(key);
22807
+ return raw ? JSON.parse(raw) : null;
22808
+ } catch {
22809
+ return null;
22810
+ }
22811
+ }
22812
+ async setUncacheableResult(reportId, client, tenants, flags, filters, additionalProcessing, pivot, report) {
22813
+ const key = this.getUncacheableRequestKey(
22814
+ reportId,
22815
+ client,
22816
+ tenants,
22817
+ flags,
22818
+ filters,
22819
+ additionalProcessing,
22820
+ pivot
22821
+ );
22822
+ try {
22823
+ await this.storage.setItem(key, JSON.stringify(report));
22824
+ } catch {
22825
+ }
22826
+ }
22827
+ async getOrFetchUncacheableResult(reportId, client, tenants, flags, filters, additionalProcessing, pivot, fetcher, forceRefresh = false) {
22828
+ const key = this.getUncacheableRequestKey(
22829
+ reportId,
22830
+ client,
22831
+ tenants,
22832
+ flags,
22833
+ filters,
22834
+ additionalProcessing,
22835
+ pivot
22836
+ );
22837
+ if (!forceRefresh) {
22838
+ const raw = await this.storage.getItem(key);
22839
+ if (raw) {
22840
+ return { report: JSON.parse(raw), fromCache: true };
22841
+ }
22842
+ const inFlight = this.uncacheableInFlight.get(key);
22843
+ if (inFlight) {
22844
+ const report = await inFlight;
22845
+ return { report, fromCache: false };
22846
+ }
22847
+ }
22848
+ const requestPromise = (async () => {
22849
+ const report = await fetcher();
22850
+ try {
22851
+ await this.storage.setItem(key, JSON.stringify(report));
22852
+ } catch {
22853
+ }
22854
+ return report;
22855
+ })();
22856
+ this.uncacheableInFlight.set(key, requestPromise);
22857
+ try {
22858
+ const report = await requestPromise;
22859
+ return { report, fromCache: false };
22860
+ } finally {
22861
+ this.uncacheableInFlight.delete(key);
22862
+ }
22863
+ }
22864
+ async addToCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, firstTime = true, forceRefresh = false) {
22865
+ const tenantPart = tenants ? JSON.stringify(tenants) : "";
22866
+ const cacheKey = this.getCacheKey(reportId, tenants);
22867
+ if (firstTime) {
22868
+ const result = await this.fetchInitialReport({ reportId, client, tenants, flags, filters: dashboardFilters, getToken, eventTracking, forceRefresh });
22869
+ try {
22870
+ await this.storage.setItem(this.DATA_PREFIX + cacheKey, JSON.stringify(result));
22871
+ this.cachedReportIds.push(cacheKey);
22872
+ await this.persistMetaToStorage();
22873
+ } catch {
22874
+ console.warn(`Failed to cache report: ${reportId}. Cache full?`);
22875
+ }
22876
+ const newRows = await this.applyPivotsAndFilters(result, dashboardFilters, customFilters, pivot, tenantPart, false);
22877
+ if (pivot) {
22878
+ return { ...result, pivotRows: newRows, pivotRowCount: newRows.length };
22879
+ }
22880
+ return { ...result, rows: newRows, rowCount: newRows.length };
22881
+ } else {
22882
+ const dbDateFilter = dashboardFilters.find((x) => x.filterType === "date_range");
22883
+ const { start: requestedStart, end: requestedEnd } = normalizePSTRanges(
22884
+ dbDateFilter?.startDate ? new Date(dbDateFilter.startDate) : void 0,
22885
+ dbDateFilter?.endDate ? new Date(dbDateFilter.endDate) : void 0
22886
+ );
22887
+ if (!requestedStart || !requestedEnd) {
22888
+ return this.addToCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, true);
22889
+ }
22890
+ const currentRange = this.fetchedRange[cacheKey];
22891
+ const rangeStart = currentRange?.start ?? requestedStart;
22892
+ const rangeEnd = currentRange?.end ?? endOfDayPST(/* @__PURE__ */ new Date());
22893
+ const existingRaw = await this.storage.getItem(this.DATA_PREFIX + cacheKey);
22894
+ let existing;
22895
+ let fetchedRows = [];
22896
+ try {
22897
+ existing = JSON.parse(existingRaw);
22898
+ if (!existing.rows) {
22899
+ throw new Error("Invalid Cache!");
22900
+ }
22901
+ if (requestedStart < rangeStart) {
22902
+ const olderReport = await this.fetchReport({
22903
+ reportId,
22904
+ client,
22905
+ tenants,
22906
+ flags,
22907
+ filters: dashboardFilters,
22908
+ getToken,
22909
+ eventTracking,
22910
+ start: requestedStart,
22911
+ end: rangeStart
22912
+ });
22913
+ fetchedRows = olderReport.rows;
22914
+ }
22915
+ if (requestedEnd && requestedEnd > rangeEnd) {
22916
+ const newerReport = await this.fetchReport({
22917
+ reportId,
22918
+ client,
22919
+ tenants,
22920
+ flags,
22921
+ filters: dashboardFilters,
22922
+ getToken,
22923
+ eventTracking,
22924
+ start: rangeEnd,
22925
+ end: requestedEnd
22926
+ });
22927
+ fetchedRows = fetchedRows.concat(newerReport.rows);
22928
+ }
22929
+ } catch {
22930
+ existing = await this.fetchReport({
22931
+ reportId,
22932
+ client,
22933
+ tenants,
22934
+ flags,
22935
+ filters: dashboardFilters,
22936
+ getToken,
22937
+ eventTracking,
22938
+ start: requestedStart,
22939
+ end: requestedEnd
22940
+ });
22941
+ fetchedRows = existing.rows;
22942
+ }
22943
+ const dateKey = existing.dateField?.field ? removeQuotes(existing.dateField.field) : void 0;
22944
+ let mergedRows;
22945
+ if (dateKey) {
22946
+ const startMs = rangeStart.getTime();
22947
+ const endMs = rangeEnd.getTime();
22948
+ const boundaryRows = existing.rows.filter((row) => {
22949
+ const raw = row[dateKey];
22950
+ if (!raw) return false;
22951
+ const t = new Date(raw).getTime();
22952
+ return Math.abs(t - startMs) <= MS_IN_DAY || Math.abs(t - endMs) <= MS_IN_DAY;
22953
+ });
22954
+ const filteredNew = filterNewRows(boundaryRows, fetchedRows);
22955
+ mergedRows = filteredNew.concat(existing.rows);
22956
+ } else {
22957
+ mergedRows = filterNewRows(existing.rows, fetchedRows).concat(existing.rows);
22958
+ }
22959
+ const merged = { ...existing, rows: mergedRows };
22960
+ await this.storage.setItem(this.DATA_PREFIX + cacheKey, JSON.stringify(merged));
22961
+ await this.persistMetaToStorage();
22962
+ const newRows = await this.applyPivotsAndFilters(merged, dashboardFilters, customFilters, pivot, tenantPart, false);
22963
+ if (pivot) {
22964
+ return { ...merged, pivotRows: newRows, pivotRowCount: newRows.length };
22965
+ }
22966
+ return { ...merged, rows: newRows, rowCount: newRows.length };
22967
+ }
22968
+ }
22969
+ /**
22970
+ * Returns cache entry (or re-queries if stale)
22971
+ */
22972
+ async getFromCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking) {
22973
+ const dateRangeFilter = dashboardFilters.find((x) => x.filterType === "date_range");
22974
+ const cacheKey = this.getCacheKey(reportId, tenants);
22975
+ if (!dateRangeFilter || dateRangeFilter?.primaryRange.value === "ALL_TIME") {
22976
+ const fetchInfo = this.fetchedRange[cacheKey];
22977
+ if (!fetchInfo || fetchInfo?.allTimeDoneBefore === false || Date.now() - fetchInfo.fetchedAtUTCMS >= MS_IN_DAY) {
22978
+ return this.addToCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, true);
22979
+ }
22980
+ } else if (this.weShouldReQuery(cacheKey, dateRangeFilter)) {
22981
+ return this.addToCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, false);
22982
+ }
22983
+ try {
22984
+ const raw = await this.storage.getItem(this.DATA_PREFIX + cacheKey);
22985
+ if (!raw) {
22986
+ throw new Error("Invalid Cache!");
22987
+ }
22988
+ const parsed = JSON.parse(raw);
22989
+ const tenantPart = tenants ? JSON.stringify(tenants) : "";
22990
+ const newRows = await this.applyPivotsAndFilters(parsed, dashboardFilters, customFilters, pivot, tenantPart);
22991
+ if (pivot) {
22992
+ return { ...parsed, pivotRows: newRows, pivotRowCount: newRows.length };
22993
+ }
22994
+ return { ...parsed, rows: newRows, rowCount: newRows.length };
22995
+ } catch (err) {
22996
+ console.error(err);
22997
+ return this.addToCache(reportId, dashboardFilters, customFilters, pivot, client, tenants, flags, getToken, eventTracking, false);
22998
+ }
22999
+ }
23000
+ weShouldReQuery(cacheKey, dateRangeFilter) {
23001
+ const start2 = dateRangeFilter.startDate;
23002
+ const end = dateRangeFilter.endDate;
23003
+ const range = this.fetchedRange[cacheKey];
23004
+ const { start: s, end: e } = normalizePSTRanges(
23005
+ start2 ? new Date(start2) : void 0,
23006
+ end ? new Date(end) : void 0
23007
+ );
23008
+ return !range || !s || !e || range.start > s || range.end < e;
23009
+ }
23010
+ async fetchInitialReport({
23011
+ reportId,
23012
+ client,
23013
+ tenants,
23014
+ flags,
23015
+ filters = [],
23016
+ getToken,
23017
+ eventTracking,
23018
+ forceRefresh
23019
+ }) {
23020
+ let start2;
23021
+ let end;
23022
+ const dateRangeFilter = filters.find((x) => x.filterType === "date_range");
23023
+ const cacheRange = dateRangeFilter?.initialCacheDateRange;
23024
+ if (cacheRange && cacheRange.startDate) {
23025
+ const startDate = dateRangeFilter?.startDate;
23026
+ start2 = startDate ? (0, import_date_fns9.min)([new Date(cacheRange.startDate), new Date(startDate)]) : new Date(cacheRange.startDate);
23027
+ end = endOfDayPST(/* @__PURE__ */ new Date());
23028
+ } else {
23029
+ const endDate = dateRangeFilter?.endDate ? new Date(dateRangeFilter.endDate) : void 0;
23030
+ const currentDay = endOfDayPST(/* @__PURE__ */ new Date());
23031
+ end = endDate ? (0, import_date_fns9.max)([currentDay, endDate]) : currentDay;
23032
+ start2 = (0, import_date_fns9.subMonths)(end, 7);
23033
+ }
23034
+ const normalized = normalizePSTRanges(start2, end);
23035
+ return this.fetchReport({
23036
+ reportId,
23037
+ client,
23038
+ tenants,
23039
+ flags,
23040
+ filters,
23041
+ getToken,
23042
+ eventTracking,
23043
+ start: normalized.start,
23044
+ end: normalized.end,
23045
+ forceRefresh
23046
+ });
23047
+ }
23048
+ async fetchReport({
23049
+ reportId,
23050
+ client,
23051
+ tenants,
23052
+ flags,
23053
+ filters = [],
23054
+ getToken,
23055
+ eventTracking,
23056
+ start: start2,
23057
+ end,
23058
+ forceRefresh
23059
+ }) {
23060
+ let reportInfo = void 0;
23061
+ try {
23062
+ const { start: s, end: e } = normalizePSTRanges(start2, end);
23063
+ const adjusted = [...filters].map((x) => {
23064
+ return { ...x, options: void 0 };
23065
+ });
23066
+ const dateFilterIndex = adjusted.findIndex((x) => x.filterType === "date_range");
23067
+ const isAllTime = dateFilterIndex !== -1 && adjusted[dateFilterIndex].primaryRange?.value === "ALL_TIME";
23068
+ if (!isAllTime) {
23069
+ const dateFilter = adjusted[dateFilterIndex];
23070
+ if (dateFilter && dateFilter.startDate && dateFilter.endDate) {
23071
+ adjusted[dateFilterIndex] = { ...dateFilter, startDate: s, endDate: e };
23072
+ }
23073
+ }
23074
+ const fetchResp = await quillFetch({
23075
+ client,
23076
+ task: "report",
23077
+ metadata: {
23078
+ reportId,
23079
+ clientId: client.publicKey,
23080
+ databaseType: client.databaseType,
23081
+ filters: adjusted,
23082
+ additionalProcessing: { page: { rowsPerPage: 1e3, rowsPerRequest: 1e5 } },
23083
+ useNewNodeSql: true,
23084
+ tenants,
23085
+ flags,
23086
+ overwriteCache: forceRefresh ?? false
23087
+ },
23088
+ getToken
23089
+ });
23090
+ const resp = await parseFetchResponse(
23091
+ client,
23092
+ "report",
23093
+ fetchResp,
23094
+ getToken,
23095
+ true
23096
+ );
23097
+ reportInfo = await processReportResponse({
23098
+ resp,
23099
+ client,
23100
+ filters: adjusted,
23101
+ dateBucket: resp?.dateBucket,
23102
+ additionalProcessing: { page: { rowsPerPage: 1e3, rowsPerRequest: 1e5 } },
23103
+ getToken,
23104
+ eventTracking,
23105
+ tenants,
23106
+ // CacheCab fetches with task: 'report'; keep pivot processing local.
23107
+ skipPivotFetch: true,
23108
+ overwriteCache: forceRefresh ?? false
23109
+ });
23110
+ const dateField = reportInfo.dateField?.field;
23111
+ if (!isAllTime && dateField !== void 0 && reportInfo.rows.length > 0) {
23112
+ const cleanedDateField = removeQuotes(dateField);
23113
+ const missingDateFieldCount = reportInfo.rows.some((row) => row[cleanedDateField] === void 0);
23114
+ if (missingDateFieldCount) {
23115
+ this.uncacheableReportIDs.push(reportId);
23116
+ return EMPTY_INTERNAL_REPORT;
23117
+ }
23118
+ }
23119
+ const requiredFilterFields = adjusted.flatMap((x, idx) => {
23120
+ if (idx === dateFilterIndex || !x.values && !x.selectedValue) return [];
23121
+ return removeQuotes(x.field);
23122
+ });
23123
+ const missingFields = [...new Set(requiredFilterFields.filter(
23124
+ (field) => reportInfo?.rows.some((row) => row[field] === void 0)
23125
+ ))];
23126
+ if (missingFields.length > 0) {
23127
+ this.uncacheableReportIDs.push(reportId);
23128
+ return EMPTY_INTERNAL_REPORT;
23129
+ }
23130
+ const cacheKey = this.getCacheKey(reportId, tenants);
23131
+ if (isAllTime) {
23132
+ this.fetchedRange[cacheKey] = { start: /* @__PURE__ */ new Date(0), end: /* @__PURE__ */ new Date(), fetchedAtUTCMS: Date.now(), allTimeDoneBefore: true };
23133
+ } else {
23134
+ const existing = this.fetchedRange[cacheKey];
23135
+ if (existing && !forceRefresh) {
23136
+ const oldStart = existing.start;
23137
+ const oldEnd = existing.end;
23138
+ this.fetchedRange[cacheKey] = { start: getMinDate(oldStart, s), end: getMaxDate(oldEnd, e), fetchedAtUTCMS: Date.now(), allTimeDoneBefore: false };
23139
+ } else {
23140
+ this.fetchedRange[cacheKey] = { start: s, end: e, fetchedAtUTCMS: Date.now(), allTimeDoneBefore: false };
23141
+ }
23142
+ }
23143
+ } catch (error) {
23144
+ console.warn(error);
23145
+ if (error instanceof Error && error.name === "AbortError") {
23146
+ throw error;
23147
+ }
23148
+ }
23149
+ return reportInfo || EMPTY_INTERNAL_REPORT;
23150
+ }
23151
+ async applyPivotsAndFilters(report, dashboardFilters, customFilters, pivot, tenantPart, useCache = true) {
23152
+ const datasetVersion = this.fetchedRange[report.id + tenantPart]?.fetchedAtUTCMS ?? 0;
23153
+ const keyParts = [
23154
+ report.queryString,
23155
+ tenantPart,
23156
+ datasetVersion,
23157
+ // prevents fetching stale filters on hard refresh
23158
+ hashString(stableStringify(dashboardFilters)),
23159
+ hashString(stableStringify(customFilters))
23160
+ ];
23161
+ const queryKey = this.DATA_PREFIX + keyParts.join("|");
23162
+ let filtersApplied;
23163
+ if (useCache) {
23164
+ try {
23165
+ const cache = await this.storage.getItem(queryKey);
23166
+ if (cache) {
23167
+ filtersApplied = JSON.parse(cache);
23168
+ }
23169
+ } catch {
23170
+ }
23171
+ }
23172
+ if (!filtersApplied) {
23173
+ const dateIndex = dashboardFilters.findIndex((x) => x.filterType === "date_range");
23174
+ const requiredFilterFields = dashboardFilters.flatMap((x, idx) => {
23175
+ if (idx === dateIndex || !x.values?.length && !x.selectedValue) return [];
23176
+ return removeQuotes(x.field);
23177
+ });
23178
+ const missingFields = [...new Set(requiredFilterFields.filter(
23179
+ (field) => report.rows.some((row) => row[field] === void 0)
23180
+ ))];
23181
+ if (missingFields.length > 0) {
23182
+ this.uncacheableReportIDs.push(report.id);
23183
+ return [];
23184
+ }
23185
+ const dbDateFilter = dashboardFilters.find((x) => x.filterType === "date_range");
23186
+ if (report.dateField && dbDateFilter?.startDate) {
23187
+ const { start: startDate, end: endDate } = normalizePSTRanges(
23188
+ new Date(dbDateFilter.startDate),
23189
+ dbDateFilter.endDate ? new Date(dbDateFilter.endDate) : void 0
23190
+ );
23191
+ const fieldToUse = report.rows[0] && report.rows[0]["__quillRawDate"] ? "__quillRawDate" : removeQuotes(report.dateField.field);
23192
+ const dateFilteredRows = report.rows.filter((x) => {
23193
+ const rowDate = new Date(x[fieldToUse]);
23194
+ return startDate <= rowDate && (endDate ? rowDate <= endDate : true);
23195
+ });
23196
+ filtersApplied = applyFiltersInMemory(dateFilteredRows, [], { dashboardFilters, customFilters });
23197
+ } else {
23198
+ filtersApplied = applyFiltersInMemory(report.rows, [], { dashboardFilters, customFilters });
23199
+ }
23200
+ }
23201
+ try {
23202
+ await this.storage.setItem(queryKey, JSON.stringify(filtersApplied));
23203
+ } catch {
23204
+ }
23205
+ const withPivot = applyPivotInMemory(filtersApplied, pivot, dashboardFilters.concat(customFilters));
23206
+ return withPivot;
23207
+ }
23208
+ getCacheKey(reportId, tenants) {
23209
+ const tenantPart = tenants ? JSON.stringify(tenants) : "";
23210
+ return reportId + tenantPart;
23211
+ }
23212
+ getUncacheableRequestKey(reportId, client, tenants, flags, filters, additionalProcessing, pivot) {
23213
+ const canonicalFilters = filters.map(
23214
+ (f) => canonicalizeFilterForUncacheableKey(f)
23215
+ );
23216
+ const keyParts = [
23217
+ reportId,
23218
+ client.publicKey,
23219
+ client.databaseType,
23220
+ hashString(stableStringify(canonicalizeForKey(tenants ?? null))),
23221
+ hashString(stableStringify(canonicalizeForKey(flags ?? null))),
23222
+ hashString(stableStringify(canonicalFilters)),
23223
+ hashString(stableStringify(canonicalizeForKey(additionalProcessing ?? null))),
23224
+ hashString(stableStringify(canonicalizeForKey(pivot ?? null)))
23225
+ ];
23226
+ return this.UNCACHEABLE_PREFIX + keyParts.join("|");
23227
+ }
23228
+ async loadMetaFromStorage() {
23229
+ const meta = await this.storage.getItem(this.META_KEY);
23230
+ if (!meta) return;
23231
+ try {
23232
+ const parsed = JSON.parse(meta);
23233
+ this.cachedReportIds = parsed.cached || [];
23234
+ this.uncacheableReportIDs = parsed.cannotBeCached;
23235
+ this.fetchedRange = Object.fromEntries(
23236
+ Object.entries(parsed.fetchedRange || {}).map(([id2, range]) => [
23237
+ id2,
23238
+ { ...range, start: new Date(range.start), end: new Date(range.end) }
23239
+ ])
23240
+ );
23241
+ } catch (err) {
23242
+ console.warn("CacheCab: could not parse meta from storage", err);
23243
+ }
23244
+ }
23245
+ async persistMetaToStorage() {
23246
+ const serializableRange = Object.fromEntries(
23247
+ Object.entries(this.fetchedRange).map(([id2, range]) => [
23248
+ id2,
23249
+ { ...range }
23250
+ ])
23251
+ );
23252
+ await this.storage.setItem(
23253
+ this.META_KEY,
23254
+ JSON.stringify({
23255
+ fetchedRange: serializableRange,
23256
+ cached: this.cachedReportIds,
23257
+ cannotBeCached: this.uncacheableReportIDs
23258
+ })
23259
+ );
23260
+ }
23261
+ };
23262
+ var MemoryStorage = class {
23263
+ store = /* @__PURE__ */ new Map();
23264
+ async getItem(key) {
23265
+ return this.store.get(key) ?? null;
23266
+ }
23267
+ async setItem(key, value) {
23268
+ this.store.set(key, value);
23269
+ }
23270
+ };
23271
+ var DB_NAME = "quill.cachecab";
23272
+ var STORE_NAME = "kv";
23273
+ var IdbStorage = class {
23274
+ dbPromise;
23275
+ constructor() {
23276
+ this.dbPromise = (0, import_idb.openDB)(DB_NAME, 1, {
23277
+ upgrade(db) {
23278
+ if (!db.objectStoreNames.contains(STORE_NAME)) {
23279
+ db.createObjectStore(STORE_NAME);
23280
+ }
23281
+ }
23282
+ });
23283
+ }
23284
+ async getItem(key) {
23285
+ const db = await this.dbPromise;
23286
+ return await db.get(STORE_NAME, key) ?? null;
23287
+ }
23288
+ async setItem(key, value) {
23289
+ const db = await this.dbPromise;
23290
+ await db.put(STORE_NAME, value, key);
23291
+ }
23292
+ };
23293
+ function removeQuotes(str) {
23294
+ return str.replace(/^['"]|['"]$/g, "");
23295
+ }
23296
+ function getMaxDate(d1, d2) {
23297
+ return d1 > d2 ? d1 : d2;
23298
+ }
23299
+ function getMinDate(d1, d2) {
23300
+ return d2 > d1 ? d1 : d2;
23301
+ }
23302
+ function hashString(str) {
23303
+ let h1 = 3735928559 ^ 0, h2 = 1103547991 ^ 0;
23304
+ for (let i = 0, ch; i < str.length; i++) {
23305
+ ch = str.charCodeAt(i);
23306
+ h1 = Math.imul(h1 ^ ch, 2654435761);
23307
+ h2 = Math.imul(h2 ^ ch, 1597334677);
23308
+ }
23309
+ h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909);
23310
+ h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909);
23311
+ return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(36);
23312
+ }
23313
+ function filterNewRows(existingRows, newRows) {
23314
+ const seen = /* @__PURE__ */ new Set();
23315
+ const getKey = (row) => stableStringify(row);
23316
+ existingRows.forEach((row) => seen.add(getKey(row)));
23317
+ return newRows.filter((row) => {
23318
+ const k = getKey(row);
23319
+ if (seen.has(k)) return false;
23320
+ seen.add(k);
23321
+ return true;
23322
+ });
23323
+ }
23324
+ function stableStringify(obj) {
23325
+ if (obj === null || typeof obj !== "object") return JSON.stringify(obj);
23326
+ if (Array.isArray(obj)) {
23327
+ return `[${obj.map(stableStringify).join(",")}]`;
23328
+ }
23329
+ const keys = Object.keys(obj).sort();
23330
+ return `{${keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",")}}`;
23331
+ }
23332
+ function canonicalizeForKey(value) {
23333
+ if (value instanceof Date) {
23334
+ return value.toISOString();
23335
+ }
23336
+ if (Array.isArray(value)) {
23337
+ return value.map(canonicalizeForKey);
23338
+ }
23339
+ if (value && typeof value === "object") {
23340
+ const out = {};
23341
+ Object.keys(value).sort().forEach((key) => {
23342
+ if (value[key] !== void 0) {
23343
+ out[key] = canonicalizeForKey(value[key]);
23344
+ }
23345
+ });
23346
+ return out;
23347
+ }
23348
+ return value;
23349
+ }
23350
+ function canonicalizeFilterForUncacheableKey(filter) {
23351
+ const raw = canonicalizeForKey(filter) ?? {};
23352
+ const base = {
23353
+ filterType: raw.filterType,
23354
+ field: raw.field,
23355
+ table: raw.table,
23356
+ label: raw.label,
23357
+ operator: raw.operator
23358
+ };
23359
+ if (raw.selectedValue !== void 0) {
23360
+ base.selectedValue = raw.selectedValue;
23361
+ }
23362
+ if (Array.isArray(raw.values)) {
23363
+ base.values = [...raw.values].map(canonicalizeForKey).sort();
23364
+ }
23365
+ if (raw.value !== void 0) {
23366
+ base.value = canonicalizeForKey(raw.value);
23367
+ }
23368
+ if (raw.filterType === "date_range") {
23369
+ const { start: start2, end } = normalizePSTRanges(
23370
+ raw.startDate ? new Date(raw.startDate) : void 0,
23371
+ raw.endDate ? new Date(raw.endDate) : void 0
23372
+ );
23373
+ base.startDate = start2 ? start2.toISOString() : void 0;
23374
+ base.endDate = end ? end.toISOString() : void 0;
23375
+ base.primaryRange = raw.primaryRange?.value;
23376
+ base.comparisonRange = raw.comparisonRange?.value;
23377
+ }
23378
+ return canonicalizeForKey(base);
23379
+ }
23380
+ function startOfDayPST(date) {
23381
+ const pstDate = (0, import_date_fns_tz2.utcToZonedTime)(date, TZ);
23382
+ const startPst = (0, import_date_fns9.startOfDay)(pstDate);
23383
+ return (0, import_date_fns_tz2.zonedTimeToUtc)(startPst, TZ);
23384
+ }
23385
+ function endOfDayPST(date) {
23386
+ const pstDate = (0, import_date_fns_tz2.utcToZonedTime)(date, TZ);
23387
+ const endPst = (0, import_date_fns9.endOfDay)(pstDate);
23388
+ return (0, import_date_fns_tz2.zonedTimeToUtc)(endPst, TZ);
23389
+ }
23390
+ function normalizePSTRanges(start2, end) {
23391
+ return {
23392
+ start: start2 ? startOfDayPST(start2) : void 0,
23393
+ end: end ? endOfDayPST(end) : void 0
23394
+ };
23395
+ }
23396
+
23397
+ // src/Context.tsx
21589
23398
  var import_jsx_runtime = require("react/jsx-runtime");
21590
23399
  var dummySetter = () => {
21591
23400
  };
@@ -21917,7 +23726,9 @@ var ReportFiltersContext = (0, import_react.createContext)({
21917
23726
  loadFiltersForReport: async () => {
21918
23727
  },
21919
23728
  abortLoadingFilters: () => {
21920
- }
23729
+ },
23730
+ customFiltersLoaded: false,
23731
+ setCustomFiltersLoaded: dummySetter
21921
23732
  });
21922
23733
  var customDashboardFiltersReducer = (state, action) => {
21923
23734
  switch (action.type) {
@@ -22007,6 +23818,9 @@ var FetchContext = (0, import_react.createContext)({
22007
23818
  var EventTrackingContext = (0, import_react.createContext)({
22008
23819
  eventTracking: null
22009
23820
  });
23821
+ var CacheCabContext = (0, import_react.createContext)({
23822
+ getCacheCab: (storageType) => new CacheCab({ storageType })
23823
+ });
22010
23824
  var ContextProvider = ({
22011
23825
  children,
22012
23826
  initialTheme,
@@ -22020,6 +23834,14 @@ var ContextProvider = ({
22020
23834
  getAuthorizationToken = async () => "",
22021
23835
  eventTracking = null
22022
23836
  }) => {
23837
+ const cacheCabByTypeRef = (0, import_react.useRef)({});
23838
+ const getCacheCab = (0, import_react.useCallback)((storageType) => {
23839
+ const key = storageType === "idb" ? "idb" : "memory";
23840
+ if (!cacheCabByTypeRef.current[key]) {
23841
+ cacheCabByTypeRef.current[key] = new CacheCab({ storageType: key });
23842
+ }
23843
+ return cacheCabByTypeRef.current[key];
23844
+ }, []);
22023
23845
  const [client, setClient] = (0, import_react.useState)(
22024
23846
  typeof window !== "undefined" && sessionStorage ? JSON.parse(sessionStorage.getItem("quill-client") ?? "null") : null
22025
23847
  );
@@ -22082,6 +23904,7 @@ var ContextProvider = ({
22082
23904
  reportFiltersReducer,
22083
23905
  {}
22084
23906
  );
23907
+ const [customFiltersLoaded, setCustomFiltersLoaded] = (0, import_react.useState)(false);
22085
23908
  const reportFilterOptionsAbortControllers = (0, import_react.useRef)({});
22086
23909
  const [reports, reportsDispatch] = (0, import_react.useReducer)(reportsReducer, {});
22087
23910
  const [reportsLoadingState, reportsLoadingStateDispatch] = (0, import_react.useReducer)(
@@ -22105,6 +23928,11 @@ var ContextProvider = ({
22105
23928
  const viewerTenantsByOwnerRequests = (0, import_react.useRef)(/* @__PURE__ */ new Set());
22106
23929
  const mappedTenantsRequests = (0, import_react.useRef)(/* @__PURE__ */ new Set());
22107
23930
  const loadDashboardProcessId = (0, import_react.useRef)({});
23931
+ (0, import_react.useEffect)(() => {
23932
+ if (Object.keys(customReportFilters).length) {
23933
+ setCustomFiltersLoaded(true);
23934
+ }
23935
+ }, [customReportFilters]);
22108
23936
  (0, import_react.useEffect)(() => {
22109
23937
  if (!theme) {
22110
23938
  const populatedTheme = {
@@ -22873,6 +24701,7 @@ var ContextProvider = ({
22873
24701
  ...dashboard2,
22874
24702
  dateFilter: dashboard2.dateFilter ? {
22875
24703
  ...dashboard2.dateFilter,
24704
+ initialCacheDateRange: dashboard2.initialCacheDateRange ? { ...dashboard2.initialCacheDateRange } : void 0,
22876
24705
  presetOptions: dashboard2.dateFilter.presetOptions?.map(
22877
24706
  (preset) => ({
22878
24707
  ...preset,
@@ -23215,6 +25044,7 @@ var ContextProvider = ({
23215
25044
  ...dashboard2,
23216
25045
  dateFilter: dashboard2.dateFilter ? {
23217
25046
  ...dashboard2.dateFilter,
25047
+ initialCacheDateRange: dashboard2.initialCacheDateRange ? { ...dashboard2.initialCacheDateRange } : void 0,
23218
25048
  presetOptions: dashboard2.dateFilter.presetOptions?.map(
23219
25049
  (preset) => ({
23220
25050
  ...preset,
@@ -23259,6 +25089,7 @@ var ContextProvider = ({
23259
25089
  if (dashboard2.dateFilter) {
23260
25090
  dashboard2.dateFilter = {
23261
25091
  ...dashboard2.dateFilter,
25092
+ initialCacheDateRange: dashboard2.initialCacheDateRange ? { ...dashboard2.initialCacheDateRange } : void 0,
23262
25093
  startDate: presetOptions.find(
23263
25094
  (elem) => elem.value === dashboard2.dateFilter.primaryRange?.value
23264
25095
  )?.startDate,
@@ -23527,7 +25358,7 @@ var ContextProvider = ({
23527
25358
  if (!theme) {
23528
25359
  return null;
23529
25360
  }
23530
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
25361
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CacheCabContext.Provider, { value: { getCacheCab }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
23531
25362
  ClientContext.Provider,
23532
25363
  {
23533
25364
  value: [
@@ -23568,7 +25399,9 @@ var ContextProvider = ({
23568
25399
  reportFiltersDispatch,
23569
25400
  customReportFiltersDispatch,
23570
25401
  loadFiltersForReport,
23571
- abortLoadingFilters
25402
+ abortLoadingFilters,
25403
+ customFiltersLoaded,
25404
+ setCustomFiltersLoaded
23572
25405
  },
23573
25406
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
23574
25407
  ReportsContext.Provider,
@@ -23611,7 +25444,7 @@ var ContextProvider = ({
23611
25444
  }
23612
25445
  ) })
23613
25446
  }
23614
- );
25447
+ ) });
23615
25448
  };
23616
25449
 
23617
25450
  // src/hooks/useExport.tsx
@@ -23627,9 +25460,9 @@ init_Filter();
23627
25460
  init_filterProcessing();
23628
25461
 
23629
25462
  // src/utils/merge.ts
23630
- var import_date_fns8 = require("date-fns");
25463
+ var import_date_fns10 = require("date-fns");
23631
25464
  init_columnType();
23632
- var import_date_fns_tz2 = require("date-fns-tz");
25465
+ var import_date_fns_tz3 = require("date-fns-tz");
23633
25466
  function mergeComparisonRange(resp) {
23634
25467
  if (resp.chartType === "table") return resp;
23635
25468
  const compRows = resp.compareRows;
@@ -23672,6 +25505,18 @@ var useDashboardInternal = (dashboardName, customFilters) => {
23672
25505
  (f) => f.filter
23673
25506
  ) : null;
23674
25507
  }, [dashboardFilters, dashboardName]);
25508
+ const getExistingDateFilter = (0, import_react2.useMemo)(
25509
+ () => (name2) => {
25510
+ if (!name2) return void 0;
25511
+ const filtersForDashboard = dashboardFilters[name2];
25512
+ if (!filtersForDashboard) return void 0;
25513
+ const entry = Object.values(filtersForDashboard).find(
25514
+ (f) => f?.filter?.filterType === "date_range" /* Date */
25515
+ );
25516
+ return entry?.filter;
25517
+ },
25518
+ [dashboardFilters]
25519
+ );
23675
25520
  (0, import_react2.useEffect)(() => {
23676
25521
  if (!dashboardName) return;
23677
25522
  if (backfilledDashboards.current.has(dashboardName)) return;
@@ -23709,7 +25554,7 @@ var useDashboardInternal = (dashboardName, customFilters) => {
23709
25554
  customFilters
23710
25555
  );
23711
25556
  }, [dashboardName, loading, dashboardConfig, dashboardFilters]);
23712
- const handleReload = async (overrideDashboardName, fetchFromServer = false, reportAction, overrideFilters) => {
25557
+ const handleReload = async (overrideDashboardName, fetchFromServer = false, reportAction, overrideFilters, options) => {
23713
25558
  if (!dashboardName) return;
23714
25559
  if (overrideFilters) {
23715
25560
  const dateFilter2 = overrideFilters.filters.find(
@@ -23762,10 +25607,19 @@ var useDashboardInternal = (dashboardName, customFilters) => {
23762
25607
  Object.values(dashboard?.sections ?? {}).flat(),
23763
25608
  dashboardName
23764
25609
  ) : void 0;
25610
+ const existingDateFilter = options?.preserveExistingDateFilter ? getExistingDateFilter(dashboardName) : void 0;
25611
+ const mergedDateFilter = dateFilter && existingDateFilter ? {
25612
+ ...dateFilter,
25613
+ startDate: existingDateFilter.startDate ?? dateFilter.startDate,
25614
+ endDate: existingDateFilter.endDate ?? dateFilter.endDate,
25615
+ preset: existingDateFilter.preset ?? dateFilter.preset,
25616
+ primaryRange: existingDateFilter.primaryRange ?? dateFilter.primaryRange,
25617
+ comparisonRange: existingDateFilter.comparisonRange ?? dateFilter.comparisonRange
25618
+ } : dateFilter ?? existingDateFilter;
23765
25619
  loadFiltersForDashboard(
23766
25620
  dashboardName,
23767
25621
  [
23768
- ...dateFilter ? [dateFilter] : [],
25622
+ ...mergedDateFilter ? [mergedDateFilter] : [],
23769
25623
  ...updatedDashboard?.filters?.map((filter) => ({
23770
25624
  ...filter,
23771
25625
  query: void 0
@@ -24050,7 +25904,8 @@ var useDashboards = () => {
24050
25904
  tenantFilters,
24051
25905
  dateFilter,
24052
25906
  customFilters,
24053
- tenantKeys
25907
+ tenantKeys,
25908
+ initialCacheDateRange
24054
25909
  }) => {
24055
25910
  if (!client) return;
24056
25911
  if (tenantKeys?.some((key) => !key)) {
@@ -24071,6 +25926,7 @@ var useDashboards = () => {
24071
25926
  filters,
24072
25927
  tenantFilters,
24073
25928
  dateFilter: dateFilter ?? null,
25929
+ initialCacheDateRange,
24074
25930
  name: name2.trim(),
24075
25931
  task: "edit-dashboard",
24076
25932
  clientId: client.clientId,
@@ -24282,7 +26138,9 @@ var useDashboards = () => {
24282
26138
  };
24283
26139
  };
24284
26140
  var useDashboard = (dashboardName, config) => {
26141
+ const logCacheStatistics = config?.showCacheLogs || false;
24285
26142
  const { data, dashboardFilters, reload, isLoading } = useDashboardInternal(dashboardName);
26143
+ const [lastUpdated, setLastUpdated] = (0, import_react2.useState)(0);
24286
26144
  const { customFilterDispatch } = (0, import_react2.useContext)(DashboardFiltersContext);
24287
26145
  const { reportsDispatch, reportsLoadingStateDispatch } = (0, import_react2.useContext)(ReportsContext);
24288
26146
  const initialLoad = (0, import_react2.useRef)(true);
@@ -24291,15 +26149,19 @@ var useDashboard = (dashboardName, config) => {
24291
26149
  const [client] = (0, import_react2.useContext)(ClientContext);
24292
26150
  const { tenants, flags } = (0, import_react2.useContext)(TenantContext);
24293
26151
  const { getToken } = (0, import_react2.useContext)(FetchContext);
24294
- const { customReportFilters } = (0, import_react2.useContext)(ReportFiltersContext);
26152
+ const { customReportFilters, customFiltersLoaded, setCustomFiltersLoaded } = (0, import_react2.useContext)(ReportFiltersContext);
24295
26153
  const { eventTracking } = (0, import_react2.useContext)(EventTrackingContext);
24296
- const customFiltersRef = (0, import_react2.useRef)(customReportFilters);
26154
+ const { getCacheCab } = (0, import_react2.useContext)(CacheCabContext);
24297
26155
  const reportRequestIds = (0, import_react2.useRef)({});
24298
26156
  const lastDashboardName = (0, import_react2.useRef)(null);
24299
26157
  const pendingNameChangeReload = (0, import_react2.useRef)(false);
24300
- (0, import_react2.useEffect)(() => {
24301
- customFiltersRef.current = customReportFilters;
24302
- }, [customReportFilters]);
26158
+ const [loadedDashes, setLoadedDashes] = (0, import_react2.useState)([]);
26159
+ const [lastUpdatedDict, setLastUpdatedDict] = (0, import_react2.useState)({});
26160
+ const cacheEnabled = config?.cacheEnabled ?? true;
26161
+ const cacheCab = (0, import_react2.useMemo)(
26162
+ () => getCacheCab(config?.cacheType),
26163
+ [getCacheCab, config?.cacheType]
26164
+ );
24303
26165
  (0, import_react2.useEffect)(() => {
24304
26166
  const nameChanged = dashboardName !== lastDashboardName.current;
24305
26167
  if (nameChanged) {
@@ -24309,19 +26171,29 @@ var useDashboard = (dashboardName, config) => {
24309
26171
  backfilledDashboards.current = false;
24310
26172
  reportRequestIds.current = {};
24311
26173
  pendingNameChangeReload.current = true;
26174
+ if (customFiltersLoaded && !loadedDashes.includes(dashboardName)) {
26175
+ setCustomFiltersLoaded(false);
26176
+ }
26177
+ setLastUpdated(lastUpdatedDict[dashboardName] || 0);
24312
26178
  }
24313
26179
  if (!dashboardName) return;
24314
26180
  if (pendingNameChangeReload.current && data) {
24315
26181
  pendingNameChangeReload.current = false;
24316
26182
  initialLoad.current = false;
26183
+ fetchedInitialReports.current = false;
24317
26184
  return;
24318
26185
  }
24319
26186
  if (pendingNameChangeReload.current && !isLoading && !data && initialLoad.current) {
24320
26187
  initialLoad.current = false;
24321
26188
  pendingNameChangeReload.current = false;
24322
- reload();
26189
+ reload(dashboardName, false, void 0, void 0, {
26190
+ preserveExistingDateFilter: true
26191
+ });
24323
26192
  }
24324
26193
  }, [isLoading, data, dashboardName]);
26194
+ (0, import_react2.useEffect)(() => {
26195
+ setLastUpdated(lastUpdatedDict[dashboardName] || 0);
26196
+ }, [lastUpdatedDict, dashboardName]);
24325
26197
  (0, import_react2.useEffect)(() => {
24326
26198
  if (backfilledDashboards.current) return;
24327
26199
  if (isLoading || !data) return;
@@ -24330,7 +26202,9 @@ var useDashboard = (dashboardName, config) => {
24330
26202
  );
24331
26203
  if (!needsBackfill) return;
24332
26204
  backfilledDashboards.current = true;
24333
- reload(dashboardName, false);
26205
+ reload(dashboardName, false, void 0, void 0, {
26206
+ preserveExistingDateFilter: true
26207
+ });
24334
26208
  }, [isLoading, data, dashboardFilters, dashboardName]);
24335
26209
  const { allReportsById } = useAllReports();
24336
26210
  const sections = (0, import_react2.useMemo)(() => {
@@ -24354,7 +26228,13 @@ var useDashboard = (dashboardName, config) => {
24354
26228
  fetchedInitialReports.current = true;
24355
26229
  fetchReports([], dashboardFilters ?? [], config?.pageSize);
24356
26230
  }
24357
- }, [fetchedInitialReports, data, dashboardFilters]);
26231
+ }, [fetchedInitialReports, data, dashboardFilters, customFiltersLoaded]);
26232
+ (0, import_react2.useEffect)(() => {
26233
+ if (customFiltersLoaded && data && dashboardFilters !== null) {
26234
+ fetchedInitialReports.current = true;
26235
+ fetchReports([], dashboardFilters ?? [], config?.pageSize);
26236
+ }
26237
+ }, [customFiltersLoaded]);
24358
26238
  const applyDashboardFilters = (filtersToUpdate) => {
24359
26239
  const newFilters = (dashboardFilters ?? []).map((f) => {
24360
26240
  const update = filtersToUpdate.find((u) => u.label === f.label);
@@ -24433,7 +26313,7 @@ var useDashboard = (dashboardName, config) => {
24433
26313
  });
24434
26314
  return internalFilters;
24435
26315
  };
24436
- const isFilter = (f) => {
26316
+ const isFilter2 = (f) => {
24437
26317
  return f && typeof f === "object" && "filterType" in f && !("id" in f);
24438
26318
  };
24439
26319
  const isDashboardFilter = (f) => {
@@ -24441,29 +26321,22 @@ var useDashboard = (dashboardName, config) => {
24441
26321
  };
24442
26322
  const applyFilters = (filters2) => {
24443
26323
  const dashboardFilters2 = filters2.filter(isDashboardFilter);
24444
- const customFilters = filters2.filter(isFilter);
26324
+ const customFilters = filters2.filter(isFilter2);
24445
26325
  const newCustomFilters = applyCustomFilters(customFilters);
24446
26326
  const newDashboardFilters = applyDashboardFilters(dashboardFilters2);
24447
26327
  fetchReports(newCustomFilters, newDashboardFilters);
24448
26328
  };
24449
- const waitForCustomFilters = async (reportId) => {
24450
- let attempts = 0;
24451
- const maxAttempts = 10;
24452
- while (attempts < maxAttempts) {
24453
- const filters2 = customFiltersRef.current[reportId];
24454
- if (filters2 && filters2.length > 0) {
24455
- return filters2;
24456
- }
24457
- await new Promise((resolve) => setTimeout(resolve, 100));
24458
- attempts++;
24459
- }
24460
- return [];
26329
+ const forceCacheRefresh = () => {
26330
+ if (!cacheEnabled) return;
26331
+ fetchReports([], dashboardFilters ?? [], config?.pageSize, true);
24461
26332
  };
24462
- const fetchReports = async (customFilters, dashboardFilters2, pageSize) => {
26333
+ const fetchReports = async (customFilters, dashboardFilters2, pageSize, forceCacheToRefresh = false) => {
24463
26334
  if (!client || !sections) return;
24464
26335
  const allReports = Object.values(sections).flat();
26336
+ const fetchStartTime = Date.now();
26337
+ let totalCached = 0;
24465
26338
  await Promise.all(
24466
- allReports.map(async (reportInfo) => {
26339
+ allReports.map(async (reportInfo, idx) => {
24467
26340
  const reportId = reportInfo.id;
24468
26341
  const requestId = (reportRequestIds.current[reportId] ?? 0) + 1;
24469
26342
  reportRequestIds.current[reportId] = requestId;
@@ -24472,7 +26345,7 @@ var useDashboard = (dashboardName, config) => {
24472
26345
  id: reportId,
24473
26346
  data: true
24474
26347
  });
24475
- const customReportFiltersArray = await waitForCustomFilters(reportId);
26348
+ const customReportFiltersArray = customReportFilters[reportId] ?? [];
24476
26349
  let rowsPerRequest = pageSize || 600;
24477
26350
  if (!pageSize && (reportInfo.chartType === "table" || reportInfo.chartType === "metric")) {
24478
26351
  rowsPerRequest = 10;
@@ -24484,17 +26357,138 @@ var useDashboard = (dashboardName, config) => {
24484
26357
  const additionalProcessing = {
24485
26358
  page: pagination
24486
26359
  };
24487
- const usePivotTask = !!reportInfo.pivot;
26360
+ const usePivotTask = !cacheEnabled && !!reportInfo.pivot;
26361
+ const allFilters = dashboardFilters2.concat(customFilters).concat(customReportFiltersArray);
26362
+ if (cacheEnabled && cacheCab.isCacheable(reportId)) {
26363
+ const report2 = await cacheCab.get(reportId, dashboardFilters2, customFilters.concat(customReportFiltersArray), reportInfo.pivot, client, tenants, flags, pageSize, getToken, eventTracking, forceCacheToRefresh);
26364
+ if (reportRequestIds.current[reportId] !== requestId) {
26365
+ return null;
26366
+ }
26367
+ if (cacheCab.isCacheable(reportId)) {
26368
+ reportsDispatch({
26369
+ type: "UPDATE_REPORT",
26370
+ id: reportId,
26371
+ data: {
26372
+ ...report2,
26373
+ pagination,
26374
+ triggerReload: false
26375
+ }
26376
+ });
26377
+ reportsLoadingStateDispatch({
26378
+ type: "SET_REPORT_LOADING",
26379
+ id: reportId,
26380
+ data: false
26381
+ });
26382
+ totalCached += 1;
26383
+ return report2;
26384
+ }
26385
+ }
26386
+ if (cacheEnabled && !cacheCab.isCacheable(reportId)) {
26387
+ try {
26388
+ const { report: uncacheableReport, fromCache } = await cacheCab.getOrFetchUncacheableResult(
26389
+ reportId,
26390
+ client,
26391
+ tenants,
26392
+ flags,
26393
+ allFilters,
26394
+ additionalProcessing,
26395
+ reportInfo.pivot,
26396
+ async () => {
26397
+ const { report: report2, error: error2 } = await fetchReport({
26398
+ reportId,
26399
+ client,
26400
+ tenants,
26401
+ flags,
26402
+ additionalProcessing,
26403
+ filters: allFilters,
26404
+ getToken,
26405
+ eventTracking,
26406
+ usePivotTask,
26407
+ overwriteCache: forceCacheToRefresh
26408
+ });
26409
+ if (error2 || !report2) {
26410
+ throw error2 ?? new Error("Failed to fetch uncacheable report");
26411
+ }
26412
+ return report2;
26413
+ },
26414
+ forceCacheToRefresh
26415
+ );
26416
+ if (reportRequestIds.current[reportId] !== requestId) {
26417
+ return null;
26418
+ }
26419
+ reportsDispatch({
26420
+ type: "UPDATE_REPORT",
26421
+ id: reportId,
26422
+ data: {
26423
+ ...uncacheableReport,
26424
+ pagination,
26425
+ triggerReload: false
26426
+ }
26427
+ });
26428
+ reportsLoadingStateDispatch({
26429
+ type: "SET_REPORT_LOADING",
26430
+ id: reportId,
26431
+ data: false
26432
+ });
26433
+ if (fromCache) {
26434
+ totalCached += 1;
26435
+ }
26436
+ if (usePivotTask) {
26437
+ fetchReportRows({
26438
+ reportId,
26439
+ client,
26440
+ tenants,
26441
+ filters: allFilters,
26442
+ getToken,
26443
+ additionalProcessing,
26444
+ overwriteCache: forceCacheToRefresh
26445
+ }).then(({ rows, rowCount, columns, fields }) => {
26446
+ if (reportRequestIds.current[reportId] !== requestId) {
26447
+ return;
26448
+ }
26449
+ reportsDispatch({
26450
+ type: "UPDATE_REPORT",
26451
+ id: reportId,
26452
+ data: {
26453
+ rows,
26454
+ rowCount,
26455
+ columnInternal: columns,
26456
+ columns: columns.map((col) => ({
26457
+ field: col.field,
26458
+ format: col.format,
26459
+ label: col.label,
26460
+ inferFormat: col.inferFormat
26461
+ })),
26462
+ // @ts-ignore fields is not typed on QuillReportInternal
26463
+ fields,
26464
+ triggerReload: false
26465
+ }
26466
+ });
26467
+ }).catch((e) => {
26468
+ if (e instanceof Error && e.name === "AbortError") {
26469
+ return;
26470
+ }
26471
+ console.error("Failed to fetch background rows", e);
26472
+ });
26473
+ }
26474
+ return uncacheableReport;
26475
+ } catch (error2) {
26476
+ console.error(error2);
26477
+ return null;
26478
+ }
26479
+ }
24488
26480
  const { report, error } = await fetchReport({
24489
26481
  reportId,
24490
26482
  client,
24491
26483
  tenants,
24492
26484
  flags,
24493
26485
  additionalProcessing,
24494
- filters: dashboardFilters2.concat(customFilters).concat(customReportFiltersArray),
26486
+ filters: allFilters,
24495
26487
  getToken,
24496
26488
  eventTracking,
24497
- usePivotTask
26489
+ usePivotTask,
26490
+ overwriteCache: forceCacheToRefresh
26491
+ // usePivotTask: false,
24498
26492
  });
24499
26493
  if (error) {
24500
26494
  console.error(error);
@@ -24522,9 +26516,10 @@ var useDashboard = (dashboardName, config) => {
24522
26516
  reportId,
24523
26517
  client,
24524
26518
  tenants,
24525
- filters: dashboardFilters2.concat(customFilters).concat(customReportFiltersArray),
26519
+ filters: allFilters,
24526
26520
  getToken,
24527
- additionalProcessing
26521
+ additionalProcessing,
26522
+ overwriteCache: forceCacheToRefresh
24528
26523
  }).then(({ rows, rowCount, columns, fields }) => {
24529
26524
  if (reportRequestIds.current[reportId] !== requestId) {
24530
26525
  return;
@@ -24548,19 +26543,30 @@ var useDashboard = (dashboardName, config) => {
24548
26543
  }
24549
26544
  });
24550
26545
  }).catch((e) => {
24551
- if (e instanceof Error && e.name === "AbortError") return;
26546
+ if (e instanceof Error && e.name === "AbortError") {
26547
+ return;
26548
+ }
24552
26549
  console.error("Failed to fetch background rows", e);
24553
26550
  });
24554
26551
  }
24555
26552
  return report;
24556
26553
  })
24557
26554
  );
26555
+ if (!loadedDashes.includes(dashboardName) || !cacheEnabled || forceCacheToRefresh) {
26556
+ setLoadedDashes((prev) => prev.includes(dashboardName) ? prev : [...prev, dashboardName]);
26557
+ setLastUpdatedDict((prev) => ({ ...prev, [dashboardName]: Date.now() }));
26558
+ }
26559
+ if (logCacheStatistics) {
26560
+ console.log(`Dashboard "${dashboardName}": Cache Rate: ${(100 * totalCached / allReports.length).toFixed(1)}%, load time: ${((Date.now() - fetchStartTime) / 1e3).toFixed(2)} secs`);
26561
+ }
24558
26562
  };
24559
26563
  return {
24560
26564
  isLoading: !!isLoading || !sections,
24561
26565
  sections: isLoading ? null : sections,
24562
26566
  filters,
24563
- applyFilters
26567
+ applyFilters,
26568
+ lastUpdated,
26569
+ forceCacheRefresh
24564
26570
  };
24565
26571
  };
24566
26572
  var useDashboardReportInternal = (reportId, config) => {
@@ -24584,15 +26590,6 @@ var useDashboardReportInternal = (reportId, config) => {
24584
26590
  } = useDashboardInternal(reports[reportId]?.dashboardName ?? null);
24585
26591
  const [pageLoading, setPageLoading] = (0, import_react2.useState)(false);
24586
26592
  const [maxPage, setMaxPage] = (0, import_react2.useState)(0);
24587
- (0, import_react2.useEffect)(() => {
24588
- if (config?.initialFilters) {
24589
- customReportFiltersDispatch({
24590
- type: "ADD_CUSTOM_REPORT_FILTERS",
24591
- reportId,
24592
- data: config.initialFilters.map(convertCustomFilter)
24593
- });
24594
- }
24595
- }, []);
24596
26593
  const processedReport = (0, import_react2.useMemo)(() => {
24597
26594
  if (!reports[reportId]) return null;
24598
26595
  const dashboardName = reports[reportId].dashboardName;
@@ -24797,6 +26794,7 @@ var useDashboardReportInternal = (reportId, config) => {
24797
26794
  };
24798
26795
  var useDashboardReport = (reportId, config) => {
24799
26796
  const { report, loading, applyFilters, deleteReport, nextPage } = useDashboardReportInternal(reportId, config);
26797
+ const { customReportFiltersDispatch } = (0, import_react2.useContext)(ReportFiltersContext);
24800
26798
  const fetchingRef = (0, import_react2.useRef)(false);
24801
26799
  const fetchNextPage = async () => {
24802
26800
  if (fetchingRef.current) {
@@ -24811,6 +26809,15 @@ var useDashboardReport = (reportId, config) => {
24811
26809
  fetchingRef.current = false;
24812
26810
  }
24813
26811
  };
26812
+ (0, import_react2.useEffect)(() => {
26813
+ if (config?.initialFilters) {
26814
+ customReportFiltersDispatch({
26815
+ type: "ADD_CUSTOM_REPORT_FILTERS",
26816
+ reportId,
26817
+ data: config.initialFilters.map(convertCustomFilter)
26818
+ });
26819
+ }
26820
+ }, []);
24814
26821
  return {
24815
26822
  report,
24816
26823
  isLoading: loading || fetchingRef.current,
@@ -25275,7 +27282,7 @@ function QuillCustomDocumentComponent({
25275
27282
  }
25276
27283
 
25277
27284
  // src/Chart.tsx
25278
- var import_date_fns12 = require("date-fns");
27285
+ var import_date_fns14 = require("date-fns");
25279
27286
 
25280
27287
  // src/components/Chart/BarList.tsx
25281
27288
  var import_react4 = __toESM(require("react"), 1);
@@ -27964,19 +29971,23 @@ var RenderLegend = ({
27964
29971
  const seeAllMeasureRef = (0, import_react12.useRef)(null);
27965
29972
  const seeAllTriggerRef = (0, import_react12.useRef)(null);
27966
29973
  const itemRefs = (0, import_react12.useRef)([]);
27967
- if (!payload || payload.length === 0) return null;
27968
- const maxItems = limit ?? payload.length;
29974
+ const safePayload = payload ?? [];
29975
+ const maxItems = limit ?? safePayload.length;
27969
29976
  const measuredLimit = visibleCount ?? maxItems;
27970
- const visiblePayload = payload.slice(0, Math.min(maxItems, measuredLimit));
29977
+ const visiblePayload = safePayload.slice(0, Math.min(maxItems, measuredLimit));
27971
29978
  const handleOpen = () => setIsOpen(true);
27972
29979
  const handleClose = () => setIsOpen(false);
27973
29980
  (0, import_react12.useLayoutEffect)(() => {
27974
29981
  if (!containerRef.current) return;
27975
- if (!payload.length) return;
29982
+ if (!safePayload.length) {
29983
+ setShowSeeAll(false);
29984
+ setVisibleCount(null);
29985
+ return;
29986
+ }
27976
29987
  const updateVisibleCount = () => {
27977
29988
  const containerWidth = containerRef.current?.offsetWidth ?? 0;
27978
29989
  if (!containerWidth) return;
27979
- const maxCount = Math.min(maxItems, payload.length);
29990
+ const maxCount = Math.min(maxItems, safePayload.length);
27980
29991
  const seeAllWidth = getOuterWidth(seeAllMeasureRef.current);
27981
29992
  const computeCount = (reserveSeeAll) => {
27982
29993
  const availableWidth = containerWidth - (reserveSeeAll ? seeAllWidth : 0);
@@ -27992,7 +30003,7 @@ var RenderLegend = ({
27992
30003
  return Math.max(1, nextCount);
27993
30004
  };
27994
30005
  const countWithSeeAll = computeCount(true);
27995
- const shouldShowSeeAll = payload.length > countWithSeeAll;
30006
+ const shouldShowSeeAll = safePayload.length > countWithSeeAll;
27996
30007
  const finalCount = shouldShowSeeAll ? countWithSeeAll : computeCount(false);
27997
30008
  setShowSeeAll(shouldShowSeeAll);
27998
30009
  setVisibleCount(finalCount);
@@ -28001,7 +30012,8 @@ var RenderLegend = ({
28001
30012
  const observer = new ResizeObserver(updateVisibleCount);
28002
30013
  observer.observe(containerRef.current);
28003
30014
  return () => observer.disconnect();
28004
- }, [payload.length, maxItems]);
30015
+ }, [safePayload.length, maxItems]);
30016
+ if (!safePayload.length) return null;
28005
30017
  return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
28006
30018
  "div",
28007
30019
  {
@@ -28041,7 +30053,7 @@ var RenderLegend = ({
28041
30053
  justifyContent: "flex-start",
28042
30054
  flexWrap: "nowrap"
28043
30055
  },
28044
- children: payload.slice(0, maxItems).map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
30056
+ children: safePayload.slice(0, maxItems).map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
28045
30057
  "div",
28046
30058
  {
28047
30059
  ref: (element) => {
@@ -28130,7 +30142,7 @@ var RenderLegend = ({
28130
30142
  maxWidth: 520,
28131
30143
  gap: "0.5rem"
28132
30144
  },
28133
- children: payload.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
30145
+ children: safePayload.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
28134
30146
  LegendItem,
28135
30147
  {
28136
30148
  entry,
@@ -28480,8 +30492,8 @@ var PieChartWrapper = import_react13.default.forwardRef(
28480
30492
  cy: "50%",
28481
30493
  startAngle: 90,
28482
30494
  endAngle: -270,
28483
- innerRadius: isDonut ? showLegend ? "50%" : "70%" : "0%",
28484
- outerRadius: showLegend ? "70%" : "100%",
30495
+ innerRadius: isDonut ? "70%" : "0%",
30496
+ outerRadius: "100%",
28485
30497
  paddingAngle: 0,
28486
30498
  dataKey: category,
28487
30499
  nameKey: index,
@@ -29074,8 +31086,8 @@ var import_recharts2 = require("recharts");
29074
31086
  init_valueFormatter();
29075
31087
 
29076
31088
  // src/utils/axisFormatter.ts
29077
- var import_date_fns9 = require("date-fns");
29078
- var import_date_fns_tz3 = require("date-fns-tz");
31089
+ var import_date_fns11 = require("date-fns");
31090
+ var import_date_fns_tz4 = require("date-fns-tz");
29079
31091
  var axisFormatter = ({ value, field, fields }) => {
29080
31092
  if (field === void 0 || field === null) return "";
29081
31093
  if (value === void 0 || value === null) return "";
@@ -29191,9 +31203,9 @@ var formatPercent2 = (value) => {
29191
31203
  return formatter.format(Number(value));
29192
31204
  };
29193
31205
  var _getUTCDateHelper2 = (value, fmt) => {
29194
- const utcDate = (0, import_date_fns_tz3.utcToZonedTime)(new Date(value), "UTC");
29195
- if (!(0, import_date_fns9.isValid)(utcDate)) return "Invalid date";
29196
- return (0, import_date_fns9.format)(utcDate, fmt);
31206
+ const utcDate = (0, import_date_fns_tz4.utcToZonedTime)(new Date(value), "UTC");
31207
+ if (!(0, import_date_fns11.isValid)(utcDate)) return "Invalid date";
31208
+ return (0, import_date_fns11.format)(utcDate, fmt);
29197
31209
  };
29198
31210
  var format_YYYY2 = (value) => _getUTCDateHelper2(value, "yyyy");
29199
31211
  var format_MMM_dd = (value) => _getUTCDateHelper2(value, "dd MMM");
@@ -29201,31 +31213,31 @@ var format_MMM_yyyy2 = (value) => _getUTCDateHelper2(value, "MMM yyyy");
29201
31213
  var format_hh_ap_pm2 = (value) => _getUTCDateHelper2(value, "hh:mm aa");
29202
31214
  var format_MMM_dd_yyyy2 = (value) => _getUTCDateHelper2(value, "dd MMM yyyy");
29203
31215
  var format_MMM_dd_MMM_dd = (value) => {
29204
- const utcDate = (0, import_date_fns_tz3.utcToZonedTime)(new Date(value), "UTC");
29205
- if (!(0, import_date_fns9.isValid)(utcDate)) return "Invalid date";
29206
- const monday = (0, import_date_fns9.startOfWeek)(utcDate, { weekStartsOn: 1 });
29207
- const sunday = (0, import_date_fns9.endOfWeek)(utcDate, { weekStartsOn: 1 });
29208
- if ((0, import_date_fns9.format)(monday, "MMM") === (0, import_date_fns9.format)(sunday, "MMM")) {
29209
- return `${(0, import_date_fns9.format)(monday, "MMM dd")} - ${(0, import_date_fns9.format)(sunday, "dd")}`;
31216
+ const utcDate = (0, import_date_fns_tz4.utcToZonedTime)(new Date(value), "UTC");
31217
+ if (!(0, import_date_fns11.isValid)(utcDate)) return "Invalid date";
31218
+ const monday = (0, import_date_fns11.startOfWeek)(utcDate, { weekStartsOn: 1 });
31219
+ const sunday = (0, import_date_fns11.endOfWeek)(utcDate, { weekStartsOn: 1 });
31220
+ if ((0, import_date_fns11.format)(monday, "MMM") === (0, import_date_fns11.format)(sunday, "MMM")) {
31221
+ return `${(0, import_date_fns11.format)(monday, "MMM dd")} - ${(0, import_date_fns11.format)(sunday, "dd")}`;
29210
31222
  } else {
29211
- return `${(0, import_date_fns9.format)(monday, "MMM dd")} - ${(0, import_date_fns9.format)(sunday, "MMM dd")}`;
31223
+ return `${(0, import_date_fns11.format)(monday, "MMM dd")} - ${(0, import_date_fns11.format)(sunday, "MMM dd")}`;
29212
31224
  }
29213
31225
  };
29214
31226
  var format_MMM_dd_hh_mm_ap_pm2 = (value) => {
29215
- const utcDate = (0, import_date_fns_tz3.utcToZonedTime)(new Date(value), "UTC");
29216
- if (!(0, import_date_fns9.isValid)(utcDate)) return "Invalid date";
31227
+ const utcDate = (0, import_date_fns_tz4.utcToZonedTime)(new Date(value), "UTC");
31228
+ if (!(0, import_date_fns11.isValid)(utcDate)) return "Invalid date";
29217
31229
  const formatStr = utcDate.getMinutes() === 0 ? "MMM do h a" : "MMM do h:mm a";
29218
- const res = (0, import_date_fns9.format)(utcDate, formatStr);
31230
+ const res = (0, import_date_fns11.format)(utcDate, formatStr);
29219
31231
  return res.slice(0, -2) + res.slice(-2).toLowerCase();
29220
31232
  };
29221
31233
  var format_wo_yyyy2 = (value) => {
29222
- const utcDate = (0, import_date_fns_tz3.utcToZonedTime)(new Date(value), "UTC");
29223
- if (!(0, import_date_fns9.isValid)(utcDate)) return "Invalid date";
29224
- return `${(0, import_date_fns9.getWeek)(utcDate)},${utcDate.getFullYear()}`;
31234
+ const utcDate = (0, import_date_fns_tz4.utcToZonedTime)(new Date(value), "UTC");
31235
+ if (!(0, import_date_fns11.isValid)(utcDate)) return "Invalid date";
31236
+ return `${(0, import_date_fns11.getWeek)(utcDate)},${utcDate.getFullYear()}`;
29225
31237
  };
29226
31238
 
29227
31239
  // src/components/Chart/ChartTooltip.tsx
29228
- var import_date_fns10 = require("date-fns");
31240
+ var import_date_fns12 = require("date-fns");
29229
31241
 
29230
31242
  // src/components/Chart/ChartTooltipFrame.tsx
29231
31243
  var import_jsx_runtime30 = require("react/jsx-runtime");
@@ -29420,7 +31432,7 @@ var ChartTooltipPrimary = (props) => /* @__PURE__ */ (0, import_jsx_runtime33.js
29420
31432
  paddingTop: 2,
29421
31433
  paddingBottom: 2
29422
31434
  },
29423
- children: !isNaN(new Date(props.label)) && props.dateFormatter ? props.dateFormatter(props.label) : !isNaN(new Date(props.label)) ? (0, import_date_fns10.format)(new Date(props.label), "MMM yyyy") : props.label
31435
+ children: !isNaN(new Date(props.label)) && props.dateFormatter ? props.dateFormatter(props.label) : !isNaN(new Date(props.label)) ? (0, import_date_fns12.format)(new Date(props.label), "MMM yyyy") : props.label
29424
31436
  }
29425
31437
  )
29426
31438
  }
@@ -29469,8 +31481,8 @@ function reformatComparisonPayload(props, primaryLabel, comparisonLabel) {
29469
31481
  const nameKey = isComparison ? `comparison_${props.xAxisField}` : props.xAxisField;
29470
31482
  const days = LABEL_TO_DAYS[primaryLabel] ?? 0;
29471
31483
  const primaryDate = item.payload[props.xAxisField] ?? 0;
29472
- const compDate = (0, import_date_fns10.subDays)(new Date(primaryDate), days + 1);
29473
- const date = item.payload[nameKey] ?? (0, import_date_fns10.format)(compDate, props.xAxisFormat);
31484
+ const compDate = (0, import_date_fns12.subDays)(new Date(primaryDate), days + 1);
31485
+ const date = item.payload[nameKey] ?? (0, import_date_fns12.format)(compDate, props.xAxisFormat);
29474
31486
  const name2 = props.dateFormatter(date);
29475
31487
  const color2 = item.color;
29476
31488
  const value = props.valueFormatter(item.value, item.name);
@@ -29503,7 +31515,7 @@ function reformatComparisonPayload(props, primaryLabel, comparisonLabel) {
29503
31515
  return columnsByKey;
29504
31516
  }
29505
31517
  function getTooltipLabel(props, altTooltipLabel, isDateXAxis) {
29506
- return props.payload.length <= 2 && altTooltipLabel && isDateXAxis ? !isNaN(new Date(altTooltipLabel)) && props.dateFormatter ? props.dateFormatter(altTooltipLabel) : !isNaN(new Date(altTooltipLabel)) ? (0, import_date_fns10.format)(new Date(altTooltipLabel), "MMM yyyy") : altTooltipLabel : !isNaN(new Date(props.label)) && props.dateFormatter ? props.dateFormatter(props.label) : !isNaN(new Date(props.label)) ? (0, import_date_fns10.format)(new Date(props.label), "MMM yyyy") : props.label;
31518
+ return props.payload.length <= 2 && altTooltipLabel && isDateXAxis ? !isNaN(new Date(altTooltipLabel)) && props.dateFormatter ? props.dateFormatter(altTooltipLabel) : !isNaN(new Date(altTooltipLabel)) ? (0, import_date_fns12.format)(new Date(altTooltipLabel), "MMM yyyy") : altTooltipLabel : !isNaN(new Date(props.label)) && props.dateFormatter ? props.dateFormatter(props.label) : !isNaN(new Date(props.label)) ? (0, import_date_fns12.format)(new Date(props.label), "MMM yyyy") : props.label;
29507
31519
  }
29508
31520
  function ChartTooltipComparison(props) {
29509
31521
  const isDateXAxis = isDateFormat(props.xAxisFormat);
@@ -30519,7 +32531,7 @@ init_dateRangePickerUtils();
30519
32531
 
30520
32532
  // src/DateRangePicker/QuillDateRangePicker.tsx
30521
32533
  var import_react20 = require("react");
30522
- var import_date_fns11 = require("date-fns");
32534
+ var import_date_fns13 = require("date-fns");
30523
32535
 
30524
32536
  // src/components/QuillSelect.tsx
30525
32537
  var import_react19 = require("react");
@@ -30965,9 +32977,9 @@ function QuillDateRangePicker({
30965
32977
  ]
30966
32978
  }
30967
32979
  ),
30968
- localStartDate && (0, import_date_fns11.format)(localStartDate, "MMM dd, yyyy"),
32980
+ localStartDate && (0, import_date_fns13.format)(localStartDate, "MMM dd, yyyy"),
30969
32981
  localStartDate ? " - " : "Pick a date",
30970
- localEndDate && (0, import_date_fns11.format)(localEndDate, "MMM dd, yyyy")
32982
+ localEndDate && (0, import_date_fns13.format)(localEndDate, "MMM dd, yyyy")
30971
32983
  ]
30972
32984
  }
30973
32985
  ),
@@ -31034,21 +33046,21 @@ function CalendarRow({
31034
33046
  updateDateFilter,
31035
33047
  setLocalPreset
31036
33048
  }) {
31037
- const firstMonthDisplayedDates = (0, import_date_fns11.eachDayOfInterval)({
31038
- start: (0, import_date_fns11.startOfWeek)(anchorStartDate),
31039
- end: (0, import_date_fns11.endOfWeek)((0, import_date_fns11.endOfMonth)(anchorStartDate))
33049
+ const firstMonthDisplayedDates = (0, import_date_fns13.eachDayOfInterval)({
33050
+ start: (0, import_date_fns13.startOfWeek)(anchorStartDate),
33051
+ end: (0, import_date_fns13.endOfWeek)((0, import_date_fns13.endOfMonth)(anchorStartDate))
31040
33052
  });
31041
- const secondMonthDisplayedDates = (0, import_date_fns11.eachDayOfInterval)({
31042
- start: (0, import_date_fns11.startOfWeek)((0, import_date_fns11.startOfMonth)(anchorEndDate)),
31043
- end: (0, import_date_fns11.endOfWeek)(anchorEndDate)
33053
+ const secondMonthDisplayedDates = (0, import_date_fns13.eachDayOfInterval)({
33054
+ start: (0, import_date_fns13.startOfWeek)((0, import_date_fns13.startOfMonth)(anchorEndDate)),
33055
+ end: (0, import_date_fns13.endOfWeek)(anchorEndDate)
31044
33056
  });
31045
33057
  const incrementAnchorDates = () => {
31046
- setAnchorStartDate((0, import_date_fns11.startOfMonth)((0, import_date_fns11.addMonths)(anchorStartDate, 1)));
31047
- setAnchorEndDate((0, import_date_fns11.endOfMonth)((0, import_date_fns11.addMonths)(anchorEndDate, 1)));
33058
+ setAnchorStartDate((0, import_date_fns13.startOfMonth)((0, import_date_fns13.addMonths)(anchorStartDate, 1)));
33059
+ setAnchorEndDate((0, import_date_fns13.endOfMonth)((0, import_date_fns13.addMonths)(anchorEndDate, 1)));
31048
33060
  };
31049
33061
  const decrementAnchorDates = () => {
31050
- setAnchorStartDate((0, import_date_fns11.startOfMonth)((0, import_date_fns11.subMonths)(anchorStartDate, 1)));
31051
- setAnchorEndDate((0, import_date_fns11.endOfMonth)((0, import_date_fns11.subMonths)(anchorEndDate, 1)));
33062
+ setAnchorStartDate((0, import_date_fns13.startOfMonth)((0, import_date_fns13.subMonths)(anchorStartDate, 1)));
33063
+ setAnchorEndDate((0, import_date_fns13.endOfMonth)((0, import_date_fns13.subMonths)(anchorEndDate, 1)));
31052
33064
  };
31053
33065
  return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { style: { position: "absolute", zIndex: 100, marginTop: 12 }, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
31054
33066
  "div",
@@ -31144,7 +33156,7 @@ function CalendarRow({
31144
33156
  color: theme.primaryTextColor,
31145
33157
  fontWeight: 600
31146
33158
  },
31147
- children: (0, import_date_fns11.format)(anchorStartDate, "MMM yyyy")
33159
+ children: (0, import_date_fns13.format)(anchorStartDate, "MMM yyyy")
31148
33160
  }
31149
33161
  )
31150
33162
  ]
@@ -31208,7 +33220,7 @@ function CalendarRow({
31208
33220
  color: theme.primaryTextColor,
31209
33221
  fontWeight: 600
31210
33222
  },
31211
- children: (0, import_date_fns11.format)(anchorEndDate, "MMM yyyy")
33223
+ children: (0, import_date_fns13.format)(anchorEndDate, "MMM yyyy")
31212
33224
  }
31213
33225
  ),
31214
33226
  /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
@@ -31302,11 +33314,11 @@ function DayPicker({
31302
33314
  setLocalPreset,
31303
33315
  theme
31304
33316
  }) {
31305
- const isStartDate = (0, import_date_fns11.differenceInDays)((0, import_date_fns11.startOfDay)(date), (0, import_date_fns11.startOfDay)(localStartDate || 0)) === 0;
31306
- const isEndDate = (0, import_date_fns11.differenceInDays)((0, import_date_fns11.startOfDay)(date), (0, import_date_fns11.startOfDay)(localEndDate || 0)) === 0;
31307
- const isBetweenStartAndEnd = (0, import_date_fns11.isBefore)(date, localEndDate || 0) && (0, import_date_fns11.isAfter)(date, localStartDate || 0);
31308
- const isBeginningOfWeek = (0, import_date_fns11.differenceInDays)((0, import_date_fns11.startOfWeek)(date), date) === 0;
31309
- const isEndOfWeek = (0, import_date_fns11.differenceInDays)((0, import_date_fns11.endOfWeek)(date), date) === 0;
33317
+ const isStartDate = (0, import_date_fns13.differenceInDays)((0, import_date_fns13.startOfDay)(date), (0, import_date_fns13.startOfDay)(localStartDate || 0)) === 0;
33318
+ const isEndDate = (0, import_date_fns13.differenceInDays)((0, import_date_fns13.startOfDay)(date), (0, import_date_fns13.startOfDay)(localEndDate || 0)) === 0;
33319
+ const isBetweenStartAndEnd = (0, import_date_fns13.isBefore)(date, localEndDate || 0) && (0, import_date_fns13.isAfter)(date, localStartDate || 0);
33320
+ const isBeginningOfWeek = (0, import_date_fns13.differenceInDays)((0, import_date_fns13.startOfWeek)(date), date) === 0;
33321
+ const isEndOfWeek = (0, import_date_fns13.differenceInDays)((0, import_date_fns13.endOfWeek)(date), date) === 0;
31310
33322
  return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
31311
33323
  "button",
31312
33324
  {
@@ -31338,7 +33350,7 @@ function DayPicker({
31338
33350
  });
31339
33351
  setLocalPreset("");
31340
33352
  }
31341
- if (localStartDate && localEndDate && (0, import_date_fns11.isAfter)(date, localStartDate)) {
33353
+ if (localStartDate && localEndDate && (0, import_date_fns13.isAfter)(date, localStartDate)) {
31342
33354
  setLocalEndDate(date);
31343
33355
  updateDateFilter({
31344
33356
  startDate: localStartDate,
@@ -31346,7 +33358,7 @@ function DayPicker({
31346
33358
  });
31347
33359
  setLocalPreset("");
31348
33360
  }
31349
- if (localStartDate && localEndDate && (0, import_date_fns11.isBefore)(date, localStartDate)) {
33361
+ if (localStartDate && localEndDate && (0, import_date_fns13.isBefore)(date, localStartDate)) {
31350
33362
  setLocalStartDate(date);
31351
33363
  updateDateFilter({
31352
33364
  startDate: date,
@@ -31354,42 +33366,42 @@ function DayPicker({
31354
33366
  });
31355
33367
  setLocalPreset("");
31356
33368
  }
31357
- if (localStartDate && localEndDate && (0, import_date_fns11.differenceInDays)((0, import_date_fns11.startOfDay)(date), (0, import_date_fns11.startOfDay)(localStartDate)) === 0) {
33369
+ if (localStartDate && localEndDate && (0, import_date_fns13.differenceInDays)((0, import_date_fns13.startOfDay)(date), (0, import_date_fns13.startOfDay)(localStartDate)) === 0) {
31358
33370
  setLocalStartDate(void 0);
31359
33371
  setLocalEndDate(void 0);
31360
33372
  }
31361
33373
  },
31362
- children: (0, import_date_fns11.format)(date, "d")
33374
+ children: (0, import_date_fns13.format)(date, "d")
31363
33375
  }
31364
33376
  );
31365
33377
  }
31366
33378
  function getAnchorStartDate(startDate, endDate) {
31367
33379
  if (!startDate && !endDate) {
31368
- return (0, import_date_fns11.startOfMonth)((0, import_date_fns11.subMonths)(/* @__PURE__ */ new Date(), 1));
33380
+ return (0, import_date_fns13.startOfMonth)((0, import_date_fns13.subMonths)(/* @__PURE__ */ new Date(), 1));
31369
33381
  }
31370
33382
  if (startDate && !endDate) {
31371
- return (0, import_date_fns11.startOfMonth)(startDate);
33383
+ return (0, import_date_fns13.startOfMonth)(startDate);
31372
33384
  }
31373
33385
  if (!startDate && endDate) {
31374
- return (0, import_date_fns11.startOfMonth)((0, import_date_fns11.subMonths)(endDate, 1));
33386
+ return (0, import_date_fns13.startOfMonth)((0, import_date_fns13.subMonths)(endDate, 1));
31375
33387
  }
31376
33388
  if (startDate && endDate) {
31377
- return (0, import_date_fns11.startOfMonth)(startDate);
33389
+ return (0, import_date_fns13.startOfMonth)(startDate);
31378
33390
  }
31379
33391
  return /* @__PURE__ */ new Date();
31380
33392
  }
31381
33393
  function getAnchorEndDate(startDate, endDate) {
31382
33394
  if (!startDate && !endDate) {
31383
- return (0, import_date_fns11.endOfMonth)(/* @__PURE__ */ new Date());
33395
+ return (0, import_date_fns13.endOfMonth)(/* @__PURE__ */ new Date());
31384
33396
  }
31385
33397
  if (startDate && !endDate) {
31386
- return (0, import_date_fns11.endOfMonth)((0, import_date_fns11.addMonths)(startDate, 1));
33398
+ return (0, import_date_fns13.endOfMonth)((0, import_date_fns13.addMonths)(startDate, 1));
31387
33399
  }
31388
33400
  if (!startDate && endDate) {
31389
- return (0, import_date_fns11.endOfMonth)(endDate);
33401
+ return (0, import_date_fns13.endOfMonth)(endDate);
31390
33402
  }
31391
33403
  if (startDate && endDate) {
31392
- return (0, import_date_fns11.endOfMonth)((0, import_date_fns11.addMonths)(startDate, 1));
33404
+ return (0, import_date_fns13.endOfMonth)((0, import_date_fns13.addMonths)(startDate, 1));
31393
33405
  }
31394
33406
  return /* @__PURE__ */ new Date();
31395
33407
  }
@@ -32573,6 +34585,164 @@ function DashboardFilter2({
32573
34585
  // src/Chart.tsx
32574
34586
  init_paginationProcessing();
32575
34587
 
34588
+ // src/utils/cloudCacheValidation.ts
34589
+ var LIMIT_CLAUSE_REGEX = /^limit\b\s+(?:all|\d+|\$\d+|:[a-zA-Z_][a-zA-Z0-9_]*|\?)/i;
34590
+ var SQL_CONTENT_TO_IGNORE_REGEX = /'(?:''|[^'])*'|"(?:[^"]|"")*"|`[^`]*`|\[[^\]]*\]|--[^\n]*|\/\*[\s\S]*?\*\//g;
34591
+ function isWordChar(char) {
34592
+ if (!char) {
34593
+ return false;
34594
+ }
34595
+ return /[A-Za-z0-9_]/.test(char);
34596
+ }
34597
+ function getFinalSqlStatement(query) {
34598
+ const statements = query.split(";").map((statement) => statement.trim()).filter((statement) => statement.length > 0);
34599
+ return statements[statements.length - 1] ?? "";
34600
+ }
34601
+ function hasTopLevelLimitClause(statement) {
34602
+ let depth = 0;
34603
+ for (let i = 0; i < statement.length; i += 1) {
34604
+ const char = statement[i];
34605
+ if (char === "(") {
34606
+ depth += 1;
34607
+ continue;
34608
+ }
34609
+ if (char === ")") {
34610
+ depth = Math.max(0, depth - 1);
34611
+ continue;
34612
+ }
34613
+ if (depth !== 0) {
34614
+ continue;
34615
+ }
34616
+ const previousChar = i > 0 ? statement[i - 1] : void 0;
34617
+ if (isWordChar(previousChar)) {
34618
+ continue;
34619
+ }
34620
+ if (!LIMIT_CLAUSE_REGEX.test(statement.slice(i))) {
34621
+ continue;
34622
+ }
34623
+ return true;
34624
+ }
34625
+ return false;
34626
+ }
34627
+ function unwrapIdentifier(identifier) {
34628
+ if (!identifier) {
34629
+ return "";
34630
+ }
34631
+ const trimmed = identifier.trim();
34632
+ if (trimmed.length < 2) {
34633
+ return trimmed;
34634
+ }
34635
+ const startsAndEndsWithDoubleQuote = trimmed.startsWith('"') && trimmed.endsWith('"');
34636
+ const startsAndEndsWithSingleQuote = trimmed.startsWith("'") && trimmed.endsWith("'");
34637
+ const startsAndEndsWithBackticks = trimmed.startsWith("`") && trimmed.endsWith("`");
34638
+ const startsAndEndsWithBrackets = trimmed.startsWith("[") && trimmed.endsWith("]");
34639
+ if (startsAndEndsWithDoubleQuote || startsAndEndsWithSingleQuote || startsAndEndsWithBackticks || startsAndEndsWithBrackets) {
34640
+ return trimmed.slice(1, -1);
34641
+ }
34642
+ return trimmed;
34643
+ }
34644
+ function normalizeIdentifier(identifier) {
34645
+ return unwrapIdentifier(identifier).toLowerCase();
34646
+ }
34647
+ function hasRowFieldWithIdentifier(row, normalizedField) {
34648
+ if (!row || !normalizedField) {
34649
+ return false;
34650
+ }
34651
+ return Object.keys(row).some(
34652
+ (fieldName) => normalizeIdentifier(fieldName) === normalizedField
34653
+ );
34654
+ }
34655
+ function reportReferencesField(report, field, table) {
34656
+ const normalizedField = normalizeIdentifier(field);
34657
+ if (!normalizedField) {
34658
+ return false;
34659
+ }
34660
+ const referencedColumns = report?.referencedColumns ?? {};
34661
+ let entries = Object.entries(referencedColumns);
34662
+ if (entries.length === 0) {
34663
+ return false;
34664
+ }
34665
+ const normalizedTable = normalizeIdentifier(table);
34666
+ if (normalizedTable) {
34667
+ entries = entries.filter(
34668
+ ([tableName]) => normalizeIdentifier(tableName) === normalizedTable
34669
+ );
34670
+ }
34671
+ const referencedFields = entries.flatMap(([, fields]) => fields ?? []);
34672
+ if (referencedFields.length === 0) {
34673
+ return false;
34674
+ }
34675
+ return referencedFields.some((referencedField) => {
34676
+ const normalizedReferencedField = normalizeIdentifier(referencedField);
34677
+ return normalizedReferencedField === normalizedField || normalizedReferencedField === "*";
34678
+ });
34679
+ }
34680
+ function isDateFieldMissingInReport(report) {
34681
+ if (!report?.dateField?.field || !report.dateField.table) {
34682
+ return false;
34683
+ }
34684
+ const dateField = report.dateField;
34685
+ if (!reportReferencesField(report, dateField.field, dateField.table)) {
34686
+ return true;
34687
+ }
34688
+ const firstRow = report.rows?.[0];
34689
+ if (!firstRow) {
34690
+ return false;
34691
+ }
34692
+ const normalizedDateField = normalizeIdentifier(dateField.field);
34693
+ const dateFieldExistsInFirstRow = hasRowFieldWithIdentifier(
34694
+ firstRow,
34695
+ normalizedDateField
34696
+ );
34697
+ return !dateFieldExistsInFirstRow;
34698
+ }
34699
+ function hasLimitClause(query) {
34700
+ if (!query) {
34701
+ return false;
34702
+ }
34703
+ const sanitizedQuery = query.replace(SQL_CONTENT_TO_IGNORE_REGEX, " ");
34704
+ const finalStatement = getFinalSqlStatement(sanitizedQuery);
34705
+ if (!finalStatement) {
34706
+ return false;
34707
+ }
34708
+ return hasTopLevelLimitClause(finalStatement);
34709
+ }
34710
+ function reportUsesLimitClause(report) {
34711
+ const queriesToInspect = report?.itemQuery && report.itemQuery.length > 0 ? report.itemQuery : report?.queryString ? [report.queryString] : [];
34712
+ return queriesToInspect.some(hasLimitClause);
34713
+ }
34714
+ function getMissingDashboardFilterFields({
34715
+ rows = [],
34716
+ dashboardFilters = []
34717
+ }) {
34718
+ const dateIndex = dashboardFilters.findIndex(
34719
+ (filter) => filter.filterType === "date_range"
34720
+ );
34721
+ const requiredFields = dashboardFilters.flatMap((filter, index) => {
34722
+ if (index === dateIndex || !filter.field) {
34723
+ return [];
34724
+ }
34725
+ const normalizedField = normalizeIdentifier(filter.field);
34726
+ if (!normalizedField) {
34727
+ return [];
34728
+ }
34729
+ return [
34730
+ {
34731
+ displayField: unwrapIdentifier(filter.field),
34732
+ normalizedField
34733
+ }
34734
+ ];
34735
+ });
34736
+ const dedupedRequiredFields = requiredFields.filter(
34737
+ (field, index, fields) => fields.findIndex(
34738
+ (candidate) => candidate.normalizedField === field.normalizedField
34739
+ ) === index
34740
+ );
34741
+ return dedupedRequiredFields.filter(
34742
+ ({ normalizedField }) => rows.some((row) => !hasRowFieldWithIdentifier(row, normalizedField))
34743
+ ).map(({ displayField }) => displayField);
34744
+ }
34745
+
32576
34746
  // src/components/Dashboard/MetricComponent.tsx
32577
34747
  var import_react24 = require("react");
32578
34748
  init_dateRangePickerUtils();
@@ -32680,7 +34850,7 @@ function QuillMetricComponent({
32680
34850
  width: "100%"
32681
34851
  }
32682
34852
  }
32683
- ) : !report?.rows || report?.rows?.length === 0 || report.rows[0]?.[report.xAxisField] === null || report.rows[0]?.[report.xAxisField] === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
34853
+ ) : !report?.rows || report?.rows?.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
32684
34854
  "div",
32685
34855
  {
32686
34856
  style: {
@@ -36194,6 +38364,7 @@ function QuillTableDashboardComponent({
36194
38364
  }
36195
38365
 
36196
38366
  // src/Chart.tsx
38367
+ init_valueFormatter();
36197
38368
  var import_jsx_runtime49 = require("react/jsx-runtime");
36198
38369
  var MAX_ROWS_FOR_GENERIC_TABLE = 500;
36199
38370
  function sumByKey(arr, key) {
@@ -36230,7 +38401,8 @@ function Chart({
36230
38401
  filters,
36231
38402
  onClickChartElement,
36232
38403
  dateBucket,
36233
- propagateChanges
38404
+ propagateChanges,
38405
+ isAdmin = false
36234
38406
  }) {
36235
38407
  const [schemaData] = (0, import_react30.useContext)(SchemaDataContext);
36236
38408
  const { reload } = useReportInternal(reportId);
@@ -36352,6 +38524,25 @@ function Chart({
36352
38524
  }
36353
38525
  }, [report, theme]);
36354
38526
  const [client, clientLoading] = (0, import_react30.useContext)(ClientContext);
38527
+ const cloudCacheEnabled = (0, import_react30.useMemo)(() => {
38528
+ return !!client?.features?.cloudCache;
38529
+ }, [client]);
38530
+ const shouldShowCloudCacheValidationErrors = isAdmin && cloudCacheEnabled;
38531
+ const isMissingDateField = (0, import_react30.useMemo)(() => {
38532
+ if (!shouldShowCloudCacheValidationErrors) return false;
38533
+ return isDateFieldMissingInReport(report);
38534
+ }, [report, shouldShowCloudCacheValidationErrors]);
38535
+ const usesLimitInQuery = (0, import_react30.useMemo)(() => {
38536
+ if (!shouldShowCloudCacheValidationErrors) return false;
38537
+ return reportUsesLimitClause(report);
38538
+ }, [report, shouldShowCloudCacheValidationErrors]);
38539
+ const missingDashboardFilterFields = (0, import_react30.useMemo)(() => {
38540
+ if (!shouldShowCloudCacheValidationErrors || !report) return [];
38541
+ return getMissingDashboardFilterFields({
38542
+ rows: report.rows,
38543
+ dashboardFilters
38544
+ });
38545
+ }, [report, dashboardFilters, shouldShowCloudCacheValidationErrors]);
36355
38546
  const [error, setError] = (0, import_react30.useState)(void 0);
36356
38547
  const updateFilter = (filter, value, comparison) => {
36357
38548
  let filterValue = {};
@@ -36492,6 +38683,15 @@ function Chart({
36492
38683
  if (report?.error || error) {
36493
38684
  return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { style: containerStyle, className, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ChartError, { errorMessage: report?.error ?? error }) });
36494
38685
  }
38686
+ if (isMissingDateField) {
38687
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { style: containerStyle, className, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(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.` }) });
38688
+ }
38689
+ if (usesLimitInQuery) {
38690
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { style: containerStyle, className, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ChartError, { errorMessage: `The query for this report uses the LIMIT keyword, which is not supported when the cache is enabled.` }) });
38691
+ }
38692
+ if (missingDashboardFilterFields.length) {
38693
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { style: containerStyle, className, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ChartError, { errorMessage: `The query for this report is missing dashboard filter fields: ${missingDashboardFilterFields.join(", ")}` }) });
38694
+ }
36495
38695
  return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
36496
38696
  "div",
36497
38697
  {
@@ -36822,7 +39022,7 @@ var ChartDisplay = ({
36822
39022
  );
36823
39023
  }
36824
39024
  if (config?.chartType?.toLowerCase() === "metric") {
36825
- if (!config?.rows || config?.rows?.length === 0 || config?.rows[0]?.[config?.xAxisField] === null || config?.rows[0]?.[config?.xAxisField] === void 0) {
39025
+ if (!config?.rows || config?.rows?.length === 0) {
36826
39026
  return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
36827
39027
  "div",
36828
39028
  {
@@ -36860,6 +39060,36 @@ var ChartDisplay = ({
36860
39060
  }
36861
39061
  );
36862
39062
  }
39063
+ if (config?.pivotRows && config?.pivotRows?.length > 0) {
39064
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
39065
+ "div",
39066
+ {
39067
+ style: {
39068
+ fontFamily: theme?.fontFamily,
39069
+ fontSize: 32,
39070
+ color: theme?.primaryTextColor,
39071
+ fontWeight: "600",
39072
+ textOverflow: "ellipsis",
39073
+ margin: 0,
39074
+ whiteSpace: "nowrap",
39075
+ boxSizing: "content-box",
39076
+ maxWidth: "100%",
39077
+ textAlign: "left",
39078
+ overflow: "hidden",
39079
+ height: containerStyle?.height || "100%",
39080
+ display: "flex",
39081
+ width: "100%",
39082
+ flexDirection: "row",
39083
+ ...containerStyle
39084
+ },
39085
+ className,
39086
+ children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(QuillMetricComponent, { report: config ?? EMPTY_REPORT, children: quillFormat({
39087
+ value: config?.pivotRows?.[0]?.[config?.xAxisField],
39088
+ format: config?.xAxisFormat
39089
+ }) ?? "No results" })
39090
+ }
39091
+ );
39092
+ }
36863
39093
  return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
36864
39094
  "div",
36865
39095
  {
@@ -37799,7 +40029,7 @@ var FilterPopoverWrapper = ({
37799
40029
  // src/components/ReportBuilder/FilterModal.tsx
37800
40030
  var import_react35 = require("react");
37801
40031
  init_Filter();
37802
- var import_date_fns13 = require("date-fns");
40032
+ var import_date_fns15 = require("date-fns");
37803
40033
  init_textProcessing();
37804
40034
  init_filterProcessing();
37805
40035
  var import_jsx_runtime55 = require("react/jsx-runtime");
@@ -37833,10 +40063,10 @@ function FilterModal({
37833
40063
  const [unit, setUnit] = (0, import_react35.useState)("");
37834
40064
  const [unitOptions, setUnitOptions] = (0, import_react35.useState)([]);
37835
40065
  const [startDate, setStartDate] = (0, import_react35.useState)(
37836
- (0, import_date_fns13.startOfToday)().toISOString().substring(0, 10)
40066
+ (0, import_date_fns15.startOfToday)().toISOString().substring(0, 10)
37837
40067
  );
37838
40068
  const [endDate, setEndDate] = (0, import_react35.useState)(
37839
- (0, import_date_fns13.startOfToday)().toISOString().substring(0, 10)
40069
+ (0, import_date_fns15.startOfToday)().toISOString().substring(0, 10)
37840
40070
  );
37841
40071
  const [filterInitialized, setFilterInitialized] = (0, import_react35.useState)(false);
37842
40072
  const [table, setTable] = (0, import_react35.useState)(void 0);
@@ -37904,10 +40134,10 @@ function FilterModal({
37904
40134
  onOperatorChange(filter.operator);
37905
40135
  setUnit(filter.filterType === "date-filter" ? filter.value.unit : "");
37906
40136
  setStartDate(
37907
- filter.value?.startDate ? filter.value.startDate.substring(0, 10) : (0, import_date_fns13.startOfToday)().toISOString().substring(0, 10)
40137
+ filter.value?.startDate ? filter.value.startDate.substring(0, 10) : (0, import_date_fns15.startOfToday)().toISOString().substring(0, 10)
37908
40138
  );
37909
40139
  setEndDate(
37910
- filter.value?.endDate ? filter.value.endDate.substring(0, 10) : (0, import_date_fns13.startOfToday)().toISOString().substring(0, 10)
40140
+ filter.value?.endDate ? filter.value.endDate.substring(0, 10) : (0, import_date_fns15.startOfToday)().toISOString().substring(0, 10)
37911
40141
  );
37912
40142
  if (filter.filterType === "string-in-filter") {
37913
40143
  setSelectedOptions(
@@ -38002,8 +40232,8 @@ function FilterModal({
38002
40232
  DateOperator.LessThan,
38003
40233
  DateOperator.LessThanOrEqualTo,
38004
40234
  DateOperator.NotEqualTo
38005
- ].includes(operator2) && !(0, import_date_fns13.isValid)((0, import_date_fns13.parse)(value, "yyyy-mm-dd", /* @__PURE__ */ new Date())) && (filterInitialized || !filter)) {
38006
- setValue((0, import_date_fns13.startOfToday)().toISOString().substring(0, 10));
40235
+ ].includes(operator2) && !(0, import_date_fns15.isValid)((0, import_date_fns15.parse)(value, "yyyy-mm-dd", /* @__PURE__ */ new Date())) && (filterInitialized || !filter)) {
40236
+ setValue((0, import_date_fns15.startOfToday)().toISOString().substring(0, 10));
38007
40237
  } else if (type === FieldType.Date && [
38008
40238
  DateOperator.InTheLast,
38009
40239
  DateOperator.InTheCurrent,
@@ -38191,12 +40421,12 @@ function FilterModal({
38191
40421
  case DateOperator.LessThan:
38192
40422
  case DateOperator.GreaterThanOrEqualTo:
38193
40423
  case DateOperator.LessThanOrEqualTo: {
38194
- const parsedDate = (0, import_date_fns13.parse)(value, "yyyy-mm-dd", /* @__PURE__ */ new Date());
38195
- if (!(0, import_date_fns13.isValid)(parsedDate)) {
40424
+ const parsedDate = (0, import_date_fns15.parse)(value, "yyyy-mm-dd", /* @__PURE__ */ new Date());
40425
+ if (!(0, import_date_fns15.isValid)(parsedDate)) {
38196
40426
  alert("Please specify a valid date in yyyy-mm-dd");
38197
40427
  return;
38198
40428
  }
38199
- const normalizedDate = (0, import_date_fns13.format)(parsedDate, "yyyy-mm-dd");
40429
+ const normalizedDate = (0, import_date_fns15.format)(parsedDate, "yyyy-mm-dd");
38200
40430
  onSubmitFilter({
38201
40431
  field,
38202
40432
  filterType: "date-comparison-filter" /* DateComparisonFilter */,
@@ -38492,8 +40722,8 @@ function FilterModal({
38492
40722
  QuillDateRangePicker,
38493
40723
  {
38494
40724
  dateRange: {
38495
- startDate: startDate ? /* @__PURE__ */ new Date(startDate + "T00:00:00") : (0, import_date_fns13.startOfToday)(),
38496
- endDate: endDate ? /* @__PURE__ */ new Date(endDate + "T00:00:00") : (0, import_date_fns13.startOfToday)()
40725
+ startDate: startDate ? /* @__PURE__ */ new Date(startDate + "T00:00:00") : (0, import_date_fns15.startOfToday)(),
40726
+ endDate: endDate ? /* @__PURE__ */ new Date(endDate + "T00:00:00") : (0, import_date_fns15.startOfToday)()
38497
40727
  },
38498
40728
  preset: "",
38499
40729
  presetOptions: [],
@@ -38720,6 +40950,9 @@ function validateTemplatesAgainstFilters(filters, templates) {
38720
40950
  }
38721
40951
  async function addTemplatesToDashboard(name2, newTemplates, client, dashboardData, getToken, eventTracking) {
38722
40952
  try {
40953
+ if (!newTemplates?.length) {
40954
+ return null;
40955
+ }
38723
40956
  const { publicKey, tenants } = client;
38724
40957
  if (tenants) {
38725
40958
  throw new Error("Adding from template not yet supported for tenants");
@@ -38772,6 +41005,7 @@ async function addTemplatesToDashboard(name2, newTemplates, client, dashboardDat
38772
41005
  function: "addTemplatesToDashboard"
38773
41006
  }
38774
41007
  });
41008
+ return null;
38775
41009
  }
38776
41010
  }
38777
41011
 
@@ -40649,7 +42883,7 @@ var PivotList = ({
40649
42883
  };
40650
42884
 
40651
42885
  // src/internals/ReportBuilder/PivotModal.tsx
40652
- var import_date_fns14 = require("date-fns");
42886
+ var import_date_fns16 = require("date-fns");
40653
42887
  init_textProcessing();
40654
42888
  init_pivotProcessing();
40655
42889
  init_tableProcessing();
@@ -42477,7 +44711,7 @@ var validateReport = (formData, dashboardData, defaultDateFilter, allTables) =>
42477
44711
 
42478
44712
  // src/components/Chart/InternalChart.tsx
42479
44713
  var import_react42 = require("react");
42480
- var import_date_fns15 = require("date-fns");
44714
+ var import_date_fns17 = require("date-fns");
42481
44715
  init_Filter();
42482
44716
  init_filterProcessing();
42483
44717
  init_dateRangePickerUtils();
@@ -44317,7 +46551,7 @@ function ChartBuilder({
44317
46551
  template: true,
44318
46552
  referenceLines: []
44319
46553
  };
44320
- const updateDashboardFilters = async (dashboardName) => {
46554
+ const updateDashboardFilters2 = async (dashboardName) => {
44321
46555
  if (dashboardConfig && dashboardConfig[dashboardName]) {
44322
46556
  return dashboardConfig[dashboardName];
44323
46557
  }
@@ -44639,7 +46873,7 @@ function ChartBuilder({
44639
46873
  if (destinationDashboardName) {
44640
46874
  dashboardName = destinationDashboardName;
44641
46875
  }
44642
- const curDashboard = await updateDashboardFilters(dashboardName);
46876
+ const curDashboard = await updateDashboardFilters2(dashboardName);
44643
46877
  setDashboardOptions(dashboardOptions2);
44644
46878
  curFormData.dashboardName = dashboardName;
44645
46879
  const curSchemaData = schemaData.schemaWithCustomFields;
@@ -45926,7 +48160,7 @@ function ChartBuilder({
45926
48160
  value: formData.dashboardName || "",
45927
48161
  onChange: async (e) => {
45928
48162
  handleChange(e.target.value, "dashboardName");
45929
- await updateDashboardFilters(e.target.value);
48163
+ await updateDashboardFilters2(e.target.value);
45930
48164
  },
45931
48165
  options: dashboardOptions.map((elem) => ({
45932
48166
  label: elem.label,
@@ -54257,7 +56491,7 @@ function StaticChart(props) {
54257
56491
  pageLoading,
54258
56492
  nextPage,
54259
56493
  prevPage,
54260
- sortRows
56494
+ sortRows: sortRows2
54261
56495
  } = useDashboardReportInternal(reportId);
54262
56496
  const baseStyle = report?.chartType && CHART_TYPE_STYLES[report.chartType] ? CHART_TYPE_STYLES[report.chartType] : DEFAULT_STYLE;
54263
56497
  const mergedStyle = className ? { ...containerStyle ?? {} } : { ...baseStyle, ...containerStyle ?? {} };
@@ -54277,7 +56511,7 @@ function StaticChart(props) {
54277
56511
  }
54278
56512
  };
54279
56513
  const onSortChange = (sort) => {
54280
- sortRows({
56514
+ sortRows2({
54281
56515
  field: sort.field,
54282
56516
  direction: sort.direction
54283
56517
  });
@@ -54286,29 +56520,10 @@ function StaticChart(props) {
54286
56520
  ...report,
54287
56521
  ...report.pivot ? formattedPivotRowsAndColumns(report) : {}
54288
56522
  } : void 0;
54289
- const patchedConfig = config && config.pivot ? {
54290
- ...config,
54291
- yAxisFields: config.columns?.slice(1).map((col) => ({
54292
- field: col.field,
54293
- label: col.label ?? col.field,
54294
- format: col.format ?? "number"
54295
- })) ?? config.yAxisFields
54296
- } : config;
54297
- if (patchedConfig) {
54298
- const sample = (patchedConfig.pivotRows ?? patchedConfig.rows ?? []).slice(0, 1).map((row) => {
54299
- const field = patchedConfig.yAxisFields?.[0]?.field;
54300
- return {
54301
- ...row,
54302
- _firstField: field,
54303
- _firstFieldType: field ? typeof row[field] : void 0
54304
- };
54305
- });
54306
- }
54307
56523
  return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
54308
56524
  ChartDisplay,
54309
56525
  {
54310
- reportId,
54311
- config: patchedConfig,
56526
+ config,
54312
56527
  onClickChartElement,
54313
56528
  loading,
54314
56529
  className,