@quillsql/react 2.16.11 → 2.16.12

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.js CHANGED
@@ -1292,6 +1292,8 @@ import {
1292
1292
  addDays,
1293
1293
  differenceInDays,
1294
1294
  endOfDay,
1295
+ endOfMonth,
1296
+ endOfQuarter,
1295
1297
  endOfToday,
1296
1298
  format as format2,
1297
1299
  isEqual,
@@ -1300,9 +1302,13 @@ import {
1300
1302
  min,
1301
1303
  set,
1302
1304
  startOfDay,
1305
+ startOfMonth,
1306
+ startOfQuarter,
1303
1307
  startOfToday,
1304
1308
  startOfWeek as startOfWeek2,
1305
- sub
1309
+ sub,
1310
+ subMonths,
1311
+ subQuarters
1306
1312
  } from "date-fns";
1307
1313
  var primaryRangeCustomIntervals, adjustForLeapYear, convertCustomIntervalToDateRange, getLabelForCustomInterval, convertPresetOptionsToSelectableList, PRIMARY_RANGE, COMPARISON_OPTIONS, COMPARISON_RANGE, defaultOptionsV2, reportBuilderOptions, getRangeFromPresetOptions;
1308
1314
  var init_dateRangePickerUtils = __esm({
@@ -1430,6 +1436,9 @@ var init_dateRangePickerUtils = __esm({
1430
1436
  value: 12,
1431
1437
  unit: "months"
1432
1438
  },
1439
+ {
1440
+ type: "previous_month"
1441
+ },
1433
1442
  {
1434
1443
  type: "relative",
1435
1444
  value: 1,
@@ -1469,11 +1478,33 @@ var init_dateRangePickerUtils = __esm({
1469
1478
  })
1470
1479
  };
1471
1480
  }
1472
- case "relative":
1481
+ case "relative": {
1482
+ if (interval2.unit === "months" && interval2.value === 1 && (!interval2.label || interval2.label === "Last month")) {
1483
+ const lastMonth = subMonths(startOfToday(), 1);
1484
+ return {
1485
+ startDate: startOfMonth(lastMonth),
1486
+ endDate: endOfMonth(lastMonth)
1487
+ };
1488
+ }
1473
1489
  return {
1474
1490
  startDate: sub(startOfToday(), { [interval2.unit]: interval2.value }),
1475
1491
  endDate: endOfToday()
1476
1492
  };
1493
+ }
1494
+ case "previous_month": {
1495
+ const lastMonth = subMonths(startOfToday(), 1);
1496
+ return {
1497
+ startDate: startOfMonth(lastMonth),
1498
+ endDate: endOfMonth(lastMonth)
1499
+ };
1500
+ }
1501
+ case "previous_quarter": {
1502
+ const lastQuarter = subQuarters(startOfToday(), 1);
1503
+ return {
1504
+ startDate: startOfQuarter(lastQuarter),
1505
+ endDate: endOfQuarter(lastQuarter)
1506
+ };
1507
+ }
1477
1508
  case "repeating": {
1478
1509
  const currentDate = /* @__PURE__ */ new Date();
1479
1510
  const currentYear = currentDate.getFullYear();
@@ -1518,24 +1549,39 @@ var init_dateRangePickerUtils = __esm({
1518
1549
  getLabelForCustomInterval = (interval2) => {
1519
1550
  switch (interval2.type) {
1520
1551
  case "week":
1521
- return "This week";
1552
+ return interval2.label ?? "This week";
1522
1553
  case "static":
1523
1554
  return interval2.label ?? "Custom";
1524
1555
  case "relative":
1525
1556
  return interval2.label ?? `Last ${interval2.value === 1 ? "" : interval2.value + " "}${interval2.value === 1 ? interval2.unit.slice(0, -1) : interval2.unit}`;
1557
+ case "previous_month":
1558
+ return interval2.label ?? "Last month";
1559
+ case "previous_quarter":
1560
+ return interval2.label ?? "Last quarter";
1526
1561
  case "repeating":
1527
- return "This " + interval2.label.toLowerCase();
1562
+ if (interval2.label === "Month") return "This month";
1563
+ if (interval2.label === "Year") return "This year";
1564
+ return interval2.label;
1528
1565
  }
1529
1566
  };
1530
1567
  convertPresetOptionsToSelectableList = (customIntervals, defaultIntervals) => {
1531
- const defaultCustomIntervals = defaultIntervals.map(
1532
- (interval2) => {
1533
- if (interval2.label === "This week") {
1534
- return {
1568
+ const customLabelMap = /* @__PURE__ */ new Map();
1569
+ defaultIntervals.forEach((interval2) => {
1570
+ if (interval2.customLabel) {
1571
+ customLabelMap.set(interval2.label, interval2.customLabel);
1572
+ }
1573
+ });
1574
+ const defaultCustomIntervals = defaultIntervals.flatMap((interval2) => {
1575
+ let createdIntervals = [];
1576
+ if (interval2.label === "This week") {
1577
+ createdIntervals = [
1578
+ {
1535
1579
  type: "week"
1536
- };
1537
- } else if (interval2.label === "This month" || interval2.label === "Monthly") {
1538
- return {
1580
+ }
1581
+ ];
1582
+ } else if (interval2.label === "This month" || interval2.label === "Monthly") {
1583
+ createdIntervals = [
1584
+ {
1539
1585
  type: "repeating",
1540
1586
  label: "Month",
1541
1587
  loopDate: { day: 1, month: 1 },
@@ -1615,9 +1661,11 @@ var init_dateRangePickerUtils = __esm({
1615
1661
  endDate: { day: 31, month: 12 }
1616
1662
  }
1617
1663
  ]
1618
- };
1619
- } else if (interval2.label === "This year" || interval2.label === "Yearly") {
1620
- return {
1664
+ }
1665
+ ];
1666
+ } else if (interval2.label === "This year" || interval2.label === "Yearly") {
1667
+ createdIntervals = [
1668
+ {
1621
1669
  type: "repeating",
1622
1670
  label: "Year",
1623
1671
  loopDate: { day: 1, month: 1 },
@@ -1631,42 +1679,69 @@ var init_dateRangePickerUtils = __esm({
1631
1679
  endDate: { day: 31, month: 12 }
1632
1680
  }
1633
1681
  ]
1634
- };
1635
- } else if (interval2.label === "Last 7 days") {
1636
- return {
1682
+ }
1683
+ ];
1684
+ } else if (interval2.label === "Last 7 days") {
1685
+ createdIntervals = [
1686
+ {
1637
1687
  type: "relative",
1638
1688
  value: 7,
1639
1689
  unit: "days"
1640
- };
1641
- } else if (interval2.label === "Last 30 days") {
1642
- return {
1690
+ }
1691
+ ];
1692
+ } else if (interval2.label === "Last 30 days") {
1693
+ createdIntervals = [
1694
+ {
1643
1695
  type: "relative",
1644
1696
  value: 30,
1645
1697
  unit: "days"
1646
- };
1647
- } else if (interval2.label === "Last 90 days") {
1648
- return {
1698
+ }
1699
+ ];
1700
+ } else if (interval2.label === "Last 90 days") {
1701
+ createdIntervals = [
1702
+ {
1649
1703
  type: "relative",
1650
1704
  value: 90,
1651
1705
  unit: "days"
1652
- };
1653
- } else if (interval2.label === "Last 6 months") {
1654
- return {
1706
+ }
1707
+ ];
1708
+ } else if (interval2.label === "Last 6 months") {
1709
+ createdIntervals = [
1710
+ {
1655
1711
  type: "relative",
1656
1712
  value: 6,
1657
1713
  unit: "months"
1658
- };
1659
- } else if (interval2.label === "Last 12 months") {
1660
- return {
1714
+ }
1715
+ ];
1716
+ } else if (interval2.label === "Last 12 months") {
1717
+ createdIntervals = [
1718
+ {
1661
1719
  type: "relative",
1662
1720
  value: 12,
1663
1721
  unit: "months"
1664
- };
1665
- } else {
1666
- throw new Error("Invalid interval");
1667
- }
1722
+ }
1723
+ ];
1724
+ } else if (interval2.label === "Last month") {
1725
+ createdIntervals = [
1726
+ {
1727
+ type: "previous_month"
1728
+ }
1729
+ ];
1730
+ } else if (interval2.label === "Last quarter") {
1731
+ createdIntervals = [
1732
+ {
1733
+ type: "previous_quarter"
1734
+ }
1735
+ ];
1668
1736
  }
1669
- );
1737
+ if (interval2.customLabel && createdIntervals.length > 0) {
1738
+ return createdIntervals.map((i) => ({
1739
+ ...i,
1740
+ label: interval2.customLabel
1741
+ }));
1742
+ }
1743
+ return createdIntervals;
1744
+ });
1670
1745
  return customIntervals?.length || defaultCustomIntervals?.length ? (defaultCustomIntervals ?? []).concat(customIntervals ?? []).flatMap((option) => {
1671
1746
  if (option.type === "repeating" && option.loopStart) {
1672
1747
  const presets = [];
@@ -1708,8 +1783,19 @@ var init_dateRangePickerUtils = __esm({
1708
1783
  }
1709
1784
  };
1710
1785
  const currentYear = currentDate.getFullYear();
1786
+ const baseLabel = getLabelForSubInterval(currentSubInterval);
1787
+ let customLabel2;
1788
+ if (option.label && option.label !== "Month" && option.label !== "Year") {
1789
+ customLabel2 = option.label;
1790
+ } else {
1791
+ if (option.label === "Month") {
1792
+ customLabel2 = customLabelMap.get("This month") || customLabelMap.get("Monthly");
1793
+ } else if (option.label === "Year") {
1794
+ customLabel2 = customLabelMap.get("This year") || customLabelMap.get("Yearly");
1795
+ }
1796
+ }
1711
1797
  presets.push({
1712
- label: getLabelForSubInterval(currentSubInterval),
1798
+ label: customLabel2 || baseLabel,
1713
1799
  value: getLabelForSubInterval(currentSubInterval).toUpperCase().replace(/ /g, "_") ?? "",
1714
1800
  startDate: set(/* @__PURE__ */ new Date(), {
1715
1801
  year: currentYear,
@@ -1741,9 +1827,12 @@ var init_dateRangePickerUtils = __esm({
1741
1827
  return presets;
1742
1828
  }
1743
1829
  const dateRange = convertCustomIntervalToDateRange(option);
1830
+ const generatedLabel = getLabelForCustomInterval(option);
1831
+ const customLabel = customLabelMap.get(generatedLabel);
1832
+ const finalLabel = customLabel || generatedLabel;
1744
1833
  return [
1745
1834
  {
1746
- label: getLabelForCustomInterval(option),
1835
+ label: finalLabel,
1747
1836
  // Value is option label in uppercase with spaces replaced by underscores
1748
1837
  value: getLabelForCustomInterval(option).toUpperCase().replace(/ /g, "_") ?? "",
1749
1838
  startDate: dateRange.startDate,
@@ -1800,6 +1889,7 @@ var init_dateRangePickerUtils = __esm({
1800
1889
  LAST_12_MONTHS: convertCustomIntervalToDateRange(
1801
1890
  primaryRangeCustomIntervals[7]
1802
1891
  ),
1892
+ LAST_MONTH: convertCustomIntervalToDateRange(primaryRangeCustomIntervals[8]),
1803
1893
  ALL_TIME: { startDate: void 0, endDate: void 0 }
1804
1894
  };
1805
1895
  COMPARISON_OPTIONS = [
@@ -1874,6 +1964,12 @@ var init_dateRangePickerUtils = __esm({
1874
1964
  startDate: PRIMARY_RANGE["LAST_30_DAYS"].startDate,
1875
1965
  endDate: PRIMARY_RANGE["LAST_30_DAYS"].endDate
1876
1966
  },
1967
+ {
1968
+ value: "LAST_MONTH",
1969
+ label: "Last month",
1970
+ startDate: PRIMARY_RANGE["LAST_MONTH"].startDate,
1971
+ endDate: PRIMARY_RANGE["LAST_MONTH"].endDate
1972
+ },
1877
1973
  {
1878
1974
  value: "LAST_90_DAYS",
1879
1975
  label: "Last 90 days",
@@ -2439,7 +2535,7 @@ import {
2439
2535
  parse as parse2,
2440
2536
  subDays,
2441
2537
  subHours,
2442
- subMonths,
2538
+ subMonths as subMonths2,
2443
2539
  subWeeks,
2444
2540
  subYears
2445
2541
  } from "date-fns";
@@ -2565,7 +2661,7 @@ function parseStartEndDate(operatorLeft, operatorRight, valueLeft, valueRight, u
2565
2661
  leftDate = format3(subYears(currentDate, valueLeft), "yyyy-MM-dd");
2566
2662
  break;
2567
2663
  case "month":
2568
- leftDate = format3(subMonths(currentDate, valueLeft), "yyyy-MM-dd");
2664
+ leftDate = format3(subMonths2(currentDate, valueLeft), "yyyy-MM-dd");
2569
2665
  break;
2570
2666
  case "week":
2571
2667
  leftDate = format3(subWeeks(currentDate, valueLeft), "yyyy-MM-dd");
@@ -2588,7 +2684,7 @@ function parseStartEndDate(operatorLeft, operatorRight, valueLeft, valueRight, u
2588
2684
  rightDate = format3(subYears(currentDate, valueRight), "yyyy-MM-dd");
2589
2685
  break;
2590
2686
  case "month":
2591
- rightDate = format3(subMonths(currentDate, valueRight), "yyyy-MM-dd");
2687
+ rightDate = format3(subMonths2(currentDate, valueRight), "yyyy-MM-dd");
2592
2688
  break;
2593
2689
  case "week":
2594
2690
  rightDate = format3(subWeeks(currentDate, valueRight), "yyyy-MM-dd");
@@ -15372,7 +15468,10 @@ var init_filterProcessing = __esm({
15372
15468
  })
15373
15469
  ).values()
15374
15470
  ],
15375
- options: defaultOptionsV2,
15471
+ options: filter.presetOptions || filter.defaultPresetRanges ? convertPresetOptionsToSelectableList(
15472
+ filter.presetOptions ?? [],
15473
+ filter.defaultPresetRanges ?? []
15474
+ ) : defaultOptionsV2,
15376
15475
  preset: filter.primaryRange,
15377
15476
  dashboardName,
15378
15477
  comparisonRange: filter.comparison && comparisonRangeStart && comparisonRangeEnd ? {
@@ -17955,6 +18054,22 @@ var init_tableProcessing = __esm({
17955
18054
  return {};
17956
18055
  }
17957
18056
  let uniqueValuesByColumn = {};
18057
+ const aliasToField = {};
18058
+ const fieldToAlias = {};
18059
+ columns.forEach((col) => {
18060
+ if (col.alias) {
18061
+ aliasToField[col.alias] = col.field;
18062
+ fieldToAlias[col.field] = col.alias;
18063
+ }
18064
+ });
18065
+ reportBuilderState?.columns?.forEach((col) => {
18066
+ if (col.alias) {
18067
+ aliasToField[col.alias] = col.field;
18068
+ if (!fieldToAlias[col.field]) {
18069
+ fieldToAlias[col.field] = col.alias;
18070
+ }
18071
+ }
18072
+ });
17958
18073
  let rows = resp?.rows;
17959
18074
  if (!rows && fetchResult.queries?.queryResults?.[0]?.rows) {
17960
18075
  rows = fetchResult.queries.queryResults[0].rows;
@@ -17963,11 +18078,24 @@ var init_tableProcessing = __esm({
17963
18078
  uniqueValuesByColumn = resp.uniqueValues;
17964
18079
  } else if (rows && Array.isArray(rows)) {
17965
18080
  rows.forEach((row) => {
17966
- if (row.field && row.string_values) {
18081
+ if (row?.field && row?.string_values) {
17967
18082
  uniqueValuesByColumn[row.field] = row.string_values;
17968
18083
  }
17969
18084
  });
17970
18085
  }
18086
+ const normalizedUniqueValuesByColumn = {};
18087
+ Object.entries(uniqueValuesByColumn).forEach(([key, values]) => {
18088
+ if (!Array.isArray(values)) {
18089
+ return;
18090
+ }
18091
+ const fieldKey = aliasToField[key] || key;
18092
+ normalizedUniqueValuesByColumn[fieldKey] = values;
18093
+ const aliasKey = fieldToAlias[fieldKey];
18094
+ if (aliasKey) {
18095
+ normalizedUniqueValuesByColumn[aliasKey] = values;
18096
+ }
18097
+ });
18098
+ uniqueValuesByColumn = normalizedUniqueValuesByColumn;
17971
18099
  const uniqueValues2 = {};
17972
18100
  tables.forEach((tableName) => {
17973
18101
  const tableUniqueValues = {};
@@ -20359,7 +20487,18 @@ async function fetchReportRows({
20359
20487
  getToken
20360
20488
  });
20361
20489
  const resp = await parseFetchResponse(client, "report", fetchResp, getToken);
20362
- return { rows: resp.rows || [], rowCount: resp.rowCount || 0 };
20490
+ if (client.databaseType?.toLowerCase() === "bigquery") {
20491
+ parseValueFromBigQueryDates(resp.rows, resp.fields);
20492
+ }
20493
+ const columns = (resp.fields || []).map(
20494
+ (field) => convertPostgresColumn(field)
20495
+ );
20496
+ return {
20497
+ rows: resp.rows || [],
20498
+ rowCount: resp.rowCount || 0,
20499
+ columns,
20500
+ fields: resp.fields || []
20501
+ };
20363
20502
  }
20364
20503
  async function fetchReport({
20365
20504
  reportId,
@@ -20469,6 +20608,7 @@ async function processReportResponse({
20469
20608
  tenants,
20470
20609
  skipPivotFetch = false
20471
20610
  }) {
20611
+ const shouldSkipPivotFetch = skipPivotFetch || !!resp?.pivotRows && !!resp?.fields;
20472
20612
  const dashboardItem = {
20473
20613
  ...resp,
20474
20614
  filtersApplied: filters?.filter(
@@ -20499,7 +20639,7 @@ async function processReportResponse({
20499
20639
  getToken,
20500
20640
  tenants,
20501
20641
  eventTracking,
20502
- skipPivotFetch
20642
+ skipPivotFetch: shouldSkipPivotFetch
20503
20643
  });
20504
20644
  if (additionalProcessing) {
20505
20645
  reportInfo.pagination = additionalProcessing.page;
@@ -22528,6 +22668,34 @@ var ContextProvider = ({
22528
22668
  );
22529
22669
  if (currentProcessId === loadDashboardProcessId.current[dashboardName]) {
22530
22670
  if (!equal(resp, curDashboardConfig)) {
22671
+ Object.values(
22672
+ resp.sections ?? {}
22673
+ ).flat().forEach((report) => {
22674
+ const existing = reports[report.id];
22675
+ if (existing) {
22676
+ const merged = {
22677
+ ...report,
22678
+ // prefer fresh server metadata (chartType, flags, etc.)
22679
+ // preserve existing row payload if server response is metadata-only
22680
+ ...existing.rows ? { rows: existing.rows } : {},
22681
+ ...existing.rowCount !== void 0 ? { rowCount: existing.rowCount } : {},
22682
+ ...existing.columns ? { columns: existing.columns } : {},
22683
+ ...existing.columnInternal ? { columnInternal: existing.columnInternal } : {},
22684
+ ...existing.pagination ? { pagination: existing.pagination } : {}
22685
+ };
22686
+ reportsDispatch({
22687
+ type: "UPDATE_REPORT",
22688
+ id: report.id,
22689
+ data: merged
22690
+ });
22691
+ } else {
22692
+ reportsDispatch({
22693
+ type: "ADD_REPORT",
22694
+ id: report.id,
22695
+ data: report
22696
+ });
22697
+ }
22698
+ });
22531
22699
  dashboardConfigDispatch({
22532
22700
  type: "UPDATE_DASHBOARD",
22533
22701
  id: dashboardName,
@@ -23201,7 +23369,7 @@ init_columnType();
23201
23369
  import {
23202
23370
  add,
23203
23371
  startOfDay as startOfDay3,
23204
- startOfMonth,
23372
+ startOfMonth as startOfMonth2,
23205
23373
  startOfWeek as startOfWeek3,
23206
23374
  startOfYear
23207
23375
  } from "date-fns";
@@ -23349,11 +23517,12 @@ var useDashboardInternal = (dashboardName, customFilters) => {
23349
23517
  dashboardName,
23350
23518
  sectionOrder
23351
23519
  };
23352
- void quillFetchWithToken({
23353
- client,
23354
- task: "set-section-order",
23355
- metadata: body
23356
- }).then((response) => {
23520
+ try {
23521
+ const response = await quillFetchWithToken({
23522
+ client,
23523
+ task: "set-section-order",
23524
+ metadata: body
23525
+ });
23357
23526
  Object.entries(response?.data?.newIds ?? {}).forEach(
23358
23527
  ([section, newId2]) => {
23359
23528
  dashboardConfigDispatch({
@@ -23375,11 +23544,24 @@ var useDashboardInternal = (dashboardName, customFilters) => {
23375
23544
  });
23376
23545
  }
23377
23546
  );
23378
- }).catch((error) => {
23379
- if (error instanceof Error && error.name === "AbortError") {
23547
+ } catch (e) {
23548
+ if (e instanceof Error && e.name === "AbortError") {
23380
23549
  return;
23381
23550
  }
23382
- });
23551
+ eventTracking?.logError?.({
23552
+ type: "bug",
23553
+ // TODO: determine type
23554
+ severity: "high",
23555
+ message: "Error setting section order",
23556
+ errorMessage: e?.message,
23557
+ errorStack: e?.stack,
23558
+ errorData: {
23559
+ caller: "useDashboard",
23560
+ function: "setSectionOrder"
23561
+ }
23562
+ });
23563
+ console.error(e);
23564
+ }
23383
23565
  }
23384
23566
  };
23385
23567
  function isDashboardFilterLoading(filterName) {
@@ -23637,7 +23819,8 @@ var useDashboards = () => {
23637
23819
  (preset) => ({
23638
23820
  ...preset,
23639
23821
  loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
23640
- loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0
23822
+ loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0,
23823
+ customLabel: preset.customLabel
23641
23824
  })
23642
23825
  )
23643
23826
  } : void 0,
@@ -23697,7 +23880,8 @@ var useDashboards = () => {
23697
23880
  (preset) => ({
23698
23881
  ...preset,
23699
23882
  loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
23700
- loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0
23883
+ loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0,
23884
+ customLabel: preset.customLabel
23701
23885
  })
23702
23886
  ),
23703
23887
  dashboardName: updated.data.dashboard.name,
@@ -23815,6 +23999,7 @@ var useDashboard = (dashboardName, config) => {
23815
23999
  const { customReportFilters } = useContext(ReportFiltersContext);
23816
24000
  const { eventTracking } = useContext(EventTrackingContext);
23817
24001
  const customFiltersRef = useRef2(customReportFilters);
24002
+ const reportRequestIds = useRef2({});
23818
24003
  useEffect2(() => {
23819
24004
  customFiltersRef.current = customReportFilters;
23820
24005
  }, [customReportFilters]);
@@ -23957,6 +24142,8 @@ var useDashboard = (dashboardName, config) => {
23957
24142
  await Promise.all(
23958
24143
  allReports.map(async (reportInfo) => {
23959
24144
  const reportId = reportInfo.id;
24145
+ const requestId = (reportRequestIds.current[reportId] ?? 0) + 1;
24146
+ reportRequestIds.current[reportId] = requestId;
23960
24147
  reportsLoadingStateDispatch({
23961
24148
  type: "SET_REPORT_LOADING",
23962
24149
  id: reportId,
@@ -23974,6 +24161,7 @@ var useDashboard = (dashboardName, config) => {
23974
24161
  const additionalProcessing = {
23975
24162
  page: pagination
23976
24163
  };
24164
+ const usePivotTask = !!reportInfo.pivot;
23977
24165
  const { report, error } = await fetchReport({
23978
24166
  reportId,
23979
24167
  client,
@@ -23982,12 +24170,16 @@ var useDashboard = (dashboardName, config) => {
23982
24170
  additionalProcessing,
23983
24171
  filters: dashboardFilters2.concat(customFilters).concat(customReportFiltersArray),
23984
24172
  getToken,
23985
- eventTracking
24173
+ eventTracking,
24174
+ usePivotTask
23986
24175
  });
23987
24176
  if (error) {
23988
24177
  console.error(error);
23989
24178
  return null;
23990
24179
  }
24180
+ if (reportRequestIds.current[reportId] !== requestId) {
24181
+ return null;
24182
+ }
23991
24183
  reportsDispatch({
23992
24184
  type: "UPDATE_REPORT",
23993
24185
  id: reportId,
@@ -24001,6 +24193,40 @@ var useDashboard = (dashboardName, config) => {
24001
24193
  id: reportId,
24002
24194
  data: false
24003
24195
  });
24196
+ if (usePivotTask) {
24197
+ fetchReportRows({
24198
+ reportId,
24199
+ client,
24200
+ tenants,
24201
+ filters: dashboardFilters2.concat(customFilters).concat(customReportFiltersArray),
24202
+ getToken,
24203
+ additionalProcessing
24204
+ }).then(({ rows, rowCount, columns, fields }) => {
24205
+ if (reportRequestIds.current[reportId] !== requestId) {
24206
+ return;
24207
+ }
24208
+ reportsDispatch({
24209
+ type: "UPDATE_REPORT",
24210
+ id: reportId,
24211
+ data: {
24212
+ rows,
24213
+ rowCount,
24214
+ columnInternal: columns,
24215
+ columns: columns.map((col) => ({
24216
+ field: col.field,
24217
+ format: col.format,
24218
+ label: col.label,
24219
+ inferFormat: col.inferFormat
24220
+ })),
24221
+ // @ts-ignore fields is not typed on QuillReportInternal
24222
+ fields
24223
+ }
24224
+ });
24225
+ }).catch((e) => {
24226
+ if (e instanceof Error && e.name === "AbortError") return;
24227
+ console.error("Failed to fetch background rows", e);
24228
+ });
24229
+ }
24004
24230
  return report;
24005
24231
  })
24006
24232
  );
@@ -28322,6 +28548,8 @@ var axisFormatter = ({ value, field, fields }) => {
28322
28548
  return formatPercent2(value);
28323
28549
  case "dollar_amount":
28324
28550
  return formatDollarAmount2(value);
28551
+ case "dollar_cents":
28552
+ return formatDollarCents2(value);
28325
28553
  case "whole_number":
28326
28554
  return formatWholeNumber2(value);
28327
28555
  case "two_decimal_places":
@@ -28386,6 +28614,12 @@ var formatterDollar2 = new Intl.NumberFormat("en-US", {
28386
28614
  currency: "USD",
28387
28615
  maximumFractionDigits: 0
28388
28616
  });
28617
+ var formatterDollarCents = new Intl.NumberFormat("en-US", {
28618
+ style: "currency",
28619
+ currency: "USD",
28620
+ minimumFractionDigits: 2,
28621
+ maximumFractionDigits: 2
28622
+ });
28389
28623
  var formatDollarAmount2 = (value) => {
28390
28624
  const num = Number(value ?? 0);
28391
28625
  if (num >= 1e3 || num === 0) {
@@ -28394,6 +28628,9 @@ var formatDollarAmount2 = (value) => {
28394
28628
  return formatterDollar2.format(num);
28395
28629
  }
28396
28630
  };
28631
+ var formatDollarCents2 = (value) => {
28632
+ return formatterDollarCents.format(Number(value ?? 0));
28633
+ };
28397
28634
  var formatterBigWholeNumber = new Intl.NumberFormat("en-US", {
28398
28635
  minimumSignificantDigits: 1,
28399
28636
  maximumSignificantDigits: 2,
@@ -29809,11 +30046,11 @@ import {
29809
30046
  useState as useState11
29810
30047
  } from "react";
29811
30048
  import {
29812
- startOfMonth as startOfMonth2,
29813
- endOfMonth,
30049
+ startOfMonth as startOfMonth3,
30050
+ endOfMonth as endOfMonth2,
29814
30051
  format as format7,
29815
30052
  eachDayOfInterval,
29816
- subMonths as subMonths2,
30053
+ subMonths as subMonths3,
29817
30054
  startOfWeek as startOfWeek5,
29818
30055
  endOfWeek as endOfWeek3,
29819
30056
  differenceInDays as differenceInDays3,
@@ -30338,19 +30575,19 @@ function CalendarRow({
30338
30575
  }) {
30339
30576
  const firstMonthDisplayedDates = eachDayOfInterval({
30340
30577
  start: startOfWeek5(anchorStartDate),
30341
- end: endOfWeek3(endOfMonth(anchorStartDate))
30578
+ end: endOfWeek3(endOfMonth2(anchorStartDate))
30342
30579
  });
30343
30580
  const secondMonthDisplayedDates = eachDayOfInterval({
30344
- start: startOfWeek5(startOfMonth2(anchorEndDate)),
30581
+ start: startOfWeek5(startOfMonth3(anchorEndDate)),
30345
30582
  end: endOfWeek3(anchorEndDate)
30346
30583
  });
30347
30584
  const incrementAnchorDates = () => {
30348
- setAnchorStartDate(startOfMonth2(addMonths(anchorStartDate, 1)));
30349
- setAnchorEndDate(endOfMonth(addMonths(anchorEndDate, 1)));
30585
+ setAnchorStartDate(startOfMonth3(addMonths(anchorStartDate, 1)));
30586
+ setAnchorEndDate(endOfMonth2(addMonths(anchorEndDate, 1)));
30350
30587
  };
30351
30588
  const decrementAnchorDates = () => {
30352
- setAnchorStartDate(startOfMonth2(subMonths2(anchorStartDate, 1)));
30353
- setAnchorEndDate(endOfMonth(subMonths2(anchorEndDate, 1)));
30589
+ setAnchorStartDate(startOfMonth3(subMonths3(anchorStartDate, 1)));
30590
+ setAnchorEndDate(endOfMonth2(subMonths3(anchorEndDate, 1)));
30354
30591
  };
30355
30592
  return /* @__PURE__ */ jsx39("div", { style: { position: "absolute", zIndex: 100, marginTop: 12 }, children: /* @__PURE__ */ jsxs29(
30356
30593
  "div",
@@ -30667,31 +30904,31 @@ function DayPicker({
30667
30904
  }
30668
30905
  function getAnchorStartDate(startDate, endDate) {
30669
30906
  if (!startDate && !endDate) {
30670
- return startOfMonth2(subMonths2(/* @__PURE__ */ new Date(), 1));
30907
+ return startOfMonth3(subMonths3(/* @__PURE__ */ new Date(), 1));
30671
30908
  }
30672
30909
  if (startDate && !endDate) {
30673
- return startOfMonth2(startDate);
30910
+ return startOfMonth3(startDate);
30674
30911
  }
30675
30912
  if (!startDate && endDate) {
30676
- return startOfMonth2(subMonths2(endDate, 1));
30913
+ return startOfMonth3(subMonths3(endDate, 1));
30677
30914
  }
30678
30915
  if (startDate && endDate) {
30679
- return startOfMonth2(startDate);
30916
+ return startOfMonth3(startDate);
30680
30917
  }
30681
30918
  return /* @__PURE__ */ new Date();
30682
30919
  }
30683
30920
  function getAnchorEndDate(startDate, endDate) {
30684
30921
  if (!startDate && !endDate) {
30685
- return endOfMonth(/* @__PURE__ */ new Date());
30922
+ return endOfMonth2(/* @__PURE__ */ new Date());
30686
30923
  }
30687
30924
  if (startDate && !endDate) {
30688
- return endOfMonth(addMonths(startDate, 1));
30925
+ return endOfMonth2(addMonths(startDate, 1));
30689
30926
  }
30690
30927
  if (!startDate && endDate) {
30691
- return endOfMonth(endDate);
30928
+ return endOfMonth2(endDate);
30692
30929
  }
30693
30930
  if (startDate && endDate) {
30694
- return endOfMonth(addMonths(startDate, 1));
30931
+ return endOfMonth2(addMonths(startDate, 1));
30695
30932
  }
30696
30933
  return /* @__PURE__ */ new Date();
30697
30934
  }
@@ -32513,6 +32750,7 @@ function DataLoader({
32513
32750
  rowsAbortController.current?.abort();
32514
32751
  rowsAbortController.current = new AbortController();
32515
32752
  const usePivotTask = !!item.pivot;
32753
+ let backgroundFetch = null;
32516
32754
  try {
32517
32755
  if (dashboardName) {
32518
32756
  const { report: fetchedReport, error: error2 } = await fetchReport({
@@ -32531,16 +32769,59 @@ function DataLoader({
32531
32769
  eventTracking,
32532
32770
  usePivotTask
32533
32771
  });
32772
+ const existingReport = dashboard[item.id] ?? reports[item.id];
32773
+ const baseReport = error2 && existingReport ? { ...existingReport, error: error2 } : fetchedReport;
32774
+ const reportToAdd = {
32775
+ ...baseReport,
32776
+ rows: baseReport?.rows ?? [],
32777
+ columns: baseReport?.columns ?? [],
32778
+ columnInternal: baseReport?.columnInternal ?? []
32779
+ };
32534
32780
  addReport({
32535
- ...fetchedReport,
32781
+ ...reportToAdd,
32536
32782
  id: item.id,
32537
32783
  triggerReload: false,
32538
- rowCount: fetchedReport.pivot ? fetchedReport.rowCount : 0,
32784
+ rowCount: reportToAdd.pivot ? reportToAdd.rowCount : 0,
32539
32785
  filtersApplied: userFilters,
32540
32786
  loadingRows: false
32541
32787
  // rowCount 0 indicates it's still loading if row length is nonzero
32542
32788
  });
32543
32789
  setError(error2);
32790
+ if (usePivotTask) {
32791
+ const backgroundAbortController = new AbortController();
32792
+ backgroundFetch = () => {
32793
+ fetchReportRows({
32794
+ reportId: item.id,
32795
+ client,
32796
+ tenants,
32797
+ filters: filters.concat(userFilters ?? []),
32798
+ getToken,
32799
+ abortSignal: backgroundAbortController.signal,
32800
+ additionalProcessing: {
32801
+ ...processing,
32802
+ ...{ page: DEFAULT_PAGINATION }
32803
+ }
32804
+ }).then(({ rows, rowCount, columns, fields }) => {
32805
+ updateReport({
32806
+ id: item.id,
32807
+ rows,
32808
+ rowCount,
32809
+ columnInternal: columns,
32810
+ columns: columns.map((col) => ({
32811
+ field: col.field,
32812
+ format: col.format,
32813
+ label: col.label,
32814
+ inferFormat: col.inferFormat
32815
+ })),
32816
+ // @ts-ignore
32817
+ fields
32818
+ });
32819
+ }).catch((e) => {
32820
+ if (e instanceof Error && e.name === "AbortError") return;
32821
+ console.error("Failed to fetch background rows", e);
32822
+ });
32823
+ };
32824
+ }
32544
32825
  } else {
32545
32826
  try {
32546
32827
  await fetchIndividualReport({
@@ -32597,6 +32878,9 @@ function DataLoader({
32597
32878
  if (fetchRowsRequestId === rowsRequestId.current) {
32598
32879
  rowsAbortController.current = null;
32599
32880
  setLoading(false);
32881
+ if (backgroundFetch) {
32882
+ backgroundFetch();
32883
+ }
32600
32884
  }
32601
32885
  }
32602
32886
  };
@@ -32737,8 +33021,16 @@ var ChartDataLoader = ({
32737
33021
  eventTracking,
32738
33022
  usePivotTask
32739
33023
  });
33024
+ const existingReport = dashboard[item.id] ?? reports[item.id];
33025
+ const baseReport = error2 && existingReport ? { ...existingReport, error: error2 } : report;
33026
+ const reportToAdd = {
33027
+ ...baseReport,
33028
+ rows: baseReport?.rows ?? [],
33029
+ columns: baseReport?.columns ?? [],
33030
+ columnInternal: baseReport?.columnInternal ?? []
33031
+ };
32740
33032
  addReport({
32741
- ...report,
33033
+ ...reportToAdd,
32742
33034
  id: item.id,
32743
33035
  triggerReload: false,
32744
33036
  filtersApplied: userFilters,
@@ -32759,11 +33051,20 @@ var ChartDataLoader = ({
32759
33051
  ...additionalProcessing,
32760
33052
  ...{ page: DEFAULT_PAGINATION }
32761
33053
  }
32762
- }).then(({ rows, rowCount }) => {
33054
+ }).then(({ rows, rowCount, columns, fields }) => {
32763
33055
  updateReport({
32764
33056
  id: item.id,
32765
33057
  rows,
32766
- rowCount
33058
+ rowCount,
33059
+ columnInternal: columns,
33060
+ columns: columns.map((col) => ({
33061
+ field: col.field,
33062
+ format: col.format,
33063
+ label: col.label,
33064
+ inferFormat: col.inferFormat
33065
+ })),
33066
+ // @ts-ignore
33067
+ fields
32767
33068
  });
32768
33069
  }).catch((e) => {
32769
33070
  if (e instanceof Error && e.name === "AbortError") return;
@@ -41346,7 +41647,7 @@ var PivotModal = ({
41346
41647
  });
41347
41648
  }
41348
41649
  },
41349
- options: (samplePivotTable?.columns ?? []).map((column) => ({
41650
+ options: (samplePivotTable?.columns && samplePivotTable.columns.length > 0 ? samplePivotTable.columns : pivotRowField ? [{ field: pivotRowField }] : []).map((column) => ({
41350
41651
  label: snakeAndCamelCaseToTitleCase(
41351
41652
  column.field
41352
41653
  ),
@@ -41766,6 +42067,7 @@ init_Filter();
41766
42067
  init_filterProcessing();
41767
42068
  init_dateRangePickerUtils();
41768
42069
  import { Fragment as Fragment11, jsx as jsx63, jsxs as jsxs45 } from "react/jsx-runtime";
42070
+ var MULTISELECT_REQUEST_DEBOUNCE_MS = 1e3;
41769
42071
  var TogglePrimitive = ({
41770
42072
  value,
41771
42073
  onClick,
@@ -41905,6 +42207,20 @@ function InternalChart({
41905
42207
  ) : defaultOptionsV2;
41906
42208
  }, [reportDateFilter]);
41907
42209
  const [filterValues, setFilterValues] = useState27({});
42210
+ const multiselectDebounceRef = useRef16({});
42211
+ const latestMultiselectValueRef = useRef16({});
42212
+ const [lockedFilters, setLockedFilters] = useState27(
42213
+ {}
42214
+ );
42215
+ useEffect22(() => {
42216
+ return () => {
42217
+ Object.values(multiselectDebounceRef.current).forEach((timer2) => {
42218
+ if (timer2) {
42219
+ clearTimeout(timer2);
42220
+ }
42221
+ });
42222
+ };
42223
+ }, []);
41908
42224
  useEffect22(() => {
41909
42225
  if (reportDateFilter) {
41910
42226
  const customDateFilter = filters?.find(
@@ -42011,6 +42327,46 @@ function InternalChart({
42011
42327
  ...filterValues2,
42012
42328
  [filter.label]: filterValue
42013
42329
  }));
42330
+ if (filter.filterType === "string" /* String */ && filter.stringFilterType === "multiselect") {
42331
+ latestMultiselectValueRef.current[filter.label] = filterValue;
42332
+ const existingTimer = multiselectDebounceRef.current[filter.label];
42333
+ if (existingTimer) {
42334
+ clearTimeout(existingTimer);
42335
+ }
42336
+ multiselectDebounceRef.current[filter.label] = setTimeout(() => {
42337
+ multiselectDebounceRef.current[filter.label] = void 0;
42338
+ setLockedFilters((prev) => ({
42339
+ ...prev,
42340
+ [filter.label]: true
42341
+ }));
42342
+ try {
42343
+ const maybePromise = onDashboardFilterChange(
42344
+ filter.label,
42345
+ latestMultiselectValueRef.current[filter.label]
42346
+ );
42347
+ if (maybePromise && typeof maybePromise.finally === "function") {
42348
+ maybePromise.finally(() => {
42349
+ setLockedFilters((prev) => ({
42350
+ ...prev,
42351
+ [filter.label]: false
42352
+ }));
42353
+ });
42354
+ } else {
42355
+ setLockedFilters((prev) => ({
42356
+ ...prev,
42357
+ [filter.label]: false
42358
+ }));
42359
+ }
42360
+ } catch (e) {
42361
+ setLockedFilters((prev) => ({
42362
+ ...prev,
42363
+ [filter.label]: false
42364
+ }));
42365
+ throw e;
42366
+ }
42367
+ }, MULTISELECT_REQUEST_DEBOUNCE_MS);
42368
+ return;
42369
+ }
42014
42370
  onDashboardFilterChange(filter.label, filterValue);
42015
42371
  };
42016
42372
  const [filtersExpanded, setFiltersExpanded] = useState27(false);
@@ -42168,7 +42524,7 @@ function InternalChart({
42168
42524
  SelectComponent,
42169
42525
  MultiSelectComponent,
42170
42526
  DateRangePickerComponent,
42171
- disabled: !filtersEnabled,
42527
+ disabled: !filtersEnabled || lockedFilters[filter.filter.label],
42172
42528
  containerStyle: {
42173
42529
  // display: !filtersExpanded && visibleFilters[index] ? 'none' : 'inline',
42174
42530
  visibility: !filtersExpanded && visibleFilters[index] ? "hidden" : "visible"
@@ -44034,6 +44390,7 @@ function ChartBuilder({
44034
44390
  client,
44035
44391
  uniqueValues,
44036
44392
  dashboardName: destinationDashboardName,
44393
+ dashboardFilters: dashboardFilters2,
44037
44394
  tenants,
44038
44395
  additionalProcessing: baseProcessing,
44039
44396
  getToken,
@@ -44145,7 +44502,7 @@ function ChartBuilder({
44145
44502
  }
44146
44503
  return filter;
44147
44504
  });
44148
- loadFiltersForReport(
44505
+ return loadFiltersForReport(
44149
44506
  report?.id ?? TEMP_REPORT_ID,
44150
44507
  "ChartBuilder",
44151
44508
  updatedFilters,
@@ -44155,7 +44512,7 @@ function ChartBuilder({
44155
44512
  ).then(() => {
44156
44513
  setCurrentPage(0);
44157
44514
  setMaxPage(0);
44158
- handleRunQuery(baseProcessing, updatedFilters);
44515
+ return handleRunQuery(baseProcessing, updatedFilters);
44159
44516
  });
44160
44517
  };
44161
44518
  const filtersEnabledRef = useRef18(filtersEnabled);
@@ -44714,12 +45071,21 @@ function ChartBuilder({
44714
45071
  error: void 0,
44715
45072
  section: formData.section
44716
45073
  };
44717
- addReport(data);
44718
- reportsDispatch({
44719
- type: "ADD_REPORT",
44720
- id: resp.id,
44721
- data
44722
- });
45074
+ const reportFlags = data.flags;
45075
+ const hasRestrictedFlags = reportFlags && Object.values(reportFlags).some(
45076
+ (v) => Array.isArray(v) && v.length > 0
45077
+ );
45078
+ const currentTenantCanSee = !hasRestrictedFlags || flags && Object.values(reportFlags).some(
45079
+ (v) => v === "QUILL_ALL_TENANTS" || Array.isArray(v) && v.some((f) => flags.includes(f))
45080
+ );
45081
+ if (currentTenantCanSee) {
45082
+ addReport(data);
45083
+ reportsDispatch({
45084
+ type: "ADD_REPORT",
45085
+ id: resp.id,
45086
+ data
45087
+ });
45088
+ }
44723
45089
  if (onAddToDashboardComplete) {
44724
45090
  onAddToDashboardComplete(data);
44725
45091
  } else {
@@ -49141,6 +49507,14 @@ var useReportBuilderInternal = ({
49141
49507
  report,
49142
49508
  skipPivotColumnFetch
49143
49509
  }) => {
49510
+ const tablesEqual = (a, b) => {
49511
+ if (a.length !== b.length) return false;
49512
+ const aNames = a.map((t) => t.name).sort();
49513
+ const bNames = b.map((t) => t.name).sort();
49514
+ return aNames.every((name2, idx) => name2 === bNames[idx]);
49515
+ };
49516
+ const haveTablesChanged = tablesChanged ?? !tablesEqual(state.tables, tables);
49517
+ const needsFilteredUniqueValues = !!filtersChanged || !!limitChanged || haveTablesChanged;
49144
49518
  if (!client) {
49145
49519
  return;
49146
49520
  }
@@ -49148,8 +49522,8 @@ var useReportBuilderInternal = ({
49148
49522
  state,
49149
49523
  pivot: state.pivot,
49150
49524
  previousReport: report,
49151
- requiresNewFilteredUniqueValues: filtersChanged || limitChanged,
49152
- requiresNewUnfilteredUniqueValues: tablesChanged,
49525
+ requiresNewFilteredUniqueValues: needsFilteredUniqueValues,
49526
+ requiresNewUnfilteredUniqueValues: haveTablesChanged,
49153
49527
  skipPivotColumnFetch
49154
49528
  });
49155
49529
  };
@@ -49760,18 +50134,10 @@ var useReportBuilderInternal = ({
49760
50134
  }, [client]);
49761
50135
  useEffect26(() => {
49762
50136
  const loadChart = async () => {
49763
- let report;
49764
- if (!client) {
49765
- return;
49766
- }
50137
+ if (!client || !reportId) return;
50138
+ const report = allReportsById[reportId];
50139
+ if (!report) return;
49767
50140
  try {
49768
- if (!reportId) {
49769
- throw new Error("Report ID is required");
49770
- }
49771
- report = allReportsById[reportId];
49772
- if (!report) {
49773
- throw new Error("Report not found");
49774
- }
49775
50141
  const { ast: newAst, pivot: newPivot } = await fetchASTFromQuillReport(
49776
50142
  report,
49777
50143
  client,
@@ -53096,15 +53462,20 @@ function ChartEditor({
53096
53462
  const parentRef = useRef22(null);
53097
53463
  const [modalWidth, setModalWidth] = useState38(200);
53098
53464
  const [modalHeight, setModalHeight] = useState38(200);
53099
- const { addReport } = useDashboardReports(destinationDashboard);
53100
53465
  const { allReportsById } = useAllReports();
53466
+ const report = allReportsById[reportId];
53467
+ const resolvedDashboard = useMemo26(
53468
+ () => destinationDashboard ?? report?.dashboardName ?? null,
53469
+ [destinationDashboard, report?.dashboardName]
53470
+ );
53471
+ const { addReport } = useDashboardReports(resolvedDashboard ?? void 0);
53101
53472
  const { tenants, flags } = useContext33(TenantContext);
53102
53473
  const { getToken } = useContext33(FetchContext);
53103
- const report = allReportsById[reportId];
53104
53474
  const [client, isClientLoading] = useContext33(ClientContext);
53105
53475
  const [schemaData] = useContext33(SchemaDataContext);
53106
53476
  const { dashboardFilters } = useContext33(DashboardFiltersContext);
53107
53477
  const { eventTracking } = useContext33(EventTrackingContext);
53478
+ const { reload } = useDashboardInternal(resolvedDashboard);
53108
53479
  const specificDashboardFilters = useMemo26(() => {
53109
53480
  if (!report) {
53110
53481
  return [];
@@ -53112,7 +53483,7 @@ function ChartEditor({
53112
53483
  return Object.values(dashboardFilters[report.dashboardName] || {}).map(
53113
53484
  (f) => f.filter
53114
53485
  );
53115
- }, [dashboardFilters]);
53486
+ }, [dashboardFilters, report?.dashboardName]);
53116
53487
  const [filtersEnabled, setFiltersEnabled] = useState38(true);
53117
53488
  const [chartBuilderKey, setChartBuilderKey] = useState38(0);
53118
53489
  const dateFilter = Object.values(specificDashboardFilters).find(
@@ -53138,7 +53509,7 @@ function ChartEditor({
53138
53509
  };
53139
53510
  }, []);
53140
53511
  const fetchReportHelper = async (processing) => {
53141
- if (!client) {
53512
+ if (!client || !reportId) {
53142
53513
  return;
53143
53514
  }
53144
53515
  const minimalFilters = Object.values(specificDashboardFilters).length ? Object.values(specificDashboardFilters).map((filter) => {
@@ -53170,10 +53541,13 @@ function ChartEditor({
53170
53541
  addReport(report2);
53171
53542
  };
53172
53543
  useEffect30(() => {
53544
+ if (!isOpen || !reportId) {
53545
+ return;
53546
+ }
53173
53547
  if (!isClientLoading && !report) {
53174
53548
  fetchReportHelper();
53175
53549
  }
53176
- }, [reportId, isClientLoading, allReportsById]);
53550
+ }, [reportId, isClientLoading, allReportsById, isOpen]);
53177
53551
  return /* @__PURE__ */ jsx82("div", { ref: parentRef, style: { height: "100%" }, children: /* @__PURE__ */ jsx82(
53178
53552
  ModalComponent,
53179
53553
  {
@@ -53187,7 +53561,7 @@ function ChartEditor({
53187
53561
  title: chartBuilderTitle || "Add to dashboard",
53188
53562
  width: isHorizontalView ? modalWidth : void 0,
53189
53563
  height: isHorizontalView ? modalHeight : void 0,
53190
- children: allReportsById[reportId] ? /* @__PURE__ */ jsx82(
53564
+ children: reportId && allReportsById[reportId] ? /* @__PURE__ */ jsx82(
53191
53565
  ChartBuilder,
53192
53566
  {
53193
53567
  reportId,
@@ -53202,8 +53576,15 @@ function ChartEditor({
53202
53576
  } else if (onAddToDashboardComplete) {
53203
53577
  onAddToDashboardComplete(data);
53204
53578
  }
53579
+ const targetDashboard = data?.dashboardName ?? resolvedDashboard;
53580
+ if (targetDashboard) {
53581
+ reload(targetDashboard, true, {
53582
+ report: data,
53583
+ action: "upsert"
53584
+ });
53585
+ }
53205
53586
  },
53206
- destinationDashboard,
53587
+ destinationDashboard: resolvedDashboard ?? void 0,
53207
53588
  destinationSection,
53208
53589
  dateRange,
53209
53590
  SelectComponent,