@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.cjs CHANGED
@@ -18813,6 +18813,21 @@ var init_tableProcessing = __esm({
18813
18813
  }
18814
18814
  });
18815
18815
 
18816
+ // src/utils/changelogNotify.ts
18817
+ function setChangelogHandler(handler) {
18818
+ changelogHandler = handler;
18819
+ }
18820
+ function notifyChangelogs(entries) {
18821
+ changelogHandler?.(entries);
18822
+ }
18823
+ var changelogHandler;
18824
+ var init_changelogNotify = __esm({
18825
+ "src/utils/changelogNotify.ts"() {
18826
+ "use strict";
18827
+ changelogHandler = null;
18828
+ }
18829
+ });
18830
+
18816
18831
  // src/utils/dataFetcher.tsx
18817
18832
  var dataFetcher_exports = {};
18818
18833
  __export(dataFetcher_exports, {
@@ -18826,6 +18841,15 @@ __export(dataFetcher_exports, {
18826
18841
  quillFetch: () => quillFetch,
18827
18842
  quillStream: () => quillStream
18828
18843
  });
18844
+ function normalizeChangelogData(data) {
18845
+ if (!data) return data;
18846
+ if (Array.isArray(data.changelogs)) return data;
18847
+ if (!Array.isArray(data.changeLogs)) return data;
18848
+ return {
18849
+ ...data,
18850
+ changelogs: data.changeLogs
18851
+ };
18852
+ }
18829
18853
  function fetchQuillData(responseData) {
18830
18854
  if (!responseData) {
18831
18855
  return null;
@@ -19346,6 +19370,7 @@ var init_dataFetcher = __esm({
19346
19370
  init_reportBuilder();
19347
19371
  init_tableProcessing();
19348
19372
  init_dates();
19373
+ init_changelogNotify();
19349
19374
  quillFetch = async ({
19350
19375
  client,
19351
19376
  task,
@@ -19384,8 +19409,12 @@ var init_dataFetcher = __esm({
19384
19409
  if (result.data?.data && (result.data.queries || result.data.status || result.data.error)) {
19385
19410
  result = result.data;
19386
19411
  }
19412
+ const normalizedData = normalizeChangelogData(result.data);
19413
+ if (task !== "fetch-changelog-list" && Array.isArray(normalizedData?.changelogs)) {
19414
+ notifyChangelogs(normalizedData.changelogs);
19415
+ }
19387
19416
  return {
19388
- data: result.data,
19417
+ data: normalizedData,
19389
19418
  queries: result.queries,
19390
19419
  status: result.status,
19391
19420
  error: result.error
@@ -19851,6 +19880,7 @@ __export(index_exports, {
19851
19880
  ThemeContext: () => ThemeContext,
19852
19881
  downloadCSV: () => downloadCSV,
19853
19882
  format: () => quillFormat,
19883
+ quillFetch: () => quillFetch,
19854
19884
  useAllReports: () => useAllReports,
19855
19885
  useAskQuill: () => useAskQuill,
19856
19886
  useChangelogRefresh: () => useChangelogRefresh,
@@ -23773,6 +23803,7 @@ function normalizePSTRanges(start, end) {
23773
23803
  }
23774
23804
 
23775
23805
  // src/Context.tsx
23806
+ init_changelogNotify();
23776
23807
  var import_jsx_runtime = require("react/jsx-runtime");
23777
23808
  var dummySetter = () => {
23778
23809
  };
@@ -24211,7 +24242,8 @@ var ContextProvider = ({
24211
24242
  flags,
24212
24243
  isAdmin,
24213
24244
  getAuthorizationToken = async () => "",
24214
- eventTracking = null
24245
+ eventTracking = null,
24246
+ onChangelogs
24215
24247
  }) => {
24216
24248
  const cacheCabByTypeRef = (0, import_react.useRef)({});
24217
24249
  const getCacheCab = (0, import_react.useCallback)((storageType) => {
@@ -24221,6 +24253,10 @@ var ContextProvider = ({
24221
24253
  }
24222
24254
  return cacheCabByTypeRef.current[key];
24223
24255
  }, []);
24256
+ (0, import_react.useEffect)(() => {
24257
+ setChangelogHandler(onChangelogs ?? null);
24258
+ return () => setChangelogHandler(null);
24259
+ }, [onChangelogs]);
24224
24260
  const [client, setClient] = (0, import_react.useState)(
24225
24261
  typeof window !== "undefined" && sessionStorage ? JSON.parse(sessionStorage.getItem("quill-client") ?? "null") : null
24226
24262
  );
@@ -24278,8 +24314,7 @@ var ContextProvider = ({
24278
24314
  customReportFiltersReducer,
24279
24315
  {}
24280
24316
  );
24281
- const filterOptionsAbortControllers = (0, import_react.useRef)(/* @__PURE__ */ new Set());
24282
- const loadingFiltersForDashboard = (0, import_react.useRef)(/* @__PURE__ */ new Set());
24317
+ const dashboardFilterLoadState = (0, import_react.useRef)({});
24283
24318
  const backfilledDashboards = (0, import_react.useRef)(/* @__PURE__ */ new Set());
24284
24319
  const [reportFilters, reportFiltersDispatch] = (0, import_react.useReducer)(
24285
24320
  reportFiltersReducer,
@@ -24645,14 +24680,15 @@ var ContextProvider = ({
24645
24680
  }
24646
24681
  }
24647
24682
  async function loadFiltersForDashboard(dashboardName, filters, updatedFilterLabel, customFilters) {
24648
- if (loadingFiltersForDashboard.current.has(dashboardName)) {
24649
- return;
24650
- }
24651
- loadingFiltersForDashboard.current.add(dashboardName);
24683
+ const previousLoad = dashboardFilterLoadState.current[dashboardName];
24684
+ previousLoad?.controllers.forEach((controller) => controller.abort());
24685
+ const nextRequestId = (previousLoad?.requestId ?? 0) + 1;
24686
+ dashboardFilterLoadState.current[dashboardName] = {
24687
+ requestId: nextRequestId,
24688
+ controllers: /* @__PURE__ */ new Set()
24689
+ };
24690
+ const shouldApply = () => dashboardFilterLoadState.current[dashboardName]?.requestId === nextRequestId;
24652
24691
  try {
24653
- filterOptionsAbortControllers.current.forEach(
24654
- (controller) => controller.abort()
24655
- );
24656
24692
  dashboardFiltersDispatch({
24657
24693
  type: "ADD_DASHBOARD_FILTERS",
24658
24694
  dashboardName,
@@ -24666,6 +24702,9 @@ var ContextProvider = ({
24666
24702
  });
24667
24703
  await Promise.allSettled(
24668
24704
  filters.map(async (filter) => {
24705
+ if (!shouldApply()) {
24706
+ return null;
24707
+ }
24669
24708
  if (filter.filterType === "date_range") {
24670
24709
  dashboardFiltersDispatch({
24671
24710
  type: "UPDATE_DASHBOARD_FILTER",
@@ -24691,11 +24730,11 @@ var ContextProvider = ({
24691
24730
  return null;
24692
24731
  }
24693
24732
  if (filter.filterType === "tenant") {
24694
- await fetchTenantFilterOptions(dashboardName, filter);
24733
+ await fetchTenantFilterOptions(dashboardName, filter, shouldApply);
24695
24734
  return null;
24696
24735
  }
24697
24736
  const filterOptionsAbortController = new AbortController();
24698
- filterOptionsAbortControllers.current.add(
24737
+ dashboardFilterLoadState.current[dashboardName]?.controllers.add(
24699
24738
  filterOptionsAbortController
24700
24739
  );
24701
24740
  try {
@@ -24729,33 +24768,36 @@ var ContextProvider = ({
24729
24768
  getToken: getAuthorizationToken
24730
24769
  });
24731
24770
  const filterOptions = result.data?.filters[0]?.options ?? [];
24732
- dashboardFiltersDispatch({
24733
- type: "UPDATE_DASHBOARD_FILTER",
24734
- dashboardName,
24735
- filterName: filter.label,
24736
- data: {
24737
- filter: {
24738
- ...filter,
24739
- options: filterOptions
24740
- },
24741
- loading: false
24742
- }
24743
- });
24744
- return null;
24745
- } catch (error) {
24746
- if (error instanceof Error && error.name === "AbortError") {
24771
+ if (shouldApply() && !filterOptionsAbortController.signal.aborted) {
24747
24772
  dashboardFiltersDispatch({
24748
24773
  type: "UPDATE_DASHBOARD_FILTER",
24749
24774
  dashboardName,
24750
24775
  filterName: filter.label,
24751
24776
  data: {
24752
- filter,
24777
+ filter: {
24778
+ ...filter,
24779
+ options: filterOptions
24780
+ },
24753
24781
  loading: false
24754
24782
  }
24755
24783
  });
24784
+ }
24785
+ return null;
24786
+ } catch (error) {
24787
+ if (error instanceof Error && error.name === "AbortError") {
24788
+ if (shouldApply()) {
24789
+ dashboardFiltersDispatch({
24790
+ type: "UPDATE_DASHBOARD_FILTER",
24791
+ dashboardName,
24792
+ filterName: filter.label,
24793
+ data: {
24794
+ filter,
24795
+ loading: false
24796
+ }
24797
+ });
24798
+ }
24756
24799
  return;
24757
24800
  }
24758
- console.error("ERROR:", error);
24759
24801
  eventTracking?.logError?.({
24760
24802
  type: "bug",
24761
24803
  // TODO: determine type
@@ -24769,14 +24811,13 @@ var ContextProvider = ({
24769
24811
  }
24770
24812
  });
24771
24813
  } finally {
24772
- filterOptionsAbortControllers.current.delete(
24814
+ dashboardFilterLoadState.current[dashboardName]?.controllers.delete(
24773
24815
  filterOptionsAbortController
24774
24816
  );
24775
24817
  }
24776
24818
  })
24777
24819
  );
24778
24820
  } finally {
24779
- loadingFiltersForDashboard.current.delete(dashboardName);
24780
24821
  }
24781
24822
  }
24782
24823
  async function loadDashboard(dashboardName, fetchFromServer = false, reportAction) {
@@ -25404,8 +25445,11 @@ var ContextProvider = ({
25404
25445
  },
25405
25446
  [populatedClient, viewerTenantsByOwner]
25406
25447
  );
25407
- const fetchTenantFilterOptions = async (dashboardName, filter) => {
25448
+ const fetchTenantFilterOptions = async (dashboardName, filter, shouldApply) => {
25408
25449
  const mappings = await getMappedTenantsForDashboard(dashboardName);
25450
+ if (!shouldApply()) {
25451
+ return;
25452
+ }
25409
25453
  const options = mappings?.[filter.field] ?? [];
25410
25454
  dashboardFiltersDispatch({
25411
25455
  type: "UPDATE_DASHBOARD_FILTER",
@@ -26169,6 +26213,40 @@ var useAllReports = () => {
26169
26213
  allReportsById
26170
26214
  };
26171
26215
  };
26216
+ function hydrateDateFilter(raw) {
26217
+ if (!raw) return void 0;
26218
+ return {
26219
+ ...raw,
26220
+ presetOptions: raw.presetOptions?.map(
26221
+ (p) => ({
26222
+ ...p,
26223
+ loopStart: p.loopStart ? new Date(p.loopStart) : void 0,
26224
+ loopEnd: p.loopEnd ? new Date(p.loopEnd) : void 0
26225
+ })
26226
+ ),
26227
+ defaultPresetRanges: raw.defaultPresetRanges?.map(
26228
+ (p) => ({
26229
+ ...p,
26230
+ loopStart: p.loopStart ? new Date(p.loopStart) : void 0,
26231
+ loopEnd: p.loopEnd ? new Date(p.loopEnd) : void 0,
26232
+ customLabel: p.customLabel
26233
+ })
26234
+ )
26235
+ };
26236
+ }
26237
+ function getTaskResponseError(result) {
26238
+ const status = result.status ?? result.data?.status;
26239
+ const message = result.error ?? result.data?.error;
26240
+ if (status === "error") {
26241
+ return message ?? "Request failed";
26242
+ }
26243
+ if (message) {
26244
+ if (!result.data?.dashboard) {
26245
+ return message;
26246
+ }
26247
+ }
26248
+ return void 0;
26249
+ }
26172
26250
  var useDashboards = () => {
26173
26251
  const [dashboardReports, dashboardDispatch] = (0, import_react2.useContext)(DashboardContext);
26174
26252
  const {
@@ -26179,7 +26257,8 @@ var useDashboards = () => {
26179
26257
  const {
26180
26258
  dashboardFilters,
26181
26259
  loadFiltersForDashboard,
26182
- dispatch: dashboardFiltersDispatch
26260
+ dispatch: dashboardFiltersDispatch,
26261
+ customFilterDispatch
26183
26262
  } = (0, import_react2.useContext)(DashboardFiltersContext);
26184
26263
  const { reportsDispatch } = (0, import_react2.useContext)(ReportsContext);
26185
26264
  const { reportFiltersDispatch } = (0, import_react2.useContext)(ReportFiltersContext);
@@ -26206,7 +26285,8 @@ var useDashboards = () => {
26206
26285
  tenantFilters,
26207
26286
  filters,
26208
26287
  dateFilter,
26209
- dashboardOwners
26288
+ dashboardOwners,
26289
+ clientId
26210
26290
  }) => {
26211
26291
  if (!client) return;
26212
26292
  if (dashboardOwners?.some((key) => !key)) {
@@ -26234,7 +26314,7 @@ var useDashboards = () => {
26234
26314
  dateFilter,
26235
26315
  name: name2.trim(),
26236
26316
  task: "edit-dashboard",
26237
- clientId: client.clientId,
26317
+ clientId: clientId ?? client.clientId,
26238
26318
  tenantKeys: dashboardOwners
26239
26319
  };
26240
26320
  try {
@@ -26243,6 +26323,10 @@ var useDashboards = () => {
26243
26323
  task: "edit-dashboard",
26244
26324
  metadata: body
26245
26325
  });
26326
+ const updatedDashboard = updated.data.dashboard;
26327
+ if (!updatedDashboard) {
26328
+ throw new Error("Missing dashboard in edit-dashboard response");
26329
+ }
26246
26330
  eventTracking?.logEvent?.("create-dashboard", {
26247
26331
  dashboardName: name2
26248
26332
  });
@@ -26257,8 +26341,8 @@ var useDashboards = () => {
26257
26341
  id: name2,
26258
26342
  data: {
26259
26343
  config: {
26260
- ...updated.data.dashboard,
26261
- createdAt: new Date(updated.data.dashboard.createdAt)
26344
+ ...updatedDashboard,
26345
+ createdAt: new Date(updatedDashboard.createdAt)
26262
26346
  },
26263
26347
  loading: false
26264
26348
  }
@@ -26286,22 +26370,17 @@ var useDashboards = () => {
26286
26370
  dateFilter,
26287
26371
  customFilters,
26288
26372
  tenantKeys,
26289
- initialCacheDateRange
26373
+ initialCacheDateRange,
26374
+ clientId
26290
26375
  }) => {
26291
- if (!client) return;
26376
+ if (!client) {
26377
+ throw new Error("Client not loaded");
26378
+ }
26292
26379
  if (tenantKeys?.some((key) => !key)) {
26293
26380
  throw new Error("Tenant keys cannot be empty or undefined");
26294
26381
  }
26295
26382
  const dashboard = dashboardConfig[name2]?.config;
26296
- dashboardConfigDispatch({
26297
- type: "DELETE_DASHBOARD",
26298
- id: name2
26299
- });
26300
26383
  const oldFilters = dashboardFilters[name2];
26301
- dashboardFiltersDispatch({
26302
- type: "DELETE_DASHBOARD_FILTERS",
26303
- dashboardName: name2
26304
- });
26305
26384
  const body = {
26306
26385
  newDashboardName: newName.trim(),
26307
26386
  filters,
@@ -26310,7 +26389,7 @@ var useDashboards = () => {
26310
26389
  initialCacheDateRange,
26311
26390
  name: name2.trim(),
26312
26391
  task: "edit-dashboard",
26313
- clientId: client.clientId,
26392
+ clientId: clientId ?? client.clientId,
26314
26393
  tenantKeys
26315
26394
  };
26316
26395
  try {
@@ -26319,9 +26398,23 @@ var useDashboards = () => {
26319
26398
  task: "edit-dashboard",
26320
26399
  metadata: body
26321
26400
  });
26401
+ const taskError = getTaskResponseError(updated);
26402
+ if (taskError) {
26403
+ throw new Error(taskError);
26404
+ }
26405
+ const updatedDashboard = updated?.data?.dashboard ?? updated?.metadata?.dashboard ?? updated?.data?.metadata?.dashboard;
26406
+ if (!updatedDashboard) {
26407
+ throw new Error("Missing dashboard in edit-dashboard response");
26408
+ }
26409
+ if (name2 !== updatedDashboard.name) {
26410
+ dashboardConfigDispatch({
26411
+ type: "DELETE_DASHBOARD",
26412
+ id: name2
26413
+ });
26414
+ }
26322
26415
  eventTracking?.logEvent?.("update-dashboard", {
26323
- dashboardName: updated.data.dashboard.name,
26324
- dashboardId: updated.data.dashboard.dashboardId
26416
+ dashboardName: updatedDashboard.name,
26417
+ dashboardId: updatedDashboard.dashboardId
26325
26418
  });
26326
26419
  if (filters.length > 0 || dateFilter) {
26327
26420
  eventTracking?.logEvent?.("update-dashboard-filters", {
@@ -26331,36 +26424,19 @@ var useDashboards = () => {
26331
26424
  }
26332
26425
  dashboardConfigDispatch({
26333
26426
  type: "UPDATE_DASHBOARD",
26334
- id: updated.data.dashboard.name,
26427
+ id: updatedDashboard.name,
26335
26428
  data: {
26336
26429
  config: {
26337
26430
  ...dashboard,
26338
- ...updated.data.dashboard,
26431
+ ...updatedDashboard,
26339
26432
  allTenantFilters: tenantFilters ?? [],
26340
- dateFilter: updated.data.dashboard.dateFilter ? {
26341
- ...updated.data.dashboard.dateFilter,
26342
- presetOptions: updated.data.dashboard.dateFilter.presetOptions?.map(
26343
- (preset) => ({
26344
- ...preset,
26345
- loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
26346
- loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0
26347
- })
26348
- ),
26349
- defaultPresetRanges: updated.data.dashboard.dateFilter.defaultPresetRanges?.map(
26350
- (preset) => ({
26351
- ...preset,
26352
- loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
26353
- loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0,
26354
- customLabel: preset.customLabel
26355
- })
26356
- )
26357
- } : void 0,
26358
- createdAt: new Date(updated.data.dashboard.createdAt)
26433
+ dateFilter: hydrateDateFilter(updatedDashboard.dateFilter),
26434
+ createdAt: new Date(updatedDashboard.createdAt)
26359
26435
  },
26360
26436
  loading: false
26361
26437
  }
26362
26438
  });
26363
- Object.values(updated.data.dashboard.sections ?? {}).flat().forEach((report) => {
26439
+ Object.values(updatedDashboard.sections ?? {}).flat().forEach((report) => {
26364
26440
  dashboardDispatch({
26365
26441
  type: "ADD_DASHBOARD_ITEM",
26366
26442
  id: report._id,
@@ -26386,42 +26462,28 @@ var useDashboards = () => {
26386
26462
  id: report._id
26387
26463
  });
26388
26464
  });
26389
- if (dashboardFilters[name2])
26465
+ if (dashboardFilters[name2] && name2 !== newName)
26390
26466
  dashboardFiltersDispatch({
26391
26467
  type: "ADD_DASHBOARD_FILTERS",
26392
26468
  dashboardName: newName,
26393
26469
  data: dashboardFilters[name2]
26394
26470
  });
26471
+ const dateFilterSource = updatedDashboard.dateFilter ?? dateFilter;
26395
26472
  const range = convertPresetOptionsToSelectableList(
26396
- updated.data.dashboard.dateFilter?.presetOptions ?? [],
26397
- updated.data.dashboard.dateFilter?.defaultPresetRanges ?? []
26473
+ dateFilterSource?.presetOptions ?? [],
26474
+ dateFilterSource?.defaultPresetRanges ?? []
26398
26475
  ).find(
26399
- (option) => option.value === updated.data.dashboard.dateFilter?.primaryRange?.value
26400
- ) ?? PRIMARY_RANGE[updated.data.dashboard.dateFilter?.primaryRange?.value ?? "LAST_30_DAYS"] ?? PRIMARY_RANGE["LAST_30_DAYS"];
26401
- const updatedDateFilter = updated.data.dashboard.dateFilter ? {
26402
- ...updated.data.dashboard.dateFilter,
26403
- presetOptions: updated.data.dashboard.dateFilter.presetOptions?.map(
26404
- (preset) => ({
26405
- ...preset,
26406
- loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
26407
- loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0
26408
- })
26409
- ),
26410
- defaultPresetRanges: updated.data.dashboard.dateFilter.defaultPresetRanges?.map(
26411
- (preset) => ({
26412
- ...preset,
26413
- loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
26414
- loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0,
26415
- customLabel: preset.customLabel
26416
- })
26417
- ),
26418
- dashboardName: updated.data.dashboard.name,
26419
- preset: updated.data.dashboard.dateFilter.primaryRange,
26476
+ (option) => option.value === dateFilterSource?.primaryRange?.value
26477
+ ) ?? PRIMARY_RANGE[dateFilterSource?.primaryRange?.value ?? "LAST_30_DAYS"] ?? PRIMARY_RANGE["LAST_30_DAYS"];
26478
+ const updatedDateFilter = dateFilterSource ? {
26479
+ ...hydrateDateFilter(dateFilterSource),
26480
+ dashboardName: updatedDashboard.name,
26481
+ preset: dateFilterSource.primaryRange,
26420
26482
  filterType: "date_range" /* Date */,
26421
26483
  dateField: [
26422
26484
  ...new Map(
26423
26485
  Object.values(
26424
- dashboardConfig[updated.data.dashboard.name]?.config.sections ?? {}
26486
+ dashboardConfig[updatedDashboard.name]?.config.sections ?? {}
26425
26487
  ).flat().map((report) => {
26426
26488
  const key = JSON.stringify(report.dateField);
26427
26489
  return [key, report.dateField];
@@ -26433,11 +26495,13 @@ var useDashboards = () => {
26433
26495
  endDate: !range.endDate || range.endDate instanceof Date ? range.endDate : new Date(range.endDate)
26434
26496
  // when range.endDate is a string
26435
26497
  } : void 0;
26436
- const mappedTenants = await getMappedTenantsForDashboard(newName);
26498
+ const mappedTenants = await getMappedTenantsForDashboard(newName).catch(
26499
+ () => void 0
26500
+ );
26437
26501
  const mappedTenantKeys = Object.keys(mappedTenants ?? {});
26438
26502
  const newFilters = [
26439
26503
  ...updatedDateFilter ? [updatedDateFilter] : [],
26440
- ...updated.data.dashboard.filters.map(
26504
+ ...(updatedDashboard.filters ?? []).map(
26441
26505
  (f) => ({
26442
26506
  ...f,
26443
26507
  selectedValue: oldFilters?.[f.label]?.filter?.selectedValue,
@@ -26445,7 +26509,7 @@ var useDashboards = () => {
26445
26509
  operator: oldFilters?.[f.label]?.filter?.operator
26446
26510
  })
26447
26511
  ) ?? [],
26448
- ...(updated.data.dashboard.tenantFilters?.map(
26512
+ ...(updatedDashboard.tenantFilters?.map(
26449
26513
  (f) => ({
26450
26514
  ...f,
26451
26515
  values: oldFilters?.[f.label]?.filter?.values
@@ -26468,16 +26532,18 @@ var useDashboards = () => {
26468
26532
  };
26469
26533
  }
26470
26534
  });
26471
- dashboardFiltersDispatch({
26472
- type: "DELETE_DASHBOARD_FILTERS",
26473
- dashboardName: name2
26474
- });
26475
- loadFiltersForDashboard(
26476
- updated.data.dashboard.name,
26535
+ await loadFiltersForDashboard(
26536
+ updatedDashboard.name,
26477
26537
  newFilters,
26478
26538
  void 0,
26479
26539
  customFilters
26480
26540
  );
26541
+ if (name2 !== updatedDashboard.name) {
26542
+ dashboardFiltersDispatch({
26543
+ type: "DELETE_DASHBOARD_FILTERS",
26544
+ dashboardName: name2
26545
+ });
26546
+ }
26481
26547
  } catch (e) {
26482
26548
  console.error(e);
26483
26549
  eventTracking?.logError?.({
@@ -26492,6 +26558,7 @@ var useDashboards = () => {
26492
26558
  function: "updateDashboard"
26493
26559
  }
26494
26560
  });
26561
+ throw e;
26495
26562
  }
26496
26563
  };
26497
26564
  const deleteDashboard = async (name2) => {
@@ -26509,6 +26576,14 @@ var useDashboards = () => {
26509
26576
  type: "DELETE_DASHBOARD",
26510
26577
  id: name2
26511
26578
  });
26579
+ dashboardFiltersDispatch({
26580
+ type: "DELETE_DASHBOARD_FILTERS",
26581
+ dashboardName: name2
26582
+ });
26583
+ customFilterDispatch({
26584
+ type: "DELETE_CUSTOM_DASHBOARD_FILTERS",
26585
+ dashboardName: name2
26586
+ });
26512
26587
  };
26513
26588
  return {
26514
26589
  dashboards: isLoading || isDashboardsLoading ? null : dashboards,
@@ -26736,7 +26811,7 @@ var useDashboard = (dashboardName, config) => {
26736
26811
  const fetchStartTime = Date.now();
26737
26812
  let totalCached = 0;
26738
26813
  await Promise.all(
26739
- allReports.map(async (reportInfo, idx) => {
26814
+ allReports.map(async (reportInfo) => {
26740
26815
  const reportId = reportInfo.id;
26741
26816
  const requestId = (reportRequestIds.current[reportId] ?? 0) + 1;
26742
26817
  reportRequestIds.current[reportId] = requestId;
@@ -26783,7 +26858,19 @@ var useDashboard = (dashboardName, config) => {
26783
26858
  };
26784
26859
  };
26785
26860
  if (cacheEnabled && cacheCab.isCacheable(reportId)) {
26786
- const report2 = await cacheCab.get(reportId, dashboardFilters2, customFilters.concat(customReportFiltersArray), reportInfo.pivot, client, tenants, flags, pageSize, getToken, eventTracking, forceCacheToRefresh);
26861
+ const report2 = await cacheCab.get(
26862
+ reportId,
26863
+ dashboardFilters2,
26864
+ customFilters.concat(customReportFiltersArray),
26865
+ reportInfo.pivot,
26866
+ client,
26867
+ tenants,
26868
+ flags,
26869
+ pageSize,
26870
+ getToken,
26871
+ eventTracking,
26872
+ forceCacheToRefresh
26873
+ );
26787
26874
  if (reportRequestIds.current[reportId] !== requestId) {
26788
26875
  return null;
26789
26876
  }
@@ -26996,11 +27083,15 @@ var useDashboard = (dashboardName, config) => {
26996
27083
  })
26997
27084
  );
26998
27085
  if (!loadedDashes.includes(dashboardName) || !cacheEnabled || forceCacheToRefresh) {
26999
- setLoadedDashes((prev) => prev.includes(dashboardName) ? prev : [...prev, dashboardName]);
27086
+ setLoadedDashes(
27087
+ (prev) => prev.includes(dashboardName) ? prev : [...prev, dashboardName]
27088
+ );
27000
27089
  setLastUpdatedDict((prev) => ({ ...prev, [dashboardName]: Date.now() }));
27001
27090
  }
27002
27091
  if (logCacheStatistics) {
27003
- console.log(`Dashboard "${dashboardName}": Cache Rate: ${(100 * totalCached / allReports.length).toFixed(1)}%, load time: ${((Date.now() - fetchStartTime) / 1e3).toFixed(2)} secs`);
27092
+ console.log(
27093
+ `Dashboard "${dashboardName}": Cache Rate: ${(100 * totalCached / allReports.length).toFixed(1)}%, load time: ${((Date.now() - fetchStartTime) / 1e3).toFixed(2)} secs`
27094
+ );
27004
27095
  }
27005
27096
  };
27006
27097
  return {
@@ -42241,7 +42332,8 @@ var getThemedStyles = (theme) => ({
42241
42332
  function Dashboard({
42242
42333
  name: name2,
42243
42334
  onClickReport,
42244
- containerStyle
42335
+ containerStyle,
42336
+ EmptyDashboardComponent
42245
42337
  }) {
42246
42338
  const [themeFromContext] = (0, import_react41.useContext)(ThemeContext);
42247
42339
  const theme = (0, import_react41.useMemo)(
@@ -42424,7 +42516,8 @@ function Dashboard({
42424
42516
  sections,
42425
42517
  sectionOrder,
42426
42518
  onClickReport,
42427
- styles: themedStyles
42519
+ styles: themedStyles,
42520
+ EmptyDashboardComponent
42428
42521
  }
42429
42522
  )
42430
42523
  ] });
@@ -42432,7 +42525,8 @@ function Dashboard({
42432
42525
  function DashboardContent({
42433
42526
  sections,
42434
42527
  sectionOrder,
42435
- onClickReport
42528
+ onClickReport,
42529
+ EmptyDashboardComponent
42436
42530
  }) {
42437
42531
  const getSection = (name2) => {
42438
42532
  if (!sections) {
@@ -42493,6 +42587,11 @@ function DashboardContent({
42493
42587
  return aIndex - bIndex;
42494
42588
  });
42495
42589
  }, [sections, sectionOrder]);
42590
+ if (sections && (Object.keys(sections).length === 0 || Object.values(sections).flat().length === 0)) {
42591
+ if (EmptyDashboardComponent) {
42592
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(EmptyDashboardComponent, {});
42593
+ }
42594
+ }
42496
42595
  return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { style: styles.contentWrap, children: [
42497
42596
  metricReports.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { style: styles.splitGrid, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("section", { children: metricReports.map((report) => /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
42498
42597
  "div",
@@ -42611,7 +42710,8 @@ var QuillProvider = ({
42611
42710
  withCredentials,
42612
42711
  isAdmin,
42613
42712
  getAuthorizationToken,
42614
- eventTracking
42713
+ eventTracking,
42714
+ onChangelogs
42615
42715
  }) => {
42616
42716
  if (queryEndpoint === QUILL_SERVER + QUILL_QUERY_ENDPOINT && !tenants) {
42617
42717
  throw new Error("Tenants are required when using the quill cloud endpoint");
@@ -42630,6 +42730,7 @@ var QuillProvider = ({
42630
42730
  isAdmin,
42631
42731
  getAuthorizationToken,
42632
42732
  eventTracking,
42733
+ onChangelogs,
42633
42734
  children
42634
42735
  }
42635
42736
  );
@@ -49565,7 +49666,8 @@ function ChartBuilder({
49565
49666
  SecondaryButtonComponent,
49566
49667
  {
49567
49668
  onClick: deleteChart,
49568
- label: "Delete"
49669
+ label: "Delete",
49670
+ disabled: isSubmitting
49569
49671
  }
49570
49672
  ),
49571
49673
  !hideSubmitButton && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(import_jsx_runtime68.Fragment, { children: [
@@ -49576,7 +49678,8 @@ function ChartBuilder({
49576
49678
  setIsOpen(false);
49577
49679
  onDiscardChanges && onDiscardChanges();
49578
49680
  },
49579
- label: "Discard changes"
49681
+ label: "Discard changes",
49682
+ disabled: isSubmitting
49580
49683
  }
49581
49684
  ),
49582
49685
  /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
@@ -49589,10 +49692,11 @@ function ChartBuilder({
49589
49692
  editChart();
49590
49693
  }
49591
49694
  },
49592
- disabled: formData.name === "" || formData.dashboardName === "" || formData.chartType === "" || filterIssues.length !== 0 || Object.values(validFilter).includes(false) || currentDashboard?.tenantKeys && customTenantAccess && Object.values(formFlags ?? {}).every(
49695
+ disabled: isSubmitting || formData.name === "" || formData.dashboardName === "" || formData.chartType === "" || filterIssues.length !== 0 || Object.values(validFilter).includes(false) || currentDashboard?.tenantKeys && customTenantAccess && Object.values(formFlags ?? {}).every(
49593
49696
  (value) => !value.length
49594
49697
  ),
49595
49698
  tooltipText: memoizedTooltipText,
49699
+ isLoading: isSubmitting,
49596
49700
  label: buttonLabel ? buttonLabel : report ? "Save changes" : "Add to dashboard"
49597
49701
  }
49598
49702
  )
@@ -59284,16 +59388,24 @@ var useVirtualTables = () => {
59284
59388
  getToken,
59285
59389
  eventTracking
59286
59390
  });
59287
- setSchemaData({
59288
- schema: schemaData.schema.map((table) => {
59391
+ setSchemaData((prev) => {
59392
+ const existingIds = new Set(prev.schema.map((table) => table._id));
59393
+ const updatedSchema = prev.schema.map((table) => {
59289
59394
  if (tableIds.includes(table._id)) {
59290
59395
  return schema.find((newTable) => newTable._id === table._id) || table;
59291
59396
  }
59292
59397
  return table;
59293
- }, {}),
59294
- customFields: customFieldsByTable,
59295
- isSchemaLoading: false,
59296
- schemaWithCustomFields
59398
+ });
59399
+ const addedSchema = schema.filter(
59400
+ (table) => tableIds.includes(table._id) && !existingIds.has(table._id)
59401
+ );
59402
+ return {
59403
+ ...prev,
59404
+ schema: [...updatedSchema, ...addedSchema],
59405
+ customFields: customFieldsByTable,
59406
+ isSchemaLoading: false,
59407
+ schemaWithCustomFields
59408
+ };
59297
59409
  });
59298
59410
  return {
59299
59411
  schema,
@@ -59369,27 +59481,67 @@ var useVirtualTables = () => {
59369
59481
 
59370
59482
  // src/hooks/useChangelogRefresh.ts
59371
59483
  var import_react67 = require("react");
59484
+ init_filterProcessing();
59372
59485
  var CALLER = "agent-changelog";
59486
+ var getChangeType = (entry) => {
59487
+ let parsed;
59488
+ if (typeof entry.changeObject === "string") {
59489
+ try {
59490
+ parsed = JSON.parse(entry.changeObject);
59491
+ } catch {
59492
+ return "UNKNOWN";
59493
+ }
59494
+ } else if (entry.changeObject && typeof entry.changeObject === "object") {
59495
+ parsed = entry.changeObject;
59496
+ } else {
59497
+ console.error(`Unknown changelog entry ${entry._id}`);
59498
+ return "UNKNOWN";
59499
+ }
59500
+ const changeType = parsed?.changeType;
59501
+ return typeof changeType === "string" ? changeType.toUpperCase() : "UNKNOWN";
59502
+ };
59373
59503
  var useChangelogRefresh = () => {
59374
- const { loadDashboard, dashboardConfig } = (0, import_react67.useContext)(DashboardConfigContext);
59504
+ const { loadDashboard, dashboardConfig, dashboardConfigDispatch } = (0, import_react67.useContext)(DashboardConfigContext);
59505
+ const {
59506
+ loadFiltersForDashboard,
59507
+ dispatch: dashboardFiltersDispatch,
59508
+ customFilterDispatch
59509
+ } = (0, import_react67.useContext)(DashboardFiltersContext);
59510
+ const [, dashboardDispatch] = (0, import_react67.useContext)(DashboardContext);
59511
+ const { reportsDispatch } = (0, import_react67.useContext)(ReportsContext);
59512
+ const [, setSchemaData] = (0, import_react67.useContext)(SchemaDataContext);
59375
59513
  const { allReportsById } = useAllReports();
59376
59514
  const { reloadSome } = useVirtualTables();
59377
59515
  const refreshChangelogEntries = async (entries, client) => {
59378
59516
  const dashboardsToReload = /* @__PURE__ */ new Set();
59379
59517
  let reloadAllDashboards = false;
59380
59518
  const schemaIds = [];
59519
+ const schemaIdsToRemove = /* @__PURE__ */ new Set();
59520
+ const dashboardsToRemove = /* @__PURE__ */ new Set();
59521
+ const reportsToRemove = /* @__PURE__ */ new Map();
59381
59522
  for (const entry of entries) {
59382
59523
  if (!entry.entityId || !entry.entityType) continue;
59524
+ const changeType = getChangeType(entry);
59383
59525
  switch (entry.entityType) {
59384
59526
  case "schema":
59385
- schemaIds.push(entry.entityId);
59527
+ if (changeType === "DELETE") {
59528
+ schemaIdsToRemove.add(entry.entityId);
59529
+ } else {
59530
+ schemaIds.push(entry.entityId);
59531
+ }
59386
59532
  break;
59387
59533
  case "dashboard":
59388
- dashboardsToReload.add(entry.entityId);
59534
+ if (changeType === "DELETE") {
59535
+ dashboardsToRemove.add(entry.entityId);
59536
+ } else {
59537
+ dashboardsToReload.add(entry.entityId);
59538
+ }
59389
59539
  break;
59390
59540
  case "report": {
59391
59541
  const owningDashboard = allReportsById[entry.entityId]?.dashboardName;
59392
- if (owningDashboard) {
59542
+ if (changeType === "DELETE") {
59543
+ reportsToRemove.set(entry.entityId, owningDashboard);
59544
+ } else if (owningDashboard) {
59393
59545
  dashboardsToReload.add(owningDashboard);
59394
59546
  } else {
59395
59547
  reloadAllDashboards = true;
@@ -59400,25 +59552,97 @@ var useChangelogRefresh = () => {
59400
59552
  break;
59401
59553
  }
59402
59554
  }
59403
- const finalDashboardSet = reloadAllDashboards ? new Set(Object.keys(dashboardConfig)) : dashboardsToReload;
59555
+ if (schemaIdsToRemove.size) {
59556
+ setSchemaData((prev) => ({
59557
+ ...prev,
59558
+ schema: prev.schema.filter(
59559
+ (table) => !schemaIdsToRemove.has(table._id)
59560
+ ),
59561
+ schemaWithCustomFields: (prev.schemaWithCustomFields ?? []).filter(
59562
+ (table) => !schemaIdsToRemove.has(table?._id)
59563
+ )
59564
+ }));
59565
+ }
59566
+ for (const dashboardName of dashboardsToRemove) {
59567
+ dashboardConfigDispatch({ type: "DELETE_DASHBOARD", id: dashboardName });
59568
+ dashboardFiltersDispatch({
59569
+ type: "DELETE_DASHBOARD_FILTERS",
59570
+ dashboardName
59571
+ });
59572
+ customFilterDispatch({
59573
+ type: "DELETE_CUSTOM_DASHBOARD_FILTERS",
59574
+ dashboardName
59575
+ });
59576
+ dashboardDispatch({ type: "CLEAR_DASHBOARD", dashboard: dashboardName });
59577
+ dashboardsToReload.delete(dashboardName);
59578
+ }
59579
+ for (const [reportId] of reportsToRemove) {
59580
+ reportsDispatch({ type: "DELETE_REPORT", id: reportId });
59581
+ dashboardDispatch({ type: "REMOVE_DASHBOARD_ITEM", id: reportId });
59582
+ }
59583
+ const finalDashboardSet = reloadAllDashboards ? new Set(
59584
+ Object.keys(dashboardConfig).filter(
59585
+ (d) => !dashboardsToRemove.has(d)
59586
+ )
59587
+ ) : dashboardsToReload;
59404
59588
  const tasks = [];
59405
- if (schemaIds.length) {
59589
+ const schemaIdsToReload = schemaIds.filter(
59590
+ (id) => !schemaIdsToRemove.has(id)
59591
+ );
59592
+ if (schemaIdsToReload.length) {
59406
59593
  tasks.push(
59407
- reloadSome(client, schemaIds, CALLER).catch((err) => {
59594
+ reloadSome(client, schemaIdsToReload, CALLER).catch((err) => {
59408
59595
  console.warn("[changelog-refresh] reloadSome failed:", err);
59409
59596
  })
59410
59597
  );
59411
59598
  }
59599
+ for (const [reportId, owningDashboard] of reportsToRemove) {
59600
+ if (!owningDashboard) continue;
59601
+ finalDashboardSet.delete(owningDashboard);
59602
+ tasks.push(
59603
+ Promise.resolve(
59604
+ loadDashboard(owningDashboard, true, {
59605
+ report: { id: reportId },
59606
+ action: "delete"
59607
+ })
59608
+ ).catch((err) => {
59609
+ console.warn(
59610
+ `[changelog-refresh] loadDashboard "${owningDashboard}" (report delete) failed:`,
59611
+ err
59612
+ );
59613
+ })
59614
+ );
59615
+ }
59412
59616
  for (const dashboardName of finalDashboardSet) {
59413
59617
  tasks.push(
59414
- Promise.resolve(loadDashboard(dashboardName, true)).catch(
59415
- (err) => {
59416
- console.warn(
59417
- `[changelog-refresh] loadDashboard "${dashboardName}" failed:`,
59418
- err
59419
- );
59420
- }
59421
- )
59618
+ Promise.resolve(loadDashboard(dashboardName, true)).then((updatedDashboard) => {
59619
+ if (!updatedDashboard) return;
59620
+ const dateFilter = updatedDashboard.dateFilter ? createDefaultDateFilter(
59621
+ updatedDashboard.dateFilter,
59622
+ Object.values(updatedDashboard.sections ?? {}).flat(),
59623
+ dashboardName
59624
+ ) : void 0;
59625
+ return loadFiltersForDashboard(
59626
+ dashboardName,
59627
+ [
59628
+ ...dateFilter ? [dateFilter] : [],
59629
+ ...updatedDashboard.filters?.map((filter) => ({
59630
+ ...filter,
59631
+ query: void 0
59632
+ })) ?? [],
59633
+ ...updatedDashboard.tenantFilters?.map((filter) => ({
59634
+ ...filter
59635
+ })) ?? []
59636
+ ],
59637
+ void 0,
59638
+ void 0
59639
+ );
59640
+ }).catch((err) => {
59641
+ console.warn(
59642
+ `[changelog-refresh] loadDashboard "${dashboardName}" failed:`,
59643
+ err
59644
+ );
59645
+ })
59422
59646
  );
59423
59647
  }
59424
59648
  await Promise.all(tasks);
@@ -59429,6 +59653,7 @@ var useChangelogRefresh = () => {
59429
59653
  };
59430
59654
 
59431
59655
  // src/index.ts
59656
+ init_dataFetcher();
59432
59657
  init_dataProcessing();
59433
59658
  init_Filter();
59434
59659
  init_constants();
@@ -59465,6 +59690,7 @@ init_constants();
59465
59690
  ThemeContext,
59466
59691
  downloadCSV,
59467
59692
  format,
59693
+ quillFetch,
59468
59694
  useAllReports,
59469
59695
  useAskQuill,
59470
59696
  useChangelogRefresh,