@quillsql/react 2.16.36 → 2.16.38

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