@quillsql/react 2.15.5 → 2.15.6

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
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name2 in all)
10
13
  __defProp(target, name2, { get: all[name2], enumerable: true });
@@ -27,6 +30,358 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
30
  ));
28
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
32
 
33
+ // ../../node_modules/pluralize/pluralize.js
34
+ var require_pluralize = __commonJS({
35
+ "../../node_modules/pluralize/pluralize.js"(exports2, module2) {
36
+ "use strict";
37
+ (function(root, pluralize2) {
38
+ if (typeof require === "function" && typeof exports2 === "object" && typeof module2 === "object") {
39
+ module2.exports = pluralize2();
40
+ } else if (typeof define === "function" && define.amd) {
41
+ define(function() {
42
+ return pluralize2();
43
+ });
44
+ } else {
45
+ root.pluralize = pluralize2();
46
+ }
47
+ })(exports2, function() {
48
+ var pluralRules = [];
49
+ var singularRules = [];
50
+ var uncountables = {};
51
+ var irregularPlurals = {};
52
+ var irregularSingles = {};
53
+ function sanitizeRule(rule) {
54
+ if (typeof rule === "string") {
55
+ return new RegExp("^" + rule + "$", "i");
56
+ }
57
+ return rule;
58
+ }
59
+ function restoreCase(word, token) {
60
+ if (word === token) return token;
61
+ if (word === word.toLowerCase()) return token.toLowerCase();
62
+ if (word === word.toUpperCase()) return token.toUpperCase();
63
+ if (word[0] === word[0].toUpperCase()) {
64
+ return token.charAt(0).toUpperCase() + token.substr(1).toLowerCase();
65
+ }
66
+ return token.toLowerCase();
67
+ }
68
+ function interpolate(str, args) {
69
+ return str.replace(/\$(\d{1,2})/g, function(match, index) {
70
+ return args[index] || "";
71
+ });
72
+ }
73
+ function replace(word, rule) {
74
+ return word.replace(rule[0], function(match, index) {
75
+ var result = interpolate(rule[1], arguments);
76
+ if (match === "") {
77
+ return restoreCase(word[index - 1], result);
78
+ }
79
+ return restoreCase(match, result);
80
+ });
81
+ }
82
+ function sanitizeWord(token, word, rules) {
83
+ if (!token.length || uncountables.hasOwnProperty(token)) {
84
+ return word;
85
+ }
86
+ var len = rules.length;
87
+ while (len--) {
88
+ var rule = rules[len];
89
+ if (rule[0].test(word)) return replace(word, rule);
90
+ }
91
+ return word;
92
+ }
93
+ function replaceWord(replaceMap, keepMap, rules) {
94
+ return function(word) {
95
+ var token = word.toLowerCase();
96
+ if (keepMap.hasOwnProperty(token)) {
97
+ return restoreCase(word, token);
98
+ }
99
+ if (replaceMap.hasOwnProperty(token)) {
100
+ return restoreCase(word, replaceMap[token]);
101
+ }
102
+ return sanitizeWord(token, word, rules);
103
+ };
104
+ }
105
+ function checkWord(replaceMap, keepMap, rules, bool) {
106
+ return function(word) {
107
+ var token = word.toLowerCase();
108
+ if (keepMap.hasOwnProperty(token)) return true;
109
+ if (replaceMap.hasOwnProperty(token)) return false;
110
+ return sanitizeWord(token, token, rules) === token;
111
+ };
112
+ }
113
+ function pluralize2(word, count, inclusive) {
114
+ var pluralized = count === 1 ? pluralize2.singular(word) : pluralize2.plural(word);
115
+ return (inclusive ? count + " " : "") + pluralized;
116
+ }
117
+ pluralize2.plural = replaceWord(
118
+ irregularSingles,
119
+ irregularPlurals,
120
+ pluralRules
121
+ );
122
+ pluralize2.isPlural = checkWord(
123
+ irregularSingles,
124
+ irregularPlurals,
125
+ pluralRules
126
+ );
127
+ pluralize2.singular = replaceWord(
128
+ irregularPlurals,
129
+ irregularSingles,
130
+ singularRules
131
+ );
132
+ pluralize2.isSingular = checkWord(
133
+ irregularPlurals,
134
+ irregularSingles,
135
+ singularRules
136
+ );
137
+ pluralize2.addPluralRule = function(rule, replacement) {
138
+ pluralRules.push([sanitizeRule(rule), replacement]);
139
+ };
140
+ pluralize2.addSingularRule = function(rule, replacement) {
141
+ singularRules.push([sanitizeRule(rule), replacement]);
142
+ };
143
+ pluralize2.addUncountableRule = function(word) {
144
+ if (typeof word === "string") {
145
+ uncountables[word.toLowerCase()] = true;
146
+ return;
147
+ }
148
+ pluralize2.addPluralRule(word, "$0");
149
+ pluralize2.addSingularRule(word, "$0");
150
+ };
151
+ pluralize2.addIrregularRule = function(single, plural) {
152
+ plural = plural.toLowerCase();
153
+ single = single.toLowerCase();
154
+ irregularSingles[single] = plural;
155
+ irregularPlurals[plural] = single;
156
+ };
157
+ [
158
+ // Pronouns.
159
+ ["I", "we"],
160
+ ["me", "us"],
161
+ ["he", "they"],
162
+ ["she", "they"],
163
+ ["them", "them"],
164
+ ["myself", "ourselves"],
165
+ ["yourself", "yourselves"],
166
+ ["itself", "themselves"],
167
+ ["herself", "themselves"],
168
+ ["himself", "themselves"],
169
+ ["themself", "themselves"],
170
+ ["is", "are"],
171
+ ["was", "were"],
172
+ ["has", "have"],
173
+ ["this", "these"],
174
+ ["that", "those"],
175
+ // Words ending in with a consonant and `o`.
176
+ ["echo", "echoes"],
177
+ ["dingo", "dingoes"],
178
+ ["volcano", "volcanoes"],
179
+ ["tornado", "tornadoes"],
180
+ ["torpedo", "torpedoes"],
181
+ // Ends with `us`.
182
+ ["genus", "genera"],
183
+ ["viscus", "viscera"],
184
+ // Ends with `ma`.
185
+ ["stigma", "stigmata"],
186
+ ["stoma", "stomata"],
187
+ ["dogma", "dogmata"],
188
+ ["lemma", "lemmata"],
189
+ ["schema", "schemata"],
190
+ ["anathema", "anathemata"],
191
+ // Other irregular rules.
192
+ ["ox", "oxen"],
193
+ ["axe", "axes"],
194
+ ["die", "dice"],
195
+ ["yes", "yeses"],
196
+ ["foot", "feet"],
197
+ ["eave", "eaves"],
198
+ ["goose", "geese"],
199
+ ["tooth", "teeth"],
200
+ ["quiz", "quizzes"],
201
+ ["human", "humans"],
202
+ ["proof", "proofs"],
203
+ ["carve", "carves"],
204
+ ["valve", "valves"],
205
+ ["looey", "looies"],
206
+ ["thief", "thieves"],
207
+ ["groove", "grooves"],
208
+ ["pickaxe", "pickaxes"],
209
+ ["passerby", "passersby"]
210
+ ].forEach(function(rule) {
211
+ return pluralize2.addIrregularRule(rule[0], rule[1]);
212
+ });
213
+ [
214
+ [/s?$/i, "s"],
215
+ [/[^\u0000-\u007F]$/i, "$0"],
216
+ [/([^aeiou]ese)$/i, "$1"],
217
+ [/(ax|test)is$/i, "$1es"],
218
+ [/(alias|[^aou]us|t[lm]as|gas|ris)$/i, "$1es"],
219
+ [/(e[mn]u)s?$/i, "$1s"],
220
+ [/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i, "$1"],
221
+ [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, "$1i"],
222
+ [/(alumn|alg|vertebr)(?:a|ae)$/i, "$1ae"],
223
+ [/(seraph|cherub)(?:im)?$/i, "$1im"],
224
+ [/(her|at|gr)o$/i, "$1oes"],
225
+ [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i, "$1a"],
226
+ [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i, "$1a"],
227
+ [/sis$/i, "ses"],
228
+ [/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, "$1$2ves"],
229
+ [/([^aeiouy]|qu)y$/i, "$1ies"],
230
+ [/([^ch][ieo][ln])ey$/i, "$1ies"],
231
+ [/(x|ch|ss|sh|zz)$/i, "$1es"],
232
+ [/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, "$1ices"],
233
+ [/\b((?:tit)?m|l)(?:ice|ouse)$/i, "$1ice"],
234
+ [/(pe)(?:rson|ople)$/i, "$1ople"],
235
+ [/(child)(?:ren)?$/i, "$1ren"],
236
+ [/eaux$/i, "$0"],
237
+ [/m[ae]n$/i, "men"],
238
+ ["thou", "you"]
239
+ ].forEach(function(rule) {
240
+ return pluralize2.addPluralRule(rule[0], rule[1]);
241
+ });
242
+ [
243
+ [/s$/i, ""],
244
+ [/(ss)$/i, "$1"],
245
+ [/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i, "$1fe"],
246
+ [/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, "$1f"],
247
+ [/ies$/i, "y"],
248
+ [/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i, "$1ie"],
249
+ [/\b(mon|smil)ies$/i, "$1ey"],
250
+ [/\b((?:tit)?m|l)ice$/i, "$1ouse"],
251
+ [/(seraph|cherub)im$/i, "$1"],
252
+ [/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i, "$1"],
253
+ [/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i, "$1sis"],
254
+ [/(movie|twelve|abuse|e[mn]u)s$/i, "$1"],
255
+ [/(test)(?:is|es)$/i, "$1is"],
256
+ [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, "$1us"],
257
+ [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i, "$1um"],
258
+ [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i, "$1on"],
259
+ [/(alumn|alg|vertebr)ae$/i, "$1a"],
260
+ [/(cod|mur|sil|vert|ind)ices$/i, "$1ex"],
261
+ [/(matr|append)ices$/i, "$1ix"],
262
+ [/(pe)(rson|ople)$/i, "$1rson"],
263
+ [/(child)ren$/i, "$1"],
264
+ [/(eau)x?$/i, "$1"],
265
+ [/men$/i, "man"]
266
+ ].forEach(function(rule) {
267
+ return pluralize2.addSingularRule(rule[0], rule[1]);
268
+ });
269
+ [
270
+ // Singular words with no plurals.
271
+ "adulthood",
272
+ "advice",
273
+ "agenda",
274
+ "aid",
275
+ "aircraft",
276
+ "alcohol",
277
+ "ammo",
278
+ "analytics",
279
+ "anime",
280
+ "athletics",
281
+ "audio",
282
+ "bison",
283
+ "blood",
284
+ "bream",
285
+ "buffalo",
286
+ "butter",
287
+ "carp",
288
+ "cash",
289
+ "chassis",
290
+ "chess",
291
+ "clothing",
292
+ "cod",
293
+ "commerce",
294
+ "cooperation",
295
+ "corps",
296
+ "debris",
297
+ "diabetes",
298
+ "digestion",
299
+ "elk",
300
+ "energy",
301
+ "equipment",
302
+ "excretion",
303
+ "expertise",
304
+ "firmware",
305
+ "flounder",
306
+ "fun",
307
+ "gallows",
308
+ "garbage",
309
+ "graffiti",
310
+ "hardware",
311
+ "headquarters",
312
+ "health",
313
+ "herpes",
314
+ "highjinks",
315
+ "homework",
316
+ "housework",
317
+ "information",
318
+ "jeans",
319
+ "justice",
320
+ "kudos",
321
+ "labour",
322
+ "literature",
323
+ "machinery",
324
+ "mackerel",
325
+ "mail",
326
+ "media",
327
+ "mews",
328
+ "moose",
329
+ "music",
330
+ "mud",
331
+ "manga",
332
+ "news",
333
+ "only",
334
+ "personnel",
335
+ "pike",
336
+ "plankton",
337
+ "pliers",
338
+ "police",
339
+ "pollution",
340
+ "premises",
341
+ "rain",
342
+ "research",
343
+ "rice",
344
+ "salmon",
345
+ "scissors",
346
+ "series",
347
+ "sewage",
348
+ "shambles",
349
+ "shrimp",
350
+ "software",
351
+ "species",
352
+ "staff",
353
+ "swine",
354
+ "tennis",
355
+ "traffic",
356
+ "transportation",
357
+ "trout",
358
+ "tuna",
359
+ "wealth",
360
+ "welfare",
361
+ "whiting",
362
+ "wildebeest",
363
+ "wildlife",
364
+ "you",
365
+ /pok[eé]mon$/i,
366
+ // Regexes.
367
+ /[^aeiou]ese$/i,
368
+ // "chinese", "japanese"
369
+ /deer$/i,
370
+ // "deer", "reindeer"
371
+ /fish$/i,
372
+ // "fish", "blowfish", "angelfish"
373
+ /measles$/i,
374
+ /o[iu]s$/i,
375
+ // "carnivorous"
376
+ /pox$/i,
377
+ // "chickpox", "smallpox"
378
+ /sheep$/i
379
+ ].forEach(pluralize2.addUncountableRule);
380
+ return pluralize2;
381
+ });
382
+ }
383
+ });
384
+
30
385
  // src/index.ts
31
386
  var index_exports = {};
32
387
  __export(index_exports, {
@@ -70,6 +425,7 @@ __export(index_exports, {
70
425
  useQuill: () => useQuill,
71
426
  useReportBuilder: () => useReportBuilder,
72
427
  useReports: () => useReports,
428
+ useTenants: () => useTenants,
73
429
  useVirtualTables: () => useVirtualTables
74
430
  });
75
431
  module.exports = __toCommonJS(index_exports);
@@ -1379,6 +1735,7 @@ var DashboardFilterType = /* @__PURE__ */ ((DashboardFilterType4) => {
1379
1735
  DashboardFilterType4["Select"] = "select";
1380
1736
  DashboardFilterType4["MultiSelect"] = "multiselect";
1381
1737
  DashboardFilterType4["Date"] = "date";
1738
+ DashboardFilterType4["Tenant"] = "tenant";
1382
1739
  return DashboardFilterType4;
1383
1740
  })(DashboardFilterType || {});
1384
1741
  var convertCustomFilter = (filter) => {
@@ -1632,6 +1989,16 @@ var convertInternalDashboardFilterToDashboardFilter = (filter) => {
1632
1989
  },
1633
1990
  options
1634
1991
  };
1992
+ } else if (filter.filterType === "tenant" /* Tenant */) {
1993
+ return {
1994
+ label: filter.label,
1995
+ type: "tenant" /* Tenant */,
1996
+ value: filter.multiSelect ? filter.values ?? [] : filter.values?.[0] ?? null,
1997
+ options: (filter.options ?? []).map((opt) => ({
1998
+ label: opt.label,
1999
+ value: opt.value
2000
+ }))
2001
+ };
1635
2002
  }
1636
2003
  throw new Error(
1637
2004
  "Unknown InternalDashboardFilterType: " + filter.filterType
@@ -17496,7 +17863,7 @@ async function generatePivotWithSQL({
17496
17863
  if (!itemQuery) {
17497
17864
  throw Error("No item query found in report");
17498
17865
  }
17499
- sqlQuery = pivotQuery ?? generatePivotQuery(
17866
+ sqlQuery = generatePivotQuery(
17500
17867
  pivot,
17501
17868
  itemQuery,
17502
17869
  databaseType,
@@ -18814,10 +19181,15 @@ async function getPivotTable(report, dashboardFilters, dashboardName, getToken,
18814
19181
  });
18815
19182
  }
18816
19183
  }
19184
+ const pivotQuery = generatePivotQuery(
19185
+ pivot,
19186
+ report.itemQuery?.[0],
19187
+ client.databaseType
19188
+ );
18817
19189
  return {
18818
19190
  rows: [],
18819
19191
  rowCount: 0,
18820
- pivotQuery: "",
19192
+ pivotQuery: pivotQuery ?? "",
18821
19193
  columns
18822
19194
  };
18823
19195
  }
@@ -21298,7 +21670,19 @@ var DashboardFiltersContext = (0, import_react.createContext)({
21298
21670
  loadFiltersForDashboard: async () => {
21299
21671
  }
21300
21672
  });
21301
- var TenantContext = (0, import_react.createContext)({});
21673
+ var TenantContext = (0, import_react.createContext)({
21674
+ childTenantMappings: {},
21675
+ viewerTenants: {},
21676
+ viewerTenantsByOwner: {},
21677
+ isLoadingMappedTenants: false,
21678
+ isLoadingViewerTenants: false,
21679
+ fetchViewerTenantsForDashboard: async () => {
21680
+ },
21681
+ fetchMappedTenantsForDashboard: async () => {
21682
+ },
21683
+ getMappedTenantsForDashboard: async () => void 0,
21684
+ getViewerTenantsByOwner: async () => []
21685
+ });
21302
21686
  var FetchContext = (0, import_react.createContext)({
21303
21687
  getToken: async () => "",
21304
21688
  quillFetchWithToken: async () => ({ data: null })
@@ -21388,6 +21772,15 @@ var ContextProvider = ({
21388
21772
  const fetchSchemaProcessId = (0, import_react.useRef)(0);
21389
21773
  const currentTenant = (0, import_react.useRef)(null);
21390
21774
  const currentPublicKey = (0, import_react.useRef)(null);
21775
+ const [childTenantMappings, setChildTenantMappings] = (0, import_react.useState)({});
21776
+ const [viewerTenants, setViewerTenants] = (0, import_react.useState)({});
21777
+ const [viewerTenantsByOwner, setViewerTenantsByOwner] = (0, import_react.useState)({});
21778
+ const [isLoadingMappedTenants, setIsLoadingMappedTenants] = (0, import_react.useState)(false);
21779
+ const [isLoadingViewerTenants, setIsLoadingViewerTenants] = (0, import_react.useState)(false);
21780
+ const prevTenants = (0, import_react.useRef)(null);
21781
+ const viewerTenantsRequests = (0, import_react.useRef)(/* @__PURE__ */ new Set());
21782
+ const viewerTenantsByOwnerRequests = (0, import_react.useRef)(/* @__PURE__ */ new Set());
21783
+ const mappedTenantsRequests = (0, import_react.useRef)(/* @__PURE__ */ new Set());
21391
21784
  const loadDashboardProcessId = (0, import_react.useRef)({});
21392
21785
  (0, import_react.useEffect)(() => {
21393
21786
  if (!theme) {
@@ -21736,7 +22129,7 @@ var ContextProvider = ({
21736
22129
  });
21737
22130
  await Promise.allSettled(
21738
22131
  filters.map(async (filter) => {
21739
- if (filter.filterType !== "string") {
22132
+ if (filter.filterType === "date_range") {
21740
22133
  dashboardFiltersDispatch({
21741
22134
  type: "UPDATE_DASHBOARD_FILTER",
21742
22135
  dashboardName,
@@ -21760,6 +22153,10 @@ var ContextProvider = ({
21760
22153
  });
21761
22154
  return null;
21762
22155
  }
22156
+ if (filter.filterType === "tenant") {
22157
+ await fetchTenantFilterOptions(dashboardName, filter);
22158
+ return null;
22159
+ }
21763
22160
  const filterOptionsAbortController = new AbortController();
21764
22161
  filterOptionsAbortControllers.current.add(filterOptionsAbortController);
21765
22162
  try {
@@ -22121,7 +22518,8 @@ var ContextProvider = ({
22121
22518
  },
22122
22519
  task: "dashboards",
22123
22520
  metadata: {
22124
- clientId: publicKey2
22521
+ clientId: publicKey2,
22522
+ tenants
22125
22523
  // getSections: true, // skip fetching reports since 'dashboard' always does anyway
22126
22524
  },
22127
22525
  abortSignal: fetchDashboardsAbortController.current.signal,
@@ -22210,6 +22608,14 @@ var ContextProvider = ({
22210
22608
  loading: true
22211
22609
  };
22212
22610
  });
22611
+ dashboard2.tenantFilters?.forEach(
22612
+ (filter) => {
22613
+ acc[dashboard2.name][filter.label] = {
22614
+ filter: { ...filter, options: void 0 },
22615
+ loading: true
22616
+ };
22617
+ }
22618
+ );
22213
22619
  return acc;
22214
22620
  }, {})
22215
22621
  });
@@ -22285,6 +22691,180 @@ var ContextProvider = ({
22285
22691
  return { error: "Failed to fetch data" };
22286
22692
  }
22287
22693
  }
22694
+ const getDashboardViewerTenants = async (dashboardName) => {
22695
+ if (!populatedClient) {
22696
+ return [];
22697
+ }
22698
+ const { data } = await quillFetchWithToken({
22699
+ client: populatedClient,
22700
+ task: "viewer-tenants",
22701
+ metadata: {
22702
+ dashboardName
22703
+ }
22704
+ });
22705
+ return data?.viewerTenants || [];
22706
+ };
22707
+ const getOwnerViewerTenants = async (ownerTenant) => {
22708
+ if (!populatedClient) {
22709
+ return [];
22710
+ }
22711
+ const { data } = await quillFetchWithToken({
22712
+ client: populatedClient,
22713
+ task: "viewer-tenants-by-owner",
22714
+ metadata: {
22715
+ tenantField: ownerTenant
22716
+ }
22717
+ });
22718
+ return data?.viewerTenants || [];
22719
+ };
22720
+ const getMappedTenants = async (tenantsParam, dashboardName) => {
22721
+ if (!populatedClient) {
22722
+ return {};
22723
+ }
22724
+ const { data, queries } = await quillFetchWithToken({
22725
+ client: populatedClient,
22726
+ task: "mapped-tenants",
22727
+ metadata: {
22728
+ tenants: tenantsParam,
22729
+ dashboardName
22730
+ }
22731
+ });
22732
+ const childTenants = data.queryOrder;
22733
+ const queryResults = queries.queryResults.map((result) => {
22734
+ return result?.rows?.map((row) => ({
22735
+ value: row["flag"],
22736
+ label: row["label"]
22737
+ })) ?? null;
22738
+ });
22739
+ const mappedTenants = {};
22740
+ await Promise.all(
22741
+ childTenants.map(
22742
+ async (tenant, index) => {
22743
+ mappedTenants[tenant.tenantField] = queryResults[index];
22744
+ }
22745
+ )
22746
+ );
22747
+ return mappedTenants;
22748
+ };
22749
+ const fetchViewerTenantsForDashboard = (0, import_react.useCallback)(
22750
+ async (dashboardName) => {
22751
+ if (!populatedClient) return;
22752
+ if (viewerTenantsRequests.current.has(dashboardName)) {
22753
+ return;
22754
+ }
22755
+ if (viewerTenants[dashboardName]) {
22756
+ return;
22757
+ }
22758
+ viewerTenantsRequests.current.add(dashboardName);
22759
+ setIsLoadingViewerTenants(true);
22760
+ try {
22761
+ const viewerTenantsData = await getDashboardViewerTenants(dashboardName);
22762
+ setViewerTenants((prev) => ({
22763
+ ...prev,
22764
+ [dashboardName]: viewerTenantsData
22765
+ }));
22766
+ } catch (error) {
22767
+ console.error("Error fetching viewer tenants:", error);
22768
+ } finally {
22769
+ viewerTenantsRequests.current.delete(dashboardName);
22770
+ setIsLoadingViewerTenants(false);
22771
+ }
22772
+ },
22773
+ [populatedClient]
22774
+ );
22775
+ const fetchMappedTenantsForDashboard = async (dashboardName) => {
22776
+ await getMappedTenantsForDashboard(dashboardName);
22777
+ return;
22778
+ };
22779
+ const getMappedTenantsForDashboard = (0, import_react.useCallback)(
22780
+ async (dashboardName) => {
22781
+ if (!populatedClient || !tenants) return void 0;
22782
+ const tenantsChanged = !(0, import_fast_deep_equal.default)(prevTenants.current, tenants);
22783
+ if (childTenantMappings[dashboardName] && !tenantsChanged) {
22784
+ return childTenantMappings[dashboardName];
22785
+ }
22786
+ if (mappedTenantsRequests.current.has(dashboardName) && !tenantsChanged) {
22787
+ return new Promise((resolve) => {
22788
+ const checkInterval = setInterval(() => {
22789
+ if (!mappedTenantsRequests.current.has(dashboardName)) {
22790
+ clearInterval(checkInterval);
22791
+ resolve(childTenantMappings[dashboardName]);
22792
+ }
22793
+ }, 100);
22794
+ });
22795
+ }
22796
+ prevTenants.current = tenants;
22797
+ mappedTenantsRequests.current.add(dashboardName);
22798
+ setIsLoadingMappedTenants(true);
22799
+ try {
22800
+ const mappedTenants = await getMappedTenants(tenants, dashboardName);
22801
+ setChildTenantMappings((prev) => ({
22802
+ ...prev,
22803
+ [dashboardName]: mappedTenants
22804
+ }));
22805
+ return mappedTenants;
22806
+ } catch (error) {
22807
+ console.error("Error fetching mapped tenants:", error);
22808
+ setChildTenantMappings((prev) => ({
22809
+ ...prev,
22810
+ [dashboardName]: {}
22811
+ }));
22812
+ return void 0;
22813
+ } finally {
22814
+ mappedTenantsRequests.current.delete(dashboardName);
22815
+ setIsLoadingMappedTenants(false);
22816
+ }
22817
+ },
22818
+ [populatedClient, tenants, childTenantMappings]
22819
+ );
22820
+ const getViewerTenantsByOwner = (0, import_react.useCallback)(
22821
+ async (ownerTenant) => {
22822
+ if (!populatedClient) return [];
22823
+ if (viewerTenantsByOwner[ownerTenant]) {
22824
+ return viewerTenantsByOwner[ownerTenant];
22825
+ }
22826
+ if (viewerTenantsByOwnerRequests.current.has(ownerTenant)) {
22827
+ return new Promise((resolve) => {
22828
+ const checkInterval = setInterval(() => {
22829
+ if (!viewerTenantsByOwnerRequests.current.has(ownerTenant)) {
22830
+ clearInterval(checkInterval);
22831
+ resolve(viewerTenantsByOwner[ownerTenant] || []);
22832
+ }
22833
+ }, 100);
22834
+ });
22835
+ }
22836
+ viewerTenantsByOwnerRequests.current.add(ownerTenant);
22837
+ setIsLoadingViewerTenants(true);
22838
+ try {
22839
+ const viewerTenantsData = await getOwnerViewerTenants(ownerTenant);
22840
+ setViewerTenantsByOwner((prev) => ({
22841
+ ...prev,
22842
+ [ownerTenant]: viewerTenantsData
22843
+ }));
22844
+ return viewerTenantsData;
22845
+ } catch (error) {
22846
+ console.error("Error fetching viewer tenants by owner:", error);
22847
+ return [];
22848
+ } finally {
22849
+ viewerTenantsByOwnerRequests.current.delete(ownerTenant);
22850
+ setIsLoadingViewerTenants(false);
22851
+ }
22852
+ },
22853
+ [populatedClient, viewerTenantsByOwner]
22854
+ );
22855
+ const fetchTenantFilterOptions = async (dashboardName, filter) => {
22856
+ const mappings = await getMappedTenantsForDashboard(dashboardName);
22857
+ const options = mappings?.[filter.field] ?? [];
22858
+ dashboardFiltersDispatch({
22859
+ type: "UPDATE_DASHBOARD_FILTER",
22860
+ dashboardName,
22861
+ filterName: filter.label,
22862
+ data: {
22863
+ filter: { ...filter, options },
22864
+ loading: false
22865
+ }
22866
+ });
22867
+ };
22288
22868
  (0, import_react.useEffect)(() => {
22289
22869
  async function updateClientAndSchema(publicKey2) {
22290
22870
  if (!publicKey2 || populatedClient?.clientId === publicKey2 && populatedClient?.allTenantTypes?.length)
@@ -22443,7 +23023,17 @@ var ContextProvider = ({
22443
23023
  {
22444
23024
  value: {
22445
23025
  tenants: populatedClient?.currentTenants ?? tenants,
22446
- flags: populatedClient?.currentFlags ?? flags
23026
+ flags: populatedClient?.currentFlags ?? flags,
23027
+ childTenantMappings,
23028
+ viewerTenants,
23029
+ viewerTenantsByOwner,
23030
+ isLoadingMappedTenants,
23031
+ isLoadingViewerTenants,
23032
+ fetchViewerTenantsForDashboard,
23033
+ // fetchViewerTenantsByOwner,
23034
+ fetchMappedTenantsForDashboard,
23035
+ getMappedTenantsForDashboard,
23036
+ getViewerTenantsByOwner
22447
23037
  },
22448
23038
  children
22449
23039
  }
@@ -22531,7 +23121,7 @@ var useDashboardInternal = (dashboardName, customFilters) => {
22531
23121
  );
22532
23122
  if (!fetchFromServer && Object.keys(dashboardFilters[dashboardName] ?? {}).length && // there exists no non date filter that has undefined options
22533
23123
  Object.values(dashboardFilters[dashboardName] ?? {}).every(
22534
- (filter) => filter.filter.filterType === "date_range" /* Date */ || filter.filter.options
23124
+ (filter) => filter.filter.filterType === "date_range" /* Date */ || filter.filter.filterType === "tenant" /* Tenant */ || filter.filter.options
22535
23125
  )) {
22536
23126
  return;
22537
23127
  }
@@ -22548,6 +23138,9 @@ var useDashboardInternal = (dashboardName, customFilters) => {
22548
23138
  ...updatedDashboard?.filters?.map((filter) => ({
22549
23139
  ...filter,
22550
23140
  query: void 0
23141
+ })) ?? [],
23142
+ ...updatedDashboard?.tenantFilters?.map((filter) => ({
23143
+ ...filter
22551
23144
  })) ?? []
22552
23145
  ],
22553
23146
  void 0,
@@ -22738,8 +23331,10 @@ var useDashboards = () => {
22738
23331
  (a, b) => (a.createdAt?.getTime() ?? 0) - (b.createdAt?.getTime() ?? 0)
22739
23332
  );
22740
23333
  }, [dashboardConfig]);
23334
+ const { getMappedTenantsForDashboard } = (0, import_react2.useContext)(TenantContext);
22741
23335
  const createDashboard = async ({
22742
23336
  name: name2,
23337
+ tenantFilters,
22743
23338
  filters,
22744
23339
  dateFilter,
22745
23340
  dashboardOwners
@@ -22756,6 +23351,7 @@ var useDashboards = () => {
22756
23351
  tenantKeys: dashboardOwners,
22757
23352
  dashboardId: name2,
22758
23353
  name: name2,
23354
+ allTenantFilters: tenantFilters ?? [],
22759
23355
  filters,
22760
23356
  dateFilter
22761
23357
  },
@@ -22764,6 +23360,7 @@ var useDashboards = () => {
22764
23360
  });
22765
23361
  const body = {
22766
23362
  newDashboardName: name2.trim(),
23363
+ tenantFilters,
22767
23364
  filters,
22768
23365
  dateFilter,
22769
23366
  name: name2.trim(),
@@ -22816,6 +23413,7 @@ var useDashboards = () => {
22816
23413
  const updateDashboard = async (name2, {
22817
23414
  newName,
22818
23415
  filters,
23416
+ tenantFilters,
22819
23417
  dateFilter,
22820
23418
  customFilters,
22821
23419
  tenantKeys
@@ -22837,6 +23435,7 @@ var useDashboards = () => {
22837
23435
  const body = {
22838
23436
  newDashboardName: newName.trim(),
22839
23437
  filters,
23438
+ tenantFilters,
22840
23439
  dateFilter: dateFilter ?? null,
22841
23440
  name: name2.trim(),
22842
23441
  task: "edit-dashboard",
@@ -22866,6 +23465,7 @@ var useDashboards = () => {
22866
23465
  config: {
22867
23466
  ...dashboard,
22868
23467
  ...updated.data.dashboard,
23468
+ allTenantFilters: tenantFilters ?? [],
22869
23469
  dateFilter: updated.data.dashboard.dateFilter ? {
22870
23470
  ...updated.data.dashboard.dateFilter,
22871
23471
  presetOptions: updated.data.dashboard.dateFilter.presetOptions?.map(
@@ -22960,6 +23560,8 @@ var useDashboards = () => {
22960
23560
  endDate: !range.endDate || range.endDate instanceof Date ? range.endDate : new Date(range.endDate)
22961
23561
  // when range.endDate is a string
22962
23562
  } : void 0;
23563
+ const mappedTenants = await getMappedTenantsForDashboard(newName);
23564
+ const mappedTenantKeys = Object.keys(mappedTenants ?? {});
22963
23565
  const newFilters = [
22964
23566
  ...updatedDateFilter ? [updatedDateFilter] : [],
22965
23567
  ...updated.data.dashboard.filters.map(
@@ -22969,14 +23571,22 @@ var useDashboards = () => {
22969
23571
  values: oldFilters?.[f.label]?.filter?.values,
22970
23572
  operator: oldFilters?.[f.label]?.filter?.operator
22971
23573
  })
22972
- ) ?? []
23574
+ ) ?? [],
23575
+ ...(updated.data.dashboard.tenantFilters?.map(
23576
+ (f) => ({
23577
+ ...f,
23578
+ values: oldFilters?.[f.label]?.filter?.values
23579
+ })
23580
+ ) ?? []).filter((filter) => {
23581
+ return mappedTenantKeys.includes(filter.field);
23582
+ })
22973
23583
  ].map((f) => {
22974
23584
  if (f.filterType === "date_range" /* Date */) {
22975
23585
  return {
22976
23586
  ...f,
22977
- startDate: dashboardFilters[name2]?.[f.label]?.filter?.startDate,
22978
- endDate: dashboardFilters[name2]?.[f.label]?.filter?.endDate,
22979
- preset: dashboardFilters[name2]?.[f.label]?.filter?.preset
23587
+ startDate: dashboardFilters[name2]?.[f.label]?.filter?.startDate ?? f.startDate,
23588
+ endDate: dashboardFilters[name2]?.[f.label]?.filter?.endDate ?? f.endDate,
23589
+ preset: dashboardFilters[name2]?.[f.label]?.filter?.preset ?? f.preset
22980
23590
  };
22981
23591
  } else {
22982
23592
  return {
@@ -23118,6 +23728,20 @@ var useDashboard = (dashboardName) => {
23118
23728
  endDate: value.endDate
23119
23729
  };
23120
23730
  }
23731
+ } else if (f.filterType === "tenant" /* Tenant */) {
23732
+ const value = update.value;
23733
+ let values;
23734
+ if (Array.isArray(value)) {
23735
+ values = value;
23736
+ } else if (typeof value === "string") {
23737
+ values = [value];
23738
+ } else {
23739
+ values = [];
23740
+ }
23741
+ return {
23742
+ ...f,
23743
+ values
23744
+ };
23121
23745
  }
23122
23746
  return f;
23123
23747
  });
@@ -23577,7 +24201,7 @@ var useExport = (reportId, {
23577
24201
  } else {
23578
24202
  const rows = report.rows;
23579
24203
  for (let i = 0; i < rows.length; i += maximumRowsPerPage) {
23580
- const remainingRows = (rows.length - i) * maximumRowsPerPage;
24204
+ const remainingRows = rows.length - i;
23581
24205
  const availableSpace = maximumRowsPerPage - currentCount;
23582
24206
  const rowsToAdd = Math.min(remainingRows, availableSpace);
23583
24207
  currentCount += rowsToAdd;
@@ -25139,7 +25763,7 @@ var MemoizedButton = ({
25139
25763
  }) => {
25140
25764
  const [theme] = (0, import_react11.useContext)(ThemeContext);
25141
25765
  return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
25142
- QuillToolTip,
25766
+ QuillToolTipPortal,
25143
25767
  {
25144
25768
  enabled: !!tooltipText && tooltipText !== "",
25145
25769
  text: tooltipText ?? "",
@@ -26376,6 +27000,140 @@ var QuillToolTip = ({
26376
27000
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "tooltip-text", style: { ...textStyle }, children: text })
26377
27001
  ] }) : children;
26378
27002
  };
27003
+ var QuillToolTipPortal = ({
27004
+ children,
27005
+ text,
27006
+ enabled = true,
27007
+ containerStyle = {},
27008
+ textStyle = {},
27009
+ mirror = false
27010
+ }) => {
27011
+ const [theme] = (0, import_react11.useContext)(ThemeContext);
27012
+ const [isOpen, setIsOpen] = (0, import_react11.useState)(false);
27013
+ const tooltipRef = (0, import_react11.useRef)(null);
27014
+ const triggerRef = (0, import_react11.useRef)(null);
27015
+ const [tooltipPosition, setTooltipPosition] = (0, import_react11.useState)(void 0);
27016
+ const updatePosition = () => {
27017
+ if (triggerRef.current && tooltipRef.current) {
27018
+ const rect = triggerRef.current.getBoundingClientRect();
27019
+ const tooltipRect = tooltipRef.current.getBoundingClientRect();
27020
+ const viewportWidth = window.innerWidth;
27021
+ let top = rect.top + window.scrollY - tooltipRect.height - 8;
27022
+ let left = rect.left + window.scrollX;
27023
+ if (!mirror) {
27024
+ left = rect.left + rect.width / 2 - tooltipRect.width / 2 + window.scrollX;
27025
+ } else {
27026
+ left = rect.right - tooltipRect.width + window.scrollX;
27027
+ }
27028
+ if (left + tooltipRect.width > viewportWidth) {
27029
+ left = viewportWidth - tooltipRect.width - 16;
27030
+ }
27031
+ if (left < 16) {
27032
+ left = 16;
27033
+ }
27034
+ if (top < window.scrollY + 16) {
27035
+ top = rect.bottom + window.scrollY + 8;
27036
+ }
27037
+ setTooltipPosition({ top, left });
27038
+ }
27039
+ };
27040
+ (0, import_react11.useEffect)(() => {
27041
+ if (isOpen) {
27042
+ const timer2 = setTimeout(() => {
27043
+ updatePosition();
27044
+ }, 0);
27045
+ window.addEventListener("resize", updatePosition, { passive: true });
27046
+ window.addEventListener("scroll", updatePosition, { passive: true });
27047
+ return () => {
27048
+ clearTimeout(timer2);
27049
+ window.removeEventListener("resize", updatePosition);
27050
+ window.removeEventListener("scroll", updatePosition);
27051
+ };
27052
+ }
27053
+ }, [isOpen]);
27054
+ if (!enabled) {
27055
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_jsx_runtime26.Fragment, { children });
27056
+ }
27057
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
27058
+ "div",
27059
+ {
27060
+ ref: triggerRef,
27061
+ style: {
27062
+ display: "inline-block",
27063
+ position: "relative",
27064
+ ...containerStyle
27065
+ },
27066
+ onMouseEnter: () => setIsOpen(true),
27067
+ onMouseLeave: () => setIsOpen(false),
27068
+ children: [
27069
+ children,
27070
+ isOpen && (0, import_react_dom2.createPortal)(
27071
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
27072
+ "div",
27073
+ {
27074
+ ref: tooltipRef,
27075
+ style: {
27076
+ visibility: tooltipPosition ? "visible" : "hidden",
27077
+ position: "absolute",
27078
+ top: `${tooltipPosition?.top ?? 0}px`,
27079
+ left: `${tooltipPosition?.left ?? 0}px`,
27080
+ backgroundColor: "#ffffff",
27081
+ color: "#212121",
27082
+ textAlign: "center",
27083
+ borderRadius: 5,
27084
+ zIndex: 100,
27085
+ padding: 10,
27086
+ fontFamily: theme?.fontFamily,
27087
+ fontWeight: 600,
27088
+ fontSize: "small",
27089
+ whiteSpace: "nowrap",
27090
+ borderWidth: 1,
27091
+ borderStyle: "solid",
27092
+ borderColor: "#e7e7e7",
27093
+ boxShadow: "0px 1px 8px rgba(0, 0, 0, 0.07)",
27094
+ ...textStyle
27095
+ },
27096
+ children: [
27097
+ text,
27098
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
27099
+ "div",
27100
+ {
27101
+ style: {
27102
+ position: "absolute",
27103
+ top: "100%",
27104
+ left: "50%",
27105
+ marginLeft: -6,
27106
+ borderWidth: 6,
27107
+ borderStyle: "solid",
27108
+ borderColor: "transparent",
27109
+ borderTopColor: "#e7e7e7"
27110
+ }
27111
+ }
27112
+ ),
27113
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
27114
+ "div",
27115
+ {
27116
+ style: {
27117
+ position: "absolute",
27118
+ top: "100%",
27119
+ left: "50%",
27120
+ marginLeft: -5,
27121
+ borderWidth: 5,
27122
+ borderStyle: "solid",
27123
+ borderColor: "transparent",
27124
+ borderTopColor: "#ffffff"
27125
+ }
27126
+ }
27127
+ )
27128
+ ]
27129
+ }
27130
+ ),
27131
+ document.body
27132
+ )
27133
+ ]
27134
+ }
27135
+ );
27136
+ };
26379
27137
  var QuillChartBuilderCheckboxComponent = ({
26380
27138
  isChecked,
26381
27139
  label,
@@ -29428,7 +30186,7 @@ function QuillMultiSelectComponentWithCombo({
29428
30186
  );
29429
30187
  const potentialOptions = (0, import_react20.useMemo)(() => {
29430
30188
  return value.filter((opt) => !optionValues.has(opt ?? "")).map((opt) => ({
29431
- label: opt === "" ? "-" : opt ?? "-",
30189
+ label: opt === "" ? "-" : opt?.toString() ?? "-",
29432
30190
  value: opt ?? ""
29433
30191
  })).concat(options);
29434
30192
  }, [value, options]);
@@ -29445,7 +30203,9 @@ function QuillMultiSelectComponentWithCombo({
29445
30203
  if (matchingOptions.length === options.length && allSelectedLabel) {
29446
30204
  return allSelectedLabel;
29447
30205
  }
29448
- return matchingOptions.map((elem) => elem.label ?? "-").join(", ");
30206
+ return matchingOptions.map(
30207
+ (elem) => elem.label ?? "-"
30208
+ ).join(", ");
29449
30209
  }, [options, value]);
29450
30210
  const [selectAllCheckboxState, setSelectAllCheckboxState] = (0, import_react20.useState)(
29451
30211
  (() => {
@@ -30171,7 +30931,7 @@ function QuillSelectComponentWithCombo({
30171
30931
  textOverflow: "ellipsis",
30172
30932
  whiteSpace: "nowrap",
30173
30933
  overflow: "hidden",
30174
- fontWeight: value?.length || isLoading ? void 0 : 300
30934
+ fontWeight: value?.toString()?.length || isLoading ? void 0 : 300
30175
30935
  },
30176
30936
  children: selectedLabel
30177
30937
  }
@@ -30513,6 +31273,51 @@ function DashboardFilter2({
30513
31273
  ]
30514
31274
  }
30515
31275
  ) });
31276
+ } else if (filter.filterType === "tenant") {
31277
+ if (filter.multiSelect) {
31278
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
31279
+ QuillMultiSelectComponentWithCombo,
31280
+ {
31281
+ label: filter.label,
31282
+ value: filter.values ?? [],
31283
+ onChange: (e) => {
31284
+ if (Array.isArray(e.target.value) && e.target.value.length === 0) {
31285
+ onChangeFilter(filter, void 0);
31286
+ return;
31287
+ }
31288
+ onChangeFilter(filter, e.target.value);
31289
+ },
31290
+ options: [
31291
+ ...filter.options ? filter.options.map((elem) => ({
31292
+ label: elem.label,
31293
+ value: elem.value
31294
+ })) : []
31295
+ ],
31296
+ width: 200,
31297
+ isLoading,
31298
+ disabled
31299
+ }
31300
+ ) });
31301
+ }
31302
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
31303
+ QuillSelectComponentWithCombo,
31304
+ {
31305
+ label: filter.label,
31306
+ value: filter.values?.[0] ?? "",
31307
+ onChange: (e) => {
31308
+ onChangeFilter(filter, e.target.value);
31309
+ },
31310
+ options: [
31311
+ ...filter.options ? filter.options.map((elem) => ({
31312
+ label: elem.label,
31313
+ value: elem.value
31314
+ })) : []
31315
+ ],
31316
+ width: 200,
31317
+ isLoading,
31318
+ disabled
31319
+ }
31320
+ ) });
30516
31321
  }
30517
31322
  return null;
30518
31323
  }
@@ -33997,11 +34802,13 @@ function Chart({
33997
34802
  (0, import_react29.useEffect)(() => {
33998
34803
  setFilterValues(
33999
34804
  Object.values(reportFilters[reportId] ?? {}).reduce((acc, f) => {
34000
- acc[f.filter.label] = f.filter.filterType === "string" ? f.filter.stringFilterType === "multiselect" ? { values: f.filter.values, operator: "IN" } : { selectedValue: f.filter.selectedValue } : {
34805
+ acc[f.filter.label] = f.filter.filterType === "string" ? f.filter.stringFilterType === "multiselect" ? { values: f.filter.values, operator: "IN" } : { selectedValue: f.filter.selectedValue } : f.filter.filterType === "date_range" ? {
34001
34806
  startDate: f.filter.startDate,
34002
34807
  endDate: f.filter.endDate,
34003
34808
  preset: f.filter.preset,
34004
34809
  comparisonRange: f.filter.comparisonRange
34810
+ } : {
34811
+ values: f.filter.values
34005
34812
  };
34006
34813
  return acc;
34007
34814
  }, {})
@@ -34125,6 +34932,10 @@ function Chart({
34125
34932
  }
34126
34933
  };
34127
34934
  }
34935
+ } else if (filter.filterType === "tenant" /* Tenant */) {
34936
+ filterValue = {
34937
+ values: value ? Array.isArray(value) ? value : [value] : []
34938
+ };
34128
34939
  }
34129
34940
  setFilterValues((filterValues2) => ({
34130
34941
  ...filterValues2,
@@ -36771,11 +37582,13 @@ function Dashboard({
36771
37582
  (0, import_react37.useEffect)(() => {
36772
37583
  setFilterValues(
36773
37584
  Object.values(populatedDashboardFilters ?? {}).reduce((acc, f) => {
36774
- acc[f.label] = f.filterType === "string" ? f.stringFilterType === "multiselect" ? { values: f.values, operator: "IN" } : { selectedValue: f.selectedValue } : {
37585
+ acc[f.label] = f.filterType === "string" ? f.stringFilterType === "multiselect" ? { values: f.values, operator: "IN" } : { selectedValue: f.selectedValue } : f.filterType === "date_range" ? {
36775
37586
  startDate: f.startDate,
36776
37587
  endDate: f.endDate,
36777
37588
  preset: f.preset,
36778
37589
  comparisonRange: f.comparisonRange
37590
+ } : {
37591
+ values: f.values
36779
37592
  };
36780
37593
  return acc;
36781
37594
  }, {})
@@ -36920,6 +37733,10 @@ function Dashboard({
36920
37733
  }
36921
37734
  };
36922
37735
  }
37736
+ } else if (filter.filterType === "tenant" /* Tenant */) {
37737
+ filterValue = {
37738
+ values: value ? Array.isArray(value) ? value : [value] : []
37739
+ };
36923
37740
  }
36924
37741
  setFilterValues((filterValues2) => ({
36925
37742
  ...filterValues2,
@@ -40291,6 +41108,10 @@ function InternalChart({
40291
41108
  }
40292
41109
  };
40293
41110
  }
41111
+ } else if (filter.filterType === "tenant" /* Tenant */) {
41112
+ filterValue = {
41113
+ values: value ? Array.isArray(value) ? value : [value] : []
41114
+ };
40294
41115
  }
40295
41116
  setFilterValues((filterValues2) => ({
40296
41117
  ...filterValues2,
@@ -41112,6 +41933,7 @@ var ListboxTextInput2 = ({
41112
41933
  };
41113
41934
 
41114
41935
  // src/ChartBuilder.tsx
41936
+ var import_pluralize = __toESM(require_pluralize(), 1);
41115
41937
  var import_jsx_runtime65 = require("react/jsx-runtime");
41116
41938
  var CHART_TYPES = [
41117
41939
  "column",
@@ -41558,7 +42380,7 @@ function ChartBuilder({
41558
42380
  const validFilter = (0, import_react43.useMemo)(() => {
41559
42381
  return specificDashboardFilters.reduce(
41560
42382
  (acc, filter) => {
41561
- if (filter.filterType === "date_range") {
42383
+ if (filter.filterType === "date_range" || filter.filterType === "tenant") {
41562
42384
  acc[filter.label] = true;
41563
42385
  return acc;
41564
42386
  }
@@ -42701,6 +43523,30 @@ function ChartBuilder({
42701
43523
  setIsSubmitting(false);
42702
43524
  setTriggeredEditChart(false);
42703
43525
  };
43526
+ const memoizedTooltipText = (0, import_react43.useMemo)(() => {
43527
+ const getTooltipText = () => {
43528
+ if (formData.name === "") {
43529
+ return "Please enter a name for the chart";
43530
+ }
43531
+ if (formData.dashboardName === "") {
43532
+ return "Please select a dashboard";
43533
+ }
43534
+ if (formData.chartType === "") {
43535
+ return "Please select a chart type";
43536
+ }
43537
+ if (filterIssues.length !== 0) {
43538
+ return "Please fix the filter issues";
43539
+ }
43540
+ if (Object.values(validFilter).includes(false)) {
43541
+ return "Please fix the filter issues";
43542
+ }
43543
+ if (currentDashboard?.tenantKeys && customTenantAccess && Object.values(formFlags ?? {}).every((value) => !value.length)) {
43544
+ return "Please fix the tenant issues";
43545
+ }
43546
+ return "";
43547
+ };
43548
+ return getTooltipText();
43549
+ }, [formData, filterIssues, validFilter, formFlags, currentDashboard]);
42704
43550
  isHorizontalView = windowWidth < 1200 ? false : isHorizontalView;
42705
43551
  if (!schemaData.schema) {
42706
43552
  return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { children: "No schema" });
@@ -43790,7 +44636,7 @@ function ChartBuilder({
43790
44636
  })) ?? [],
43791
44637
  width: 200,
43792
44638
  emptyLabel: dashboardOwner.scope === "database" ? "No tags supplied" : void 0,
43793
- allSelectedLabel: "All " + dashboardOwner.name + "s",
44639
+ allSelectedLabel: "All " + (0, import_pluralize.default)(dashboardOwner.name),
43794
44640
  style: {
43795
44641
  display: customTenantAccess || containsCustomFields ? "inline" : "none",
43796
44642
  marginTop: -1,
@@ -43815,7 +44661,7 @@ function ChartBuilder({
43815
44661
  {}
43816
44662
  ) ?? {},
43817
44663
  width: 200,
43818
- allSelectedLabel: "All " + dashboardOwner.name + "s",
44664
+ allSelectedLabel: "All " + (0, import_pluralize.default)(dashboardOwner.name),
43819
44665
  style: {
43820
44666
  display: customTenantAccess || containsCustomFields ? "inline" : "none",
43821
44667
  marginTop: -1,
@@ -43920,7 +44766,7 @@ function ChartBuilder({
43920
44766
  gap: 6
43921
44767
  },
43922
44768
  children: specificDashboardFilters.filter((f) => {
43923
- return f.filterType !== "date_range";
44769
+ return f.filterType === "string";
43924
44770
  }).map((filter, index) => /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(ChartBuilderInputRowContainer, { children: [
43925
44771
  /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
43926
44772
  TextInputComponent,
@@ -44098,6 +44944,7 @@ function ChartBuilder({
44098
44944
  disabled: formData.name === "" || formData.dashboardName === "" || formData.chartType === "" || filterIssues.length !== 0 || Object.values(validFilter).includes(false) || currentDashboard?.tenantKeys && customTenantAccess && Object.values(formFlags ?? {}).every(
44099
44945
  (value) => !value.length
44100
44946
  ),
44947
+ tooltipText: memoizedTooltipText,
44101
44948
  label: buttonLabel ? buttonLabel : report ? "Save changes" : "Add to dashboard"
44102
44949
  }
44103
44950
  )
@@ -50066,7 +50913,8 @@ var SaveReport = ({
50066
50913
  reportBuilder,
50067
50914
  setIsOpen
50068
50915
  }
50069
- )
50916
+ ),
50917
+ submitButtonLabel
50070
50918
  }) => {
50071
50919
  return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { children: [
50072
50920
  SaveTrigger,
@@ -50109,7 +50957,7 @@ var SaveReport = ({
50109
50957
  FormContainer: ChartBuilderFormContainer,
50110
50958
  hideDateRangeFilter: true,
50111
50959
  hideDeleteButton: true,
50112
- buttonLabel: !!reportBuilder.reportId ? "Save changes" : "Add to dashboard",
50960
+ buttonLabel: submitButtonLabel ?? (!!reportBuilder.reportId ? "Save changes" : "Add to dashboard"),
50113
50961
  onClickChartElement,
50114
50962
  isEditingMode: true
50115
50963
  }
@@ -50208,7 +51056,8 @@ function ReportBuilder({
50208
51056
  hideCopySQL = true,
50209
51057
  isChartBuilderHorizontalView = true,
50210
51058
  onClickChartElement,
50211
- onRequestAddVirtualTable
51059
+ onRequestAddVirtualTable,
51060
+ submitButtonLabel
50212
51061
  }) {
50213
51062
  const [theme] = (0, import_react53.useContext)(ThemeContext);
50214
51063
  const parentRef = (0, import_react53.useRef)(null);
@@ -50596,7 +51445,7 @@ function ReportBuilder({
50596
51445
  setIsChartBuilderOpen(true);
50597
51446
  },
50598
51447
  disabled: !!errorMessage || !!pivotError || tableLoading || loading || !!unresolvedReportMessage,
50599
- label: reportId ? "Save changes" : "Add to dashboard",
51448
+ label: submitButtonLabel ?? (reportId ? "Save changes" : "Add to dashboard"),
50600
51449
  tooltipText: unresolvedReportMessage
50601
51450
  }
50602
51451
  )
@@ -50642,7 +51491,8 @@ function ReportBuilder({
50642
51491
  ErrorMessageComponent,
50643
51492
  PivotRowContainer,
50644
51493
  PivotColumnContainer,
50645
- onClickChartElement
51494
+ onClickChartElement,
51495
+ submitButtonLabel
50646
51496
  }
50647
51497
  ),
50648
51498
  isSaveQueryModalOpen && /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
@@ -50919,31 +51769,69 @@ function StaticChart({
50919
51769
  );
50920
51770
  }
50921
51771
 
50922
- // src/hooks/useQuill.ts
51772
+ // src/hooks/useTenants.ts
50923
51773
  var import_react55 = require("react");
51774
+ var useTenants = (dashboardName) => {
51775
+ const {
51776
+ tenants,
51777
+ flags,
51778
+ childTenantMappings,
51779
+ viewerTenants,
51780
+ isLoadingMappedTenants,
51781
+ isLoadingViewerTenants,
51782
+ fetchViewerTenantsForDashboard,
51783
+ fetchMappedTenantsForDashboard,
51784
+ getMappedTenantsForDashboard,
51785
+ getViewerTenantsByOwner
51786
+ } = (0, import_react55.useContext)(TenantContext);
51787
+ (0, import_react55.useEffect)(() => {
51788
+ if (dashboardName) {
51789
+ fetchViewerTenantsForDashboard(dashboardName);
51790
+ }
51791
+ }, [dashboardName, fetchViewerTenantsForDashboard]);
51792
+ (0, import_react55.useEffect)(() => {
51793
+ if (dashboardName) {
51794
+ fetchMappedTenantsForDashboard(dashboardName);
51795
+ }
51796
+ }, [dashboardName, fetchMappedTenantsForDashboard]);
51797
+ return {
51798
+ tenants,
51799
+ flags,
51800
+ childTenantMappings: dashboardName ? childTenantMappings[dashboardName] || {} : {},
51801
+ mappedTenants: dashboardName ? childTenantMappings[dashboardName] || {} : {},
51802
+ viewerTenants: dashboardName ? viewerTenants[dashboardName] || [] : [],
51803
+ isLoadingMappedTenants,
51804
+ isLoadingViewerTenants,
51805
+ getMappedTenantsForDashboard,
51806
+ getViewerTenantsByOwner
51807
+ };
51808
+ };
51809
+
51810
+ // src/hooks/useQuill.ts
51811
+ var import_react56 = require("react");
50924
51812
  var useQuill = (reportId, pagination) => {
50925
- const { reports, reportsDispatch, fetchIndividualReport } = (0, import_react55.useContext)(ReportsContext);
51813
+ const { reports, reportsDispatch, fetchIndividualReport } = (0, import_react56.useContext)(ReportsContext);
50926
51814
  const { allReportsById } = useAllReports();
50927
- const { getToken } = (0, import_react55.useContext)(FetchContext);
50928
- const dashboardReport = (0, import_react55.useMemo)(() => {
51815
+ const { getToken } = (0, import_react56.useContext)(FetchContext);
51816
+ const dashboardReport = (0, import_react56.useMemo)(() => {
50929
51817
  return allReportsById[reportId ?? ""];
50930
51818
  }, [allReportsById[reportId ?? ""]]);
50931
- const { dashboardFilters, dashboardCustomFilters } = (0, import_react55.useContext)(
51819
+ const { dashboardFilters, dashboardCustomFilters } = (0, import_react56.useContext)(
50932
51820
  DashboardFiltersContext
50933
51821
  );
50934
- const { reportFilters, customReportFilters, reportFiltersDispatch } = (0, import_react55.useContext)(ReportFiltersContext);
50935
- const specificReportFilters = (0, import_react55.useMemo)(() => {
51822
+ const { reportFilters, customReportFilters, reportFiltersDispatch } = (0, import_react56.useContext)(ReportFiltersContext);
51823
+ const specificReportFilters = (0, import_react56.useMemo)(() => {
50936
51824
  if (!reportId) return null;
50937
51825
  return Object.values(reportFilters[reportId] ?? []).map((f) => f.filter);
50938
51826
  }, [reportFilters, reportId]);
50939
- const [schemaData] = (0, import_react55.useContext)(SchemaDataContext);
50940
- const [client, isClientLoading] = (0, import_react55.useContext)(ClientContext);
50941
- const { tenants } = (0, import_react55.useContext)(TenantContext);
50942
- const { eventTracking } = (0, import_react55.useContext)(EventTrackingContext);
50943
- const [loading, setLoading] = (0, import_react55.useState)(true);
50944
- const [error, setError] = (0, import_react55.useState)(void 0);
50945
- const [previousPage, setPreviousPage] = (0, import_react55.useState)(0);
50946
- const processedReport = (0, import_react55.useMemo)(() => {
51827
+ const [schemaData] = (0, import_react56.useContext)(SchemaDataContext);
51828
+ const [client, isClientLoading] = (0, import_react56.useContext)(ClientContext);
51829
+ const { tenants } = (0, import_react56.useContext)(TenantContext);
51830
+ const { eventTracking } = (0, import_react56.useContext)(EventTrackingContext);
51831
+ const [loading, setLoading] = (0, import_react56.useState)(true);
51832
+ const [error, setError] = (0, import_react56.useState)(void 0);
51833
+ const [previousPage, setPreviousPage] = (0, import_react56.useState)(0);
51834
+ const processedReport = (0, import_react56.useMemo)(() => {
50947
51835
  return reportId && allReportsById[reportId] ? convertInternalReportToReport(
50948
51836
  mergeComparisonRange(allReportsById[reportId]),
50949
51837
  specificReportFilters ?? [],
@@ -50951,7 +51839,7 @@ var useQuill = (reportId, pagination) => {
50951
51839
  "useQuill"
50952
51840
  ) : void 0;
50953
51841
  }, [reportId, reportId && allReportsById[reportId], specificReportFilters]);
50954
- const [additionalProcessing, setAdditionProcessing] = (0, import_react55.useState)(
51842
+ const [additionalProcessing, setAdditionProcessing] = (0, import_react56.useState)(
50955
51843
  pagination ? {
50956
51844
  page: pagination
50957
51845
  } : void 0
@@ -51100,7 +51988,7 @@ var useQuill = (reportId, pagination) => {
51100
51988
  setLoading(false);
51101
51989
  }
51102
51990
  };
51103
- (0, import_react55.useEffect)(() => {
51991
+ (0, import_react56.useEffect)(() => {
51104
51992
  if (isClientLoading) return;
51105
51993
  if (reportId && specificReportFilters) {
51106
51994
  fetchReportHelper(reportId, {
@@ -51139,10 +52027,10 @@ var useQuill = (reportId, pagination) => {
51139
52027
  };
51140
52028
 
51141
52029
  // src/hooks/useFormat.ts
51142
- var import_react56 = require("react");
52030
+ var import_react57 = require("react");
51143
52031
  var useMemoizedRows = (reportId) => {
51144
52032
  const { data } = useQuill(reportId);
51145
- const formattedRows = (0, import_react56.useMemo)(() => {
52033
+ const formattedRows = (0, import_react57.useMemo)(() => {
51146
52034
  if (!data || !data.rows || !data.columns)
51147
52035
  return { rows: [], loading: true };
51148
52036
  return {
@@ -51166,7 +52054,7 @@ var useMemoizedRows = (reportId) => {
51166
52054
  };
51167
52055
 
51168
52056
  // src/hooks/useAskQuill.tsx
51169
- var import_react57 = require("react");
52057
+ var import_react58 = require("react");
51170
52058
  function convertColumnInternalToAskQuillColumn(columns) {
51171
52059
  return columns.map((column) => {
51172
52060
  let convertedFieldType = FieldType.String;
@@ -51190,13 +52078,13 @@ function convertColumnInternalToAskQuillColumn(columns) {
51190
52078
  });
51191
52079
  }
51192
52080
  var useAskQuill = (dashboardName) => {
51193
- const [client] = (0, import_react57.useContext)(ClientContext);
51194
- const [schemaData] = (0, import_react57.useContext)(SchemaDataContext);
51195
- const { tenants } = (0, import_react57.useContext)(TenantContext);
51196
- const { getToken } = (0, import_react57.useContext)(FetchContext);
51197
- const { eventTracking } = (0, import_react57.useContext)(EventTrackingContext);
51198
- const [astInfo, setAstInfo] = (0, import_react57.useState)(void 0);
51199
- const [data, setData] = (0, import_react57.useState)({
52081
+ const [client] = (0, import_react58.useContext)(ClientContext);
52082
+ const [schemaData] = (0, import_react58.useContext)(SchemaDataContext);
52083
+ const { tenants } = (0, import_react58.useContext)(TenantContext);
52084
+ const { getToken } = (0, import_react58.useContext)(FetchContext);
52085
+ const { eventTracking } = (0, import_react58.useContext)(EventTrackingContext);
52086
+ const [astInfo, setAstInfo] = (0, import_react58.useState)(void 0);
52087
+ const [data, setData] = (0, import_react58.useState)({
51200
52088
  rows: [],
51201
52089
  columns: [],
51202
52090
  pivot: null,
@@ -51206,9 +52094,9 @@ var useAskQuill = (dashboardName) => {
51206
52094
  pivotColumnFields: [],
51207
52095
  pivotValueFields: []
51208
52096
  });
51209
- const [loading, setLoading] = (0, import_react57.useState)(false);
51210
- const [error, setError] = (0, import_react57.useState)(void 0);
51211
- const [ask, setAsk] = (0, import_react57.useState)(
52097
+ const [loading, setLoading] = (0, import_react58.useState)(false);
52098
+ const [error, setError] = (0, import_react58.useState)(void 0);
52099
+ const [ask, setAsk] = (0, import_react58.useState)(
51212
52100
  async () => void 0
51213
52101
  );
51214
52102
  const askHelper = async (query) => {
@@ -51408,7 +52296,7 @@ var useAskQuill = (dashboardName) => {
51408
52296
  });
51409
52297
  setLoading(false);
51410
52298
  };
51411
- (0, import_react57.useEffect)(() => {
52299
+ (0, import_react58.useEffect)(() => {
51412
52300
  setAsk(() => askHelper);
51413
52301
  }, [schemaData.schema]);
51414
52302
  return {
@@ -51422,13 +52310,13 @@ var useAskQuill = (dashboardName) => {
51422
52310
  };
51423
52311
 
51424
52312
  // src/hooks/useVirtualTables.tsx
51425
- var import_react58 = require("react");
52313
+ var import_react59 = require("react");
51426
52314
  var useVirtualTables = () => {
51427
- const [schemaData, setSchemaData] = (0, import_react58.useContext)(SchemaDataContext);
51428
- const { tenants } = (0, import_react58.useContext)(TenantContext);
51429
- const { getToken, quillFetchWithToken } = (0, import_react58.useContext)(FetchContext);
51430
- const { eventTracking } = (0, import_react58.useContext)(EventTrackingContext);
51431
- const [loadingTables, setLoadingTables] = (0, import_react58.useState)({});
52315
+ const [schemaData, setSchemaData] = (0, import_react59.useContext)(SchemaDataContext);
52316
+ const { tenants } = (0, import_react59.useContext)(TenantContext);
52317
+ const { getToken, quillFetchWithToken } = (0, import_react59.useContext)(FetchContext);
52318
+ const { eventTracking } = (0, import_react59.useContext)(EventTrackingContext);
52319
+ const [loadingTables, setLoadingTables] = (0, import_react59.useState)({});
51432
52320
  const handleReload = async (client, caller) => {
51433
52321
  setSchemaData({ ...schemaData, isSchemaLoading: true });
51434
52322
  setLoadingTables(
@@ -51597,5 +52485,6 @@ var useVirtualTables = () => {
51597
52485
  useQuill,
51598
52486
  useReportBuilder,
51599
52487
  useReports,
52488
+ useTenants,
51600
52489
  useVirtualTables
51601
52490
  });