@quillsql/react 2.16.36 → 2.16.37

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
@@ -18858,6 +18858,21 @@ var init_tableProcessing = __esm({
18858
18858
  }
18859
18859
  });
18860
18860
 
18861
+ // src/utils/changelogNotify.ts
18862
+ function setChangelogHandler(handler) {
18863
+ changelogHandler = handler;
18864
+ }
18865
+ function notifyChangelogs(entries) {
18866
+ changelogHandler?.(entries);
18867
+ }
18868
+ var changelogHandler;
18869
+ var init_changelogNotify = __esm({
18870
+ "src/utils/changelogNotify.ts"() {
18871
+ "use strict";
18872
+ changelogHandler = null;
18873
+ }
18874
+ });
18875
+
18861
18876
  // src/utils/dataFetcher.tsx
18862
18877
  var dataFetcher_exports = {};
18863
18878
  __export(dataFetcher_exports, {
@@ -18871,6 +18886,15 @@ __export(dataFetcher_exports, {
18871
18886
  quillFetch: () => quillFetch,
18872
18887
  quillStream: () => quillStream
18873
18888
  });
18889
+ function normalizeChangelogData(data) {
18890
+ if (!data) return data;
18891
+ if (Array.isArray(data.changelogs)) return data;
18892
+ if (!Array.isArray(data.changeLogs)) return data;
18893
+ return {
18894
+ ...data,
18895
+ changelogs: data.changeLogs
18896
+ };
18897
+ }
18874
18898
  function fetchQuillData(responseData) {
18875
18899
  if (!responseData) {
18876
18900
  return null;
@@ -19391,6 +19415,7 @@ var init_dataFetcher = __esm({
19391
19415
  init_reportBuilder();
19392
19416
  init_tableProcessing();
19393
19417
  init_dates();
19418
+ init_changelogNotify();
19394
19419
  quillFetch = async ({
19395
19420
  client,
19396
19421
  task,
@@ -19429,8 +19454,12 @@ var init_dataFetcher = __esm({
19429
19454
  if (result.data?.data && (result.data.queries || result.data.status || result.data.error)) {
19430
19455
  result = result.data;
19431
19456
  }
19457
+ const normalizedData = normalizeChangelogData(result.data);
19458
+ if (task !== "fetch-changelog-list" && Array.isArray(normalizedData?.changelogs)) {
19459
+ notifyChangelogs(normalizedData.changelogs);
19460
+ }
19432
19461
  return {
19433
- data: result.data,
19462
+ data: normalizedData,
19434
19463
  queries: result.queries,
19435
19464
  status: result.status,
19436
19465
  error: result.error
@@ -23803,6 +23832,7 @@ function normalizePSTRanges(start, end) {
23803
23832
  }
23804
23833
 
23805
23834
  // src/Context.tsx
23835
+ init_changelogNotify();
23806
23836
  import { jsx } from "react/jsx-runtime";
23807
23837
  var dummySetter = () => {
23808
23838
  };
@@ -24241,7 +24271,8 @@ var ContextProvider = ({
24241
24271
  flags,
24242
24272
  isAdmin,
24243
24273
  getAuthorizationToken = async () => "",
24244
- eventTracking = null
24274
+ eventTracking = null,
24275
+ onChangelogs
24245
24276
  }) => {
24246
24277
  const cacheCabByTypeRef = useRef({});
24247
24278
  const getCacheCab = useCallback((storageType) => {
@@ -24251,6 +24282,10 @@ var ContextProvider = ({
24251
24282
  }
24252
24283
  return cacheCabByTypeRef.current[key];
24253
24284
  }, []);
24285
+ useEffect(() => {
24286
+ setChangelogHandler(onChangelogs ?? null);
24287
+ return () => setChangelogHandler(null);
24288
+ }, [onChangelogs]);
24254
24289
  const [client, setClient] = useState(
24255
24290
  typeof window !== "undefined" && sessionStorage ? JSON.parse(sessionStorage.getItem("quill-client") ?? "null") : null
24256
24291
  );
@@ -24308,8 +24343,7 @@ var ContextProvider = ({
24308
24343
  customReportFiltersReducer,
24309
24344
  {}
24310
24345
  );
24311
- const filterOptionsAbortControllers = useRef(/* @__PURE__ */ new Set());
24312
- const loadingFiltersForDashboard = useRef(/* @__PURE__ */ new Set());
24346
+ const dashboardFilterLoadState = useRef({});
24313
24347
  const backfilledDashboards = useRef(/* @__PURE__ */ new Set());
24314
24348
  const [reportFilters, reportFiltersDispatch] = useReducer(
24315
24349
  reportFiltersReducer,
@@ -24675,14 +24709,15 @@ var ContextProvider = ({
24675
24709
  }
24676
24710
  }
24677
24711
  async function loadFiltersForDashboard(dashboardName, filters, updatedFilterLabel, customFilters) {
24678
- if (loadingFiltersForDashboard.current.has(dashboardName)) {
24679
- return;
24680
- }
24681
- loadingFiltersForDashboard.current.add(dashboardName);
24712
+ const previousLoad = dashboardFilterLoadState.current[dashboardName];
24713
+ previousLoad?.controllers.forEach((controller) => controller.abort());
24714
+ const nextRequestId = (previousLoad?.requestId ?? 0) + 1;
24715
+ dashboardFilterLoadState.current[dashboardName] = {
24716
+ requestId: nextRequestId,
24717
+ controllers: /* @__PURE__ */ new Set()
24718
+ };
24719
+ const shouldApply = () => dashboardFilterLoadState.current[dashboardName]?.requestId === nextRequestId;
24682
24720
  try {
24683
- filterOptionsAbortControllers.current.forEach(
24684
- (controller) => controller.abort()
24685
- );
24686
24721
  dashboardFiltersDispatch({
24687
24722
  type: "ADD_DASHBOARD_FILTERS",
24688
24723
  dashboardName,
@@ -24696,6 +24731,9 @@ var ContextProvider = ({
24696
24731
  });
24697
24732
  await Promise.allSettled(
24698
24733
  filters.map(async (filter) => {
24734
+ if (!shouldApply()) {
24735
+ return null;
24736
+ }
24699
24737
  if (filter.filterType === "date_range") {
24700
24738
  dashboardFiltersDispatch({
24701
24739
  type: "UPDATE_DASHBOARD_FILTER",
@@ -24721,11 +24759,11 @@ var ContextProvider = ({
24721
24759
  return null;
24722
24760
  }
24723
24761
  if (filter.filterType === "tenant") {
24724
- await fetchTenantFilterOptions(dashboardName, filter);
24762
+ await fetchTenantFilterOptions(dashboardName, filter, shouldApply);
24725
24763
  return null;
24726
24764
  }
24727
24765
  const filterOptionsAbortController = new AbortController();
24728
- filterOptionsAbortControllers.current.add(
24766
+ dashboardFilterLoadState.current[dashboardName]?.controllers.add(
24729
24767
  filterOptionsAbortController
24730
24768
  );
24731
24769
  try {
@@ -24759,33 +24797,36 @@ var ContextProvider = ({
24759
24797
  getToken: getAuthorizationToken
24760
24798
  });
24761
24799
  const filterOptions = result.data?.filters[0]?.options ?? [];
24762
- dashboardFiltersDispatch({
24763
- type: "UPDATE_DASHBOARD_FILTER",
24764
- dashboardName,
24765
- filterName: filter.label,
24766
- data: {
24767
- filter: {
24768
- ...filter,
24769
- options: filterOptions
24770
- },
24771
- loading: false
24772
- }
24773
- });
24774
- return null;
24775
- } catch (error) {
24776
- if (error instanceof Error && error.name === "AbortError") {
24800
+ if (shouldApply() && !filterOptionsAbortController.signal.aborted) {
24777
24801
  dashboardFiltersDispatch({
24778
24802
  type: "UPDATE_DASHBOARD_FILTER",
24779
24803
  dashboardName,
24780
24804
  filterName: filter.label,
24781
24805
  data: {
24782
- filter,
24806
+ filter: {
24807
+ ...filter,
24808
+ options: filterOptions
24809
+ },
24783
24810
  loading: false
24784
24811
  }
24785
24812
  });
24813
+ }
24814
+ return null;
24815
+ } catch (error) {
24816
+ if (error instanceof Error && error.name === "AbortError") {
24817
+ if (shouldApply()) {
24818
+ dashboardFiltersDispatch({
24819
+ type: "UPDATE_DASHBOARD_FILTER",
24820
+ dashboardName,
24821
+ filterName: filter.label,
24822
+ data: {
24823
+ filter,
24824
+ loading: false
24825
+ }
24826
+ });
24827
+ }
24786
24828
  return;
24787
24829
  }
24788
- console.error("ERROR:", error);
24789
24830
  eventTracking?.logError?.({
24790
24831
  type: "bug",
24791
24832
  // TODO: determine type
@@ -24799,14 +24840,13 @@ var ContextProvider = ({
24799
24840
  }
24800
24841
  });
24801
24842
  } finally {
24802
- filterOptionsAbortControllers.current.delete(
24843
+ dashboardFilterLoadState.current[dashboardName]?.controllers.delete(
24803
24844
  filterOptionsAbortController
24804
24845
  );
24805
24846
  }
24806
24847
  })
24807
24848
  );
24808
24849
  } finally {
24809
- loadingFiltersForDashboard.current.delete(dashboardName);
24810
24850
  }
24811
24851
  }
24812
24852
  async function loadDashboard(dashboardName, fetchFromServer = false, reportAction) {
@@ -25434,8 +25474,11 @@ var ContextProvider = ({
25434
25474
  },
25435
25475
  [populatedClient, viewerTenantsByOwner]
25436
25476
  );
25437
- const fetchTenantFilterOptions = async (dashboardName, filter) => {
25477
+ const fetchTenantFilterOptions = async (dashboardName, filter, shouldApply) => {
25438
25478
  const mappings = await getMappedTenantsForDashboard(dashboardName);
25479
+ if (!shouldApply()) {
25480
+ return;
25481
+ }
25439
25482
  const options = mappings?.[filter.field] ?? [];
25440
25483
  dashboardFiltersDispatch({
25441
25484
  type: "UPDATE_DASHBOARD_FILTER",
@@ -26205,6 +26248,40 @@ var useAllReports = () => {
26205
26248
  allReportsById
26206
26249
  };
26207
26250
  };
26251
+ function hydrateDateFilter(raw) {
26252
+ if (!raw) return void 0;
26253
+ return {
26254
+ ...raw,
26255
+ presetOptions: raw.presetOptions?.map(
26256
+ (p) => ({
26257
+ ...p,
26258
+ loopStart: p.loopStart ? new Date(p.loopStart) : void 0,
26259
+ loopEnd: p.loopEnd ? new Date(p.loopEnd) : void 0
26260
+ })
26261
+ ),
26262
+ defaultPresetRanges: raw.defaultPresetRanges?.map(
26263
+ (p) => ({
26264
+ ...p,
26265
+ loopStart: p.loopStart ? new Date(p.loopStart) : void 0,
26266
+ loopEnd: p.loopEnd ? new Date(p.loopEnd) : void 0,
26267
+ customLabel: p.customLabel
26268
+ })
26269
+ )
26270
+ };
26271
+ }
26272
+ function getTaskResponseError(result) {
26273
+ const status = result.status ?? result.data?.status;
26274
+ const message = result.error ?? result.data?.error;
26275
+ if (status === "error") {
26276
+ return message ?? "Request failed";
26277
+ }
26278
+ if (message) {
26279
+ if (!result.data?.dashboard) {
26280
+ return message;
26281
+ }
26282
+ }
26283
+ return void 0;
26284
+ }
26208
26285
  var useDashboards = () => {
26209
26286
  const [dashboardReports, dashboardDispatch] = useContext(DashboardContext);
26210
26287
  const {
@@ -26215,7 +26292,8 @@ var useDashboards = () => {
26215
26292
  const {
26216
26293
  dashboardFilters,
26217
26294
  loadFiltersForDashboard,
26218
- dispatch: dashboardFiltersDispatch
26295
+ dispatch: dashboardFiltersDispatch,
26296
+ customFilterDispatch
26219
26297
  } = useContext(DashboardFiltersContext);
26220
26298
  const { reportsDispatch } = useContext(ReportsContext);
26221
26299
  const { reportFiltersDispatch } = useContext(ReportFiltersContext);
@@ -26242,7 +26320,8 @@ var useDashboards = () => {
26242
26320
  tenantFilters,
26243
26321
  filters,
26244
26322
  dateFilter,
26245
- dashboardOwners
26323
+ dashboardOwners,
26324
+ clientId
26246
26325
  }) => {
26247
26326
  if (!client) return;
26248
26327
  if (dashboardOwners?.some((key) => !key)) {
@@ -26270,7 +26349,7 @@ var useDashboards = () => {
26270
26349
  dateFilter,
26271
26350
  name: name2.trim(),
26272
26351
  task: "edit-dashboard",
26273
- clientId: client.clientId,
26352
+ clientId: clientId ?? client.clientId,
26274
26353
  tenantKeys: dashboardOwners
26275
26354
  };
26276
26355
  try {
@@ -26279,6 +26358,10 @@ var useDashboards = () => {
26279
26358
  task: "edit-dashboard",
26280
26359
  metadata: body
26281
26360
  });
26361
+ const updatedDashboard = updated.data.dashboard;
26362
+ if (!updatedDashboard) {
26363
+ throw new Error("Missing dashboard in edit-dashboard response");
26364
+ }
26282
26365
  eventTracking?.logEvent?.("create-dashboard", {
26283
26366
  dashboardName: name2
26284
26367
  });
@@ -26293,8 +26376,8 @@ var useDashboards = () => {
26293
26376
  id: name2,
26294
26377
  data: {
26295
26378
  config: {
26296
- ...updated.data.dashboard,
26297
- createdAt: new Date(updated.data.dashboard.createdAt)
26379
+ ...updatedDashboard,
26380
+ createdAt: new Date(updatedDashboard.createdAt)
26298
26381
  },
26299
26382
  loading: false
26300
26383
  }
@@ -26322,22 +26405,17 @@ var useDashboards = () => {
26322
26405
  dateFilter,
26323
26406
  customFilters,
26324
26407
  tenantKeys,
26325
- initialCacheDateRange
26408
+ initialCacheDateRange,
26409
+ clientId
26326
26410
  }) => {
26327
- if (!client) return;
26411
+ if (!client) {
26412
+ throw new Error("Client not loaded");
26413
+ }
26328
26414
  if (tenantKeys?.some((key) => !key)) {
26329
26415
  throw new Error("Tenant keys cannot be empty or undefined");
26330
26416
  }
26331
26417
  const dashboard = dashboardConfig[name2]?.config;
26332
- dashboardConfigDispatch({
26333
- type: "DELETE_DASHBOARD",
26334
- id: name2
26335
- });
26336
26418
  const oldFilters = dashboardFilters[name2];
26337
- dashboardFiltersDispatch({
26338
- type: "DELETE_DASHBOARD_FILTERS",
26339
- dashboardName: name2
26340
- });
26341
26419
  const body = {
26342
26420
  newDashboardName: newName.trim(),
26343
26421
  filters,
@@ -26346,7 +26424,7 @@ var useDashboards = () => {
26346
26424
  initialCacheDateRange,
26347
26425
  name: name2.trim(),
26348
26426
  task: "edit-dashboard",
26349
- clientId: client.clientId,
26427
+ clientId: clientId ?? client.clientId,
26350
26428
  tenantKeys
26351
26429
  };
26352
26430
  try {
@@ -26355,9 +26433,23 @@ var useDashboards = () => {
26355
26433
  task: "edit-dashboard",
26356
26434
  metadata: body
26357
26435
  });
26436
+ const taskError = getTaskResponseError(updated);
26437
+ if (taskError) {
26438
+ throw new Error(taskError);
26439
+ }
26440
+ const updatedDashboard = updated?.data?.dashboard ?? updated?.metadata?.dashboard ?? updated?.data?.metadata?.dashboard;
26441
+ if (!updatedDashboard) {
26442
+ throw new Error("Missing dashboard in edit-dashboard response");
26443
+ }
26444
+ if (name2 !== updatedDashboard.name) {
26445
+ dashboardConfigDispatch({
26446
+ type: "DELETE_DASHBOARD",
26447
+ id: name2
26448
+ });
26449
+ }
26358
26450
  eventTracking?.logEvent?.("update-dashboard", {
26359
- dashboardName: updated.data.dashboard.name,
26360
- dashboardId: updated.data.dashboard.dashboardId
26451
+ dashboardName: updatedDashboard.name,
26452
+ dashboardId: updatedDashboard.dashboardId
26361
26453
  });
26362
26454
  if (filters.length > 0 || dateFilter) {
26363
26455
  eventTracking?.logEvent?.("update-dashboard-filters", {
@@ -26367,36 +26459,19 @@ var useDashboards = () => {
26367
26459
  }
26368
26460
  dashboardConfigDispatch({
26369
26461
  type: "UPDATE_DASHBOARD",
26370
- id: updated.data.dashboard.name,
26462
+ id: updatedDashboard.name,
26371
26463
  data: {
26372
26464
  config: {
26373
26465
  ...dashboard,
26374
- ...updated.data.dashboard,
26466
+ ...updatedDashboard,
26375
26467
  allTenantFilters: tenantFilters ?? [],
26376
- dateFilter: updated.data.dashboard.dateFilter ? {
26377
- ...updated.data.dashboard.dateFilter,
26378
- presetOptions: updated.data.dashboard.dateFilter.presetOptions?.map(
26379
- (preset) => ({
26380
- ...preset,
26381
- loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
26382
- loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0
26383
- })
26384
- ),
26385
- defaultPresetRanges: updated.data.dashboard.dateFilter.defaultPresetRanges?.map(
26386
- (preset) => ({
26387
- ...preset,
26388
- loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
26389
- loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0,
26390
- customLabel: preset.customLabel
26391
- })
26392
- )
26393
- } : void 0,
26394
- createdAt: new Date(updated.data.dashboard.createdAt)
26468
+ dateFilter: hydrateDateFilter(updatedDashboard.dateFilter),
26469
+ createdAt: new Date(updatedDashboard.createdAt)
26395
26470
  },
26396
26471
  loading: false
26397
26472
  }
26398
26473
  });
26399
- Object.values(updated.data.dashboard.sections ?? {}).flat().forEach((report) => {
26474
+ Object.values(updatedDashboard.sections ?? {}).flat().forEach((report) => {
26400
26475
  dashboardDispatch({
26401
26476
  type: "ADD_DASHBOARD_ITEM",
26402
26477
  id: report._id,
@@ -26422,42 +26497,28 @@ var useDashboards = () => {
26422
26497
  id: report._id
26423
26498
  });
26424
26499
  });
26425
- if (dashboardFilters[name2])
26500
+ if (dashboardFilters[name2] && name2 !== newName)
26426
26501
  dashboardFiltersDispatch({
26427
26502
  type: "ADD_DASHBOARD_FILTERS",
26428
26503
  dashboardName: newName,
26429
26504
  data: dashboardFilters[name2]
26430
26505
  });
26506
+ const dateFilterSource = updatedDashboard.dateFilter ?? dateFilter;
26431
26507
  const range = convertPresetOptionsToSelectableList(
26432
- updated.data.dashboard.dateFilter?.presetOptions ?? [],
26433
- updated.data.dashboard.dateFilter?.defaultPresetRanges ?? []
26508
+ dateFilterSource?.presetOptions ?? [],
26509
+ dateFilterSource?.defaultPresetRanges ?? []
26434
26510
  ).find(
26435
- (option) => option.value === updated.data.dashboard.dateFilter?.primaryRange?.value
26436
- ) ?? PRIMARY_RANGE[updated.data.dashboard.dateFilter?.primaryRange?.value ?? "LAST_30_DAYS"] ?? PRIMARY_RANGE["LAST_30_DAYS"];
26437
- const updatedDateFilter = updated.data.dashboard.dateFilter ? {
26438
- ...updated.data.dashboard.dateFilter,
26439
- presetOptions: updated.data.dashboard.dateFilter.presetOptions?.map(
26440
- (preset) => ({
26441
- ...preset,
26442
- loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
26443
- loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0
26444
- })
26445
- ),
26446
- defaultPresetRanges: updated.data.dashboard.dateFilter.defaultPresetRanges?.map(
26447
- (preset) => ({
26448
- ...preset,
26449
- loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
26450
- loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0,
26451
- customLabel: preset.customLabel
26452
- })
26453
- ),
26454
- dashboardName: updated.data.dashboard.name,
26455
- preset: updated.data.dashboard.dateFilter.primaryRange,
26511
+ (option) => option.value === dateFilterSource?.primaryRange?.value
26512
+ ) ?? PRIMARY_RANGE[dateFilterSource?.primaryRange?.value ?? "LAST_30_DAYS"] ?? PRIMARY_RANGE["LAST_30_DAYS"];
26513
+ const updatedDateFilter = dateFilterSource ? {
26514
+ ...hydrateDateFilter(dateFilterSource),
26515
+ dashboardName: updatedDashboard.name,
26516
+ preset: dateFilterSource.primaryRange,
26456
26517
  filterType: "date_range" /* Date */,
26457
26518
  dateField: [
26458
26519
  ...new Map(
26459
26520
  Object.values(
26460
- dashboardConfig[updated.data.dashboard.name]?.config.sections ?? {}
26521
+ dashboardConfig[updatedDashboard.name]?.config.sections ?? {}
26461
26522
  ).flat().map((report) => {
26462
26523
  const key = JSON.stringify(report.dateField);
26463
26524
  return [key, report.dateField];
@@ -26469,11 +26530,13 @@ var useDashboards = () => {
26469
26530
  endDate: !range.endDate || range.endDate instanceof Date ? range.endDate : new Date(range.endDate)
26470
26531
  // when range.endDate is a string
26471
26532
  } : void 0;
26472
- const mappedTenants = await getMappedTenantsForDashboard(newName);
26533
+ const mappedTenants = await getMappedTenantsForDashboard(newName).catch(
26534
+ () => void 0
26535
+ );
26473
26536
  const mappedTenantKeys = Object.keys(mappedTenants ?? {});
26474
26537
  const newFilters = [
26475
26538
  ...updatedDateFilter ? [updatedDateFilter] : [],
26476
- ...updated.data.dashboard.filters.map(
26539
+ ...(updatedDashboard.filters ?? []).map(
26477
26540
  (f) => ({
26478
26541
  ...f,
26479
26542
  selectedValue: oldFilters?.[f.label]?.filter?.selectedValue,
@@ -26481,7 +26544,7 @@ var useDashboards = () => {
26481
26544
  operator: oldFilters?.[f.label]?.filter?.operator
26482
26545
  })
26483
26546
  ) ?? [],
26484
- ...(updated.data.dashboard.tenantFilters?.map(
26547
+ ...(updatedDashboard.tenantFilters?.map(
26485
26548
  (f) => ({
26486
26549
  ...f,
26487
26550
  values: oldFilters?.[f.label]?.filter?.values
@@ -26504,16 +26567,18 @@ var useDashboards = () => {
26504
26567
  };
26505
26568
  }
26506
26569
  });
26507
- dashboardFiltersDispatch({
26508
- type: "DELETE_DASHBOARD_FILTERS",
26509
- dashboardName: name2
26510
- });
26511
- loadFiltersForDashboard(
26512
- updated.data.dashboard.name,
26570
+ await loadFiltersForDashboard(
26571
+ updatedDashboard.name,
26513
26572
  newFilters,
26514
26573
  void 0,
26515
26574
  customFilters
26516
26575
  );
26576
+ if (name2 !== updatedDashboard.name) {
26577
+ dashboardFiltersDispatch({
26578
+ type: "DELETE_DASHBOARD_FILTERS",
26579
+ dashboardName: name2
26580
+ });
26581
+ }
26517
26582
  } catch (e) {
26518
26583
  console.error(e);
26519
26584
  eventTracking?.logError?.({
@@ -26528,6 +26593,7 @@ var useDashboards = () => {
26528
26593
  function: "updateDashboard"
26529
26594
  }
26530
26595
  });
26596
+ throw e;
26531
26597
  }
26532
26598
  };
26533
26599
  const deleteDashboard = async (name2) => {
@@ -26545,6 +26611,14 @@ var useDashboards = () => {
26545
26611
  type: "DELETE_DASHBOARD",
26546
26612
  id: name2
26547
26613
  });
26614
+ dashboardFiltersDispatch({
26615
+ type: "DELETE_DASHBOARD_FILTERS",
26616
+ dashboardName: name2
26617
+ });
26618
+ customFilterDispatch({
26619
+ type: "DELETE_CUSTOM_DASHBOARD_FILTERS",
26620
+ dashboardName: name2
26621
+ });
26548
26622
  };
26549
26623
  return {
26550
26624
  dashboards: isLoading || isDashboardsLoading ? null : dashboards,
@@ -26772,7 +26846,7 @@ var useDashboard = (dashboardName, config) => {
26772
26846
  const fetchStartTime = Date.now();
26773
26847
  let totalCached = 0;
26774
26848
  await Promise.all(
26775
- allReports.map(async (reportInfo, idx) => {
26849
+ allReports.map(async (reportInfo) => {
26776
26850
  const reportId = reportInfo.id;
26777
26851
  const requestId = (reportRequestIds.current[reportId] ?? 0) + 1;
26778
26852
  reportRequestIds.current[reportId] = requestId;
@@ -26819,7 +26893,19 @@ var useDashboard = (dashboardName, config) => {
26819
26893
  };
26820
26894
  };
26821
26895
  if (cacheEnabled && cacheCab.isCacheable(reportId)) {
26822
- const report2 = await cacheCab.get(reportId, dashboardFilters2, customFilters.concat(customReportFiltersArray), reportInfo.pivot, client, tenants, flags, pageSize, getToken, eventTracking, forceCacheToRefresh);
26896
+ const report2 = await cacheCab.get(
26897
+ reportId,
26898
+ dashboardFilters2,
26899
+ customFilters.concat(customReportFiltersArray),
26900
+ reportInfo.pivot,
26901
+ client,
26902
+ tenants,
26903
+ flags,
26904
+ pageSize,
26905
+ getToken,
26906
+ eventTracking,
26907
+ forceCacheToRefresh
26908
+ );
26823
26909
  if (reportRequestIds.current[reportId] !== requestId) {
26824
26910
  return null;
26825
26911
  }
@@ -27032,11 +27118,15 @@ var useDashboard = (dashboardName, config) => {
27032
27118
  })
27033
27119
  );
27034
27120
  if (!loadedDashes.includes(dashboardName) || !cacheEnabled || forceCacheToRefresh) {
27035
- setLoadedDashes((prev) => prev.includes(dashboardName) ? prev : [...prev, dashboardName]);
27121
+ setLoadedDashes(
27122
+ (prev) => prev.includes(dashboardName) ? prev : [...prev, dashboardName]
27123
+ );
27036
27124
  setLastUpdatedDict((prev) => ({ ...prev, [dashboardName]: Date.now() }));
27037
27125
  }
27038
27126
  if (logCacheStatistics) {
27039
- console.log(`Dashboard "${dashboardName}": Cache Rate: ${(100 * totalCached / allReports.length).toFixed(1)}%, load time: ${((Date.now() - fetchStartTime) / 1e3).toFixed(2)} secs`);
27127
+ console.log(
27128
+ `Dashboard "${dashboardName}": Cache Rate: ${(100 * totalCached / allReports.length).toFixed(1)}%, load time: ${((Date.now() - fetchStartTime) / 1e3).toFixed(2)} secs`
27129
+ );
27040
27130
  }
27041
27131
  };
27042
27132
  return {
@@ -42351,7 +42441,8 @@ var getThemedStyles = (theme) => ({
42351
42441
  function Dashboard({
42352
42442
  name: name2,
42353
42443
  onClickReport,
42354
- containerStyle
42444
+ containerStyle,
42445
+ EmptyDashboardComponent
42355
42446
  }) {
42356
42447
  const [themeFromContext] = useContext22(ThemeContext);
42357
42448
  const theme = useMemo19(
@@ -42534,7 +42625,8 @@ function Dashboard({
42534
42625
  sections,
42535
42626
  sectionOrder,
42536
42627
  onClickReport,
42537
- styles: themedStyles
42628
+ styles: themedStyles,
42629
+ EmptyDashboardComponent
42538
42630
  }
42539
42631
  )
42540
42632
  ] });
@@ -42542,7 +42634,8 @@ function Dashboard({
42542
42634
  function DashboardContent({
42543
42635
  sections,
42544
42636
  sectionOrder,
42545
- onClickReport
42637
+ onClickReport,
42638
+ EmptyDashboardComponent
42546
42639
  }) {
42547
42640
  const getSection = (name2) => {
42548
42641
  if (!sections) {
@@ -42603,6 +42696,11 @@ function DashboardContent({
42603
42696
  return aIndex - bIndex;
42604
42697
  });
42605
42698
  }, [sections, sectionOrder]);
42699
+ if (sections && (Object.keys(sections).length === 0 || Object.values(sections).flat().length === 0)) {
42700
+ if (EmptyDashboardComponent) {
42701
+ return /* @__PURE__ */ jsx60(EmptyDashboardComponent, {});
42702
+ }
42703
+ }
42606
42704
  return /* @__PURE__ */ jsxs43("div", { style: styles.contentWrap, children: [
42607
42705
  metricReports.length === 0 ? null : /* @__PURE__ */ jsx60("div", { style: styles.splitGrid, children: /* @__PURE__ */ jsx60("section", { children: metricReports.map((report) => /* @__PURE__ */ jsxs43(
42608
42706
  "div",
@@ -42721,7 +42819,8 @@ var QuillProvider = ({
42721
42819
  withCredentials,
42722
42820
  isAdmin,
42723
42821
  getAuthorizationToken,
42724
- eventTracking
42822
+ eventTracking,
42823
+ onChangelogs
42725
42824
  }) => {
42726
42825
  if (queryEndpoint === QUILL_SERVER + QUILL_QUERY_ENDPOINT && !tenants) {
42727
42826
  throw new Error("Tenants are required when using the quill cloud endpoint");
@@ -42740,6 +42839,7 @@ var QuillProvider = ({
42740
42839
  isAdmin,
42741
42840
  getAuthorizationToken,
42742
42841
  eventTracking,
42842
+ onChangelogs,
42743
42843
  children
42744
42844
  }
42745
42845
  );
@@ -42922,7 +43022,7 @@ import {
42922
43022
  useEffect as useEffect25,
42923
43023
  useRef as useRef20,
42924
43024
  useMemo as useMemo25,
42925
- useCallback as useCallback5
43025
+ useCallback as useCallback4
42926
43026
  } from "react";
42927
43027
  import MonacoEditor from "@monaco-editor/react";
42928
43028
 
@@ -42933,7 +43033,7 @@ import {
42933
43033
  useState as useState31,
42934
43034
  useContext as useContext28,
42935
43035
  useMemo as useMemo24,
42936
- useCallback as useCallback4
43036
+ useCallback as useCallback3
42937
43037
  } from "react";
42938
43038
  import {
42939
43039
  closestCenter,
@@ -42954,7 +43054,7 @@ import { CSS as DND_CSS } from "@dnd-kit/utilities";
42954
43054
 
42955
43055
  // src/internals/ReportBuilder/PivotModal.tsx
42956
43056
  import {
42957
- useCallback as useCallback3,
43057
+ useCallback as useCallback2,
42958
43058
  useContext as useContext25,
42959
43059
  useMemo as useMemo21,
42960
43060
  useState as useState28,
@@ -43837,7 +43937,7 @@ var PivotModal = ({
43837
43937
  setIsOpen(false);
43838
43938
  setPopUpTitle("Add pivot");
43839
43939
  };
43840
- const onCommitPivot = useCallback3(() => {
43940
+ const onCommitPivot = useCallback2(() => {
43841
43941
  const errors2 = [];
43842
43942
  if ((pivotAggregations?.length ?? 0) === 0) {
43843
43943
  errors2.push("You must have at least one aggregation");
@@ -43979,7 +44079,7 @@ var PivotModal = ({
43979
44079
  const onEditRecommendedPivot = (pivot) => {
43980
44080
  onEditPivot(pivot, null);
43981
44081
  };
43982
- const refreshPivots = useCallback3(async () => {
44082
+ const refreshPivots = useCallback2(async () => {
43983
44083
  if (!client) {
43984
44084
  return;
43985
44085
  }
@@ -47496,7 +47596,7 @@ function ChartBuilder({
47496
47596
  ) ?? {};
47497
47597
  }, [client?.allTenantTypes]);
47498
47598
  const [selectedPivotTable, setSelectedPivotTable] = useState31(pivotData);
47499
- const getDefaultXAxisFormat = useCallback4(
47599
+ const getDefaultXAxisFormat = useCallback3(
47500
47600
  (form) => {
47501
47601
  if (form.pivot?.rowField) {
47502
47602
  if (isDateField(form.pivot.rowFieldType ?? "")) {
@@ -49734,7 +49834,8 @@ function ChartBuilder({
49734
49834
  SecondaryButtonComponent,
49735
49835
  {
49736
49836
  onClick: deleteChart,
49737
- label: "Delete"
49837
+ label: "Delete",
49838
+ disabled: isSubmitting
49738
49839
  }
49739
49840
  ),
49740
49841
  !hideSubmitButton && /* @__PURE__ */ jsxs49(Fragment12, { children: [
@@ -49745,7 +49846,8 @@ function ChartBuilder({
49745
49846
  setIsOpen(false);
49746
49847
  onDiscardChanges && onDiscardChanges();
49747
49848
  },
49748
- label: "Discard changes"
49849
+ label: "Discard changes",
49850
+ disabled: isSubmitting
49749
49851
  }
49750
49852
  ),
49751
49853
  /* @__PURE__ */ jsx68(
@@ -49758,10 +49860,11 @@ function ChartBuilder({
49758
49860
  editChart();
49759
49861
  }
49760
49862
  },
49761
- disabled: formData.name === "" || formData.dashboardName === "" || formData.chartType === "" || filterIssues.length !== 0 || Object.values(validFilter).includes(false) || currentDashboard?.tenantKeys && customTenantAccess && Object.values(formFlags ?? {}).every(
49863
+ disabled: isSubmitting || formData.name === "" || formData.dashboardName === "" || formData.chartType === "" || filterIssues.length !== 0 || Object.values(validFilter).includes(false) || currentDashboard?.tenantKeys && customTenantAccess && Object.values(formFlags ?? {}).every(
49762
49864
  (value) => !value.length
49763
49865
  ),
49764
49866
  tooltipText: memoizedTooltipText,
49867
+ isLoading: isSubmitting,
49765
49868
  label: buttonLabel ? buttonLabel : report ? "Save changes" : "Add to dashboard"
49766
49869
  }
49767
49870
  )
@@ -50874,7 +50977,7 @@ function SQLEditor({
50874
50977
  onCloseChartBuilder && onCloseChartBuilder();
50875
50978
  }
50876
50979
  }, [isChartBuilderOpen]);
50877
- const handleRunSqlPrompt = useCallback5(async () => {
50980
+ const handleRunSqlPrompt = useCallback4(async () => {
50878
50981
  if (!client || sqlResponseLoading) {
50879
50982
  return;
50880
50983
  }
@@ -50893,7 +50996,7 @@ function SQLEditor({
50893
50996
  setQuery(resp.message);
50894
50997
  setSqlResponseLoading(false);
50895
50998
  }, [sqlPrompt, sqlResponseLoading]);
50896
- const debounceRunSqlPrompt = useCallback5(
50999
+ const debounceRunSqlPrompt = useCallback4(
50897
51000
  createDebounce(handleRunSqlPrompt, 500),
50898
51001
  [handleRunSqlPrompt]
50899
51002
  );
@@ -59489,16 +59592,24 @@ var useVirtualTables = () => {
59489
59592
  getToken,
59490
59593
  eventTracking
59491
59594
  });
59492
- setSchemaData({
59493
- schema: schemaData.schema.map((table) => {
59595
+ setSchemaData((prev) => {
59596
+ const existingIds = new Set(prev.schema.map((table) => table._id));
59597
+ const updatedSchema = prev.schema.map((table) => {
59494
59598
  if (tableIds.includes(table._id)) {
59495
59599
  return schema.find((newTable) => newTable._id === table._id) || table;
59496
59600
  }
59497
59601
  return table;
59498
- }, {}),
59499
- customFields: customFieldsByTable,
59500
- isSchemaLoading: false,
59501
- schemaWithCustomFields
59602
+ });
59603
+ const addedSchema = schema.filter(
59604
+ (table) => tableIds.includes(table._id) && !existingIds.has(table._id)
59605
+ );
59606
+ return {
59607
+ ...prev,
59608
+ schema: [...updatedSchema, ...addedSchema],
59609
+ customFields: customFieldsByTable,
59610
+ isSchemaLoading: false,
59611
+ schemaWithCustomFields
59612
+ };
59502
59613
  });
59503
59614
  return {
59504
59615
  schema,
@@ -59574,27 +59685,67 @@ var useVirtualTables = () => {
59574
59685
 
59575
59686
  // src/hooks/useChangelogRefresh.ts
59576
59687
  import { useContext as useContext43 } from "react";
59688
+ init_filterProcessing();
59577
59689
  var CALLER = "agent-changelog";
59690
+ var getChangeType = (entry) => {
59691
+ let parsed;
59692
+ if (typeof entry.changeObject === "string") {
59693
+ try {
59694
+ parsed = JSON.parse(entry.changeObject);
59695
+ } catch {
59696
+ return "UNKNOWN";
59697
+ }
59698
+ } else if (entry.changeObject && typeof entry.changeObject === "object") {
59699
+ parsed = entry.changeObject;
59700
+ } else {
59701
+ console.error(`Unknown changelog entry ${entry._id}`);
59702
+ return "UNKNOWN";
59703
+ }
59704
+ const changeType = parsed?.changeType;
59705
+ return typeof changeType === "string" ? changeType.toUpperCase() : "UNKNOWN";
59706
+ };
59578
59707
  var useChangelogRefresh = () => {
59579
- const { loadDashboard, dashboardConfig } = useContext43(DashboardConfigContext);
59708
+ const { loadDashboard, dashboardConfig, dashboardConfigDispatch } = useContext43(DashboardConfigContext);
59709
+ const {
59710
+ loadFiltersForDashboard,
59711
+ dispatch: dashboardFiltersDispatch,
59712
+ customFilterDispatch
59713
+ } = useContext43(DashboardFiltersContext);
59714
+ const [, dashboardDispatch] = useContext43(DashboardContext);
59715
+ const { reportsDispatch } = useContext43(ReportsContext);
59716
+ const [, setSchemaData] = useContext43(SchemaDataContext);
59580
59717
  const { allReportsById } = useAllReports();
59581
59718
  const { reloadSome } = useVirtualTables();
59582
59719
  const refreshChangelogEntries = async (entries, client) => {
59583
59720
  const dashboardsToReload = /* @__PURE__ */ new Set();
59584
59721
  let reloadAllDashboards = false;
59585
59722
  const schemaIds = [];
59723
+ const schemaIdsToRemove = /* @__PURE__ */ new Set();
59724
+ const dashboardsToRemove = /* @__PURE__ */ new Set();
59725
+ const reportsToRemove = /* @__PURE__ */ new Map();
59586
59726
  for (const entry of entries) {
59587
59727
  if (!entry.entityId || !entry.entityType) continue;
59728
+ const changeType = getChangeType(entry);
59588
59729
  switch (entry.entityType) {
59589
59730
  case "schema":
59590
- schemaIds.push(entry.entityId);
59731
+ if (changeType === "DELETE") {
59732
+ schemaIdsToRemove.add(entry.entityId);
59733
+ } else {
59734
+ schemaIds.push(entry.entityId);
59735
+ }
59591
59736
  break;
59592
59737
  case "dashboard":
59593
- dashboardsToReload.add(entry.entityId);
59738
+ if (changeType === "DELETE") {
59739
+ dashboardsToRemove.add(entry.entityId);
59740
+ } else {
59741
+ dashboardsToReload.add(entry.entityId);
59742
+ }
59594
59743
  break;
59595
59744
  case "report": {
59596
59745
  const owningDashboard = allReportsById[entry.entityId]?.dashboardName;
59597
- if (owningDashboard) {
59746
+ if (changeType === "DELETE") {
59747
+ reportsToRemove.set(entry.entityId, owningDashboard);
59748
+ } else if (owningDashboard) {
59598
59749
  dashboardsToReload.add(owningDashboard);
59599
59750
  } else {
59600
59751
  reloadAllDashboards = true;
@@ -59605,25 +59756,97 @@ var useChangelogRefresh = () => {
59605
59756
  break;
59606
59757
  }
59607
59758
  }
59608
- const finalDashboardSet = reloadAllDashboards ? new Set(Object.keys(dashboardConfig)) : dashboardsToReload;
59759
+ if (schemaIdsToRemove.size) {
59760
+ setSchemaData((prev) => ({
59761
+ ...prev,
59762
+ schema: prev.schema.filter(
59763
+ (table) => !schemaIdsToRemove.has(table._id)
59764
+ ),
59765
+ schemaWithCustomFields: (prev.schemaWithCustomFields ?? []).filter(
59766
+ (table) => !schemaIdsToRemove.has(table?._id)
59767
+ )
59768
+ }));
59769
+ }
59770
+ for (const dashboardName of dashboardsToRemove) {
59771
+ dashboardConfigDispatch({ type: "DELETE_DASHBOARD", id: dashboardName });
59772
+ dashboardFiltersDispatch({
59773
+ type: "DELETE_DASHBOARD_FILTERS",
59774
+ dashboardName
59775
+ });
59776
+ customFilterDispatch({
59777
+ type: "DELETE_CUSTOM_DASHBOARD_FILTERS",
59778
+ dashboardName
59779
+ });
59780
+ dashboardDispatch({ type: "CLEAR_DASHBOARD", dashboard: dashboardName });
59781
+ dashboardsToReload.delete(dashboardName);
59782
+ }
59783
+ for (const [reportId] of reportsToRemove) {
59784
+ reportsDispatch({ type: "DELETE_REPORT", id: reportId });
59785
+ dashboardDispatch({ type: "REMOVE_DASHBOARD_ITEM", id: reportId });
59786
+ }
59787
+ const finalDashboardSet = reloadAllDashboards ? new Set(
59788
+ Object.keys(dashboardConfig).filter(
59789
+ (d) => !dashboardsToRemove.has(d)
59790
+ )
59791
+ ) : dashboardsToReload;
59609
59792
  const tasks = [];
59610
- if (schemaIds.length) {
59793
+ const schemaIdsToReload = schemaIds.filter(
59794
+ (id) => !schemaIdsToRemove.has(id)
59795
+ );
59796
+ if (schemaIdsToReload.length) {
59611
59797
  tasks.push(
59612
- reloadSome(client, schemaIds, CALLER).catch((err) => {
59798
+ reloadSome(client, schemaIdsToReload, CALLER).catch((err) => {
59613
59799
  console.warn("[changelog-refresh] reloadSome failed:", err);
59614
59800
  })
59615
59801
  );
59616
59802
  }
59803
+ for (const [reportId, owningDashboard] of reportsToRemove) {
59804
+ if (!owningDashboard) continue;
59805
+ finalDashboardSet.delete(owningDashboard);
59806
+ tasks.push(
59807
+ Promise.resolve(
59808
+ loadDashboard(owningDashboard, true, {
59809
+ report: { id: reportId },
59810
+ action: "delete"
59811
+ })
59812
+ ).catch((err) => {
59813
+ console.warn(
59814
+ `[changelog-refresh] loadDashboard "${owningDashboard}" (report delete) failed:`,
59815
+ err
59816
+ );
59817
+ })
59818
+ );
59819
+ }
59617
59820
  for (const dashboardName of finalDashboardSet) {
59618
59821
  tasks.push(
59619
- Promise.resolve(loadDashboard(dashboardName, true)).catch(
59620
- (err) => {
59621
- console.warn(
59622
- `[changelog-refresh] loadDashboard "${dashboardName}" failed:`,
59623
- err
59624
- );
59625
- }
59626
- )
59822
+ Promise.resolve(loadDashboard(dashboardName, true)).then((updatedDashboard) => {
59823
+ if (!updatedDashboard) return;
59824
+ const dateFilter = updatedDashboard.dateFilter ? createDefaultDateFilter(
59825
+ updatedDashboard.dateFilter,
59826
+ Object.values(updatedDashboard.sections ?? {}).flat(),
59827
+ dashboardName
59828
+ ) : void 0;
59829
+ return loadFiltersForDashboard(
59830
+ dashboardName,
59831
+ [
59832
+ ...dateFilter ? [dateFilter] : [],
59833
+ ...updatedDashboard.filters?.map((filter) => ({
59834
+ ...filter,
59835
+ query: void 0
59836
+ })) ?? [],
59837
+ ...updatedDashboard.tenantFilters?.map((filter) => ({
59838
+ ...filter
59839
+ })) ?? []
59840
+ ],
59841
+ void 0,
59842
+ void 0
59843
+ );
59844
+ }).catch((err) => {
59845
+ console.warn(
59846
+ `[changelog-refresh] loadDashboard "${dashboardName}" failed:`,
59847
+ err
59848
+ );
59849
+ })
59627
59850
  );
59628
59851
  }
59629
59852
  await Promise.all(tasks);
@@ -59634,6 +59857,7 @@ var useChangelogRefresh = () => {
59634
59857
  };
59635
59858
 
59636
59859
  // src/index.ts
59860
+ init_dataFetcher();
59637
59861
  init_dataProcessing();
59638
59862
  init_Filter();
59639
59863
  init_constants();
@@ -59669,6 +59893,7 @@ export {
59669
59893
  ThemeContext,
59670
59894
  downloadCSV,
59671
59895
  quillFormat as format,
59896
+ quillFetch,
59672
59897
  useAllReports,
59673
59898
  useAskQuill,
59674
59899
  useChangelogRefresh,