@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.js CHANGED
@@ -1,3 +1,387 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __commonJS = (cb, mod) => function __require2() {
14
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
+ // If the importer is in node compatibility mode or this is not an ESM
26
+ // file that has been converted to a CommonJS file using a Babel-
27
+ // compatible transform (i.e. "__esModule" has not been set), then set
28
+ // "default" to the CommonJS "module.exports" for node compatibility.
29
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
+ mod
31
+ ));
32
+
33
+ // ../../node_modules/pluralize/pluralize.js
34
+ var require_pluralize = __commonJS({
35
+ "../../node_modules/pluralize/pluralize.js"(exports, module) {
36
+ "use strict";
37
+ (function(root, pluralize2) {
38
+ if (typeof __require === "function" && typeof exports === "object" && typeof module === "object") {
39
+ module.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
+ })(exports, 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
+
1
385
  // src/Dashboard.tsx
2
386
  import {
3
387
  useContext as useContext20,
@@ -632,6 +1016,7 @@ async function fetchSqlQuery(ast, client, getToken, formData) {
632
1016
  import equal from "fast-deep-equal";
633
1017
  import {
634
1018
  createContext,
1019
+ useCallback,
635
1020
  useEffect,
636
1021
  useMemo,
637
1022
  useReducer,
@@ -1347,6 +1732,7 @@ var DashboardFilterType = /* @__PURE__ */ ((DashboardFilterType4) => {
1347
1732
  DashboardFilterType4["Select"] = "select";
1348
1733
  DashboardFilterType4["MultiSelect"] = "multiselect";
1349
1734
  DashboardFilterType4["Date"] = "date";
1735
+ DashboardFilterType4["Tenant"] = "tenant";
1350
1736
  return DashboardFilterType4;
1351
1737
  })(DashboardFilterType || {});
1352
1738
  var convertCustomFilter = (filter) => {
@@ -1600,6 +1986,16 @@ var convertInternalDashboardFilterToDashboardFilter = (filter) => {
1600
1986
  },
1601
1987
  options
1602
1988
  };
1989
+ } else if (filter.filterType === "tenant" /* Tenant */) {
1990
+ return {
1991
+ label: filter.label,
1992
+ type: "tenant" /* Tenant */,
1993
+ value: filter.multiSelect ? filter.values ?? [] : filter.values?.[0] ?? null,
1994
+ options: (filter.options ?? []).map((opt) => ({
1995
+ label: opt.label,
1996
+ value: opt.value
1997
+ }))
1998
+ };
1603
1999
  }
1604
2000
  throw new Error(
1605
2001
  "Unknown InternalDashboardFilterType: " + filter.filterType
@@ -17479,7 +17875,7 @@ async function generatePivotWithSQL({
17479
17875
  if (!itemQuery) {
17480
17876
  throw Error("No item query found in report");
17481
17877
  }
17482
- sqlQuery = pivotQuery ?? generatePivotQuery(
17878
+ sqlQuery = generatePivotQuery(
17483
17879
  pivot,
17484
17880
  itemQuery,
17485
17881
  databaseType,
@@ -18797,10 +19193,15 @@ async function getPivotTable(report, dashboardFilters, dashboardName, getToken,
18797
19193
  });
18798
19194
  }
18799
19195
  }
19196
+ const pivotQuery = generatePivotQuery(
19197
+ pivot,
19198
+ report.itemQuery?.[0],
19199
+ client.databaseType
19200
+ );
18800
19201
  return {
18801
19202
  rows: [],
18802
19203
  rowCount: 0,
18803
- pivotQuery: "",
19204
+ pivotQuery: pivotQuery ?? "",
18804
19205
  columns
18805
19206
  };
18806
19207
  }
@@ -21281,7 +21682,19 @@ var DashboardFiltersContext = createContext({
21281
21682
  loadFiltersForDashboard: async () => {
21282
21683
  }
21283
21684
  });
21284
- var TenantContext = createContext({});
21685
+ var TenantContext = createContext({
21686
+ childTenantMappings: {},
21687
+ viewerTenants: {},
21688
+ viewerTenantsByOwner: {},
21689
+ isLoadingMappedTenants: false,
21690
+ isLoadingViewerTenants: false,
21691
+ fetchViewerTenantsForDashboard: async () => {
21692
+ },
21693
+ fetchMappedTenantsForDashboard: async () => {
21694
+ },
21695
+ getMappedTenantsForDashboard: async () => void 0,
21696
+ getViewerTenantsByOwner: async () => []
21697
+ });
21285
21698
  var FetchContext = createContext({
21286
21699
  getToken: async () => "",
21287
21700
  quillFetchWithToken: async () => ({ data: null })
@@ -21371,6 +21784,15 @@ var ContextProvider = ({
21371
21784
  const fetchSchemaProcessId = useRef(0);
21372
21785
  const currentTenant = useRef(null);
21373
21786
  const currentPublicKey = useRef(null);
21787
+ const [childTenantMappings, setChildTenantMappings] = useState({});
21788
+ const [viewerTenants, setViewerTenants] = useState({});
21789
+ const [viewerTenantsByOwner, setViewerTenantsByOwner] = useState({});
21790
+ const [isLoadingMappedTenants, setIsLoadingMappedTenants] = useState(false);
21791
+ const [isLoadingViewerTenants, setIsLoadingViewerTenants] = useState(false);
21792
+ const prevTenants = useRef(null);
21793
+ const viewerTenantsRequests = useRef(/* @__PURE__ */ new Set());
21794
+ const viewerTenantsByOwnerRequests = useRef(/* @__PURE__ */ new Set());
21795
+ const mappedTenantsRequests = useRef(/* @__PURE__ */ new Set());
21374
21796
  const loadDashboardProcessId = useRef({});
21375
21797
  useEffect(() => {
21376
21798
  if (!theme) {
@@ -21719,7 +22141,7 @@ var ContextProvider = ({
21719
22141
  });
21720
22142
  await Promise.allSettled(
21721
22143
  filters.map(async (filter) => {
21722
- if (filter.filterType !== "string") {
22144
+ if (filter.filterType === "date_range") {
21723
22145
  dashboardFiltersDispatch({
21724
22146
  type: "UPDATE_DASHBOARD_FILTER",
21725
22147
  dashboardName,
@@ -21743,6 +22165,10 @@ var ContextProvider = ({
21743
22165
  });
21744
22166
  return null;
21745
22167
  }
22168
+ if (filter.filterType === "tenant") {
22169
+ await fetchTenantFilterOptions(dashboardName, filter);
22170
+ return null;
22171
+ }
21746
22172
  const filterOptionsAbortController = new AbortController();
21747
22173
  filterOptionsAbortControllers.current.add(filterOptionsAbortController);
21748
22174
  try {
@@ -22104,7 +22530,8 @@ var ContextProvider = ({
22104
22530
  },
22105
22531
  task: "dashboards",
22106
22532
  metadata: {
22107
- clientId: publicKey2
22533
+ clientId: publicKey2,
22534
+ tenants
22108
22535
  // getSections: true, // skip fetching reports since 'dashboard' always does anyway
22109
22536
  },
22110
22537
  abortSignal: fetchDashboardsAbortController.current.signal,
@@ -22193,6 +22620,14 @@ var ContextProvider = ({
22193
22620
  loading: true
22194
22621
  };
22195
22622
  });
22623
+ dashboard2.tenantFilters?.forEach(
22624
+ (filter) => {
22625
+ acc[dashboard2.name][filter.label] = {
22626
+ filter: { ...filter, options: void 0 },
22627
+ loading: true
22628
+ };
22629
+ }
22630
+ );
22196
22631
  return acc;
22197
22632
  }, {})
22198
22633
  });
@@ -22268,6 +22703,180 @@ var ContextProvider = ({
22268
22703
  return { error: "Failed to fetch data" };
22269
22704
  }
22270
22705
  }
22706
+ const getDashboardViewerTenants = async (dashboardName) => {
22707
+ if (!populatedClient) {
22708
+ return [];
22709
+ }
22710
+ const { data } = await quillFetchWithToken({
22711
+ client: populatedClient,
22712
+ task: "viewer-tenants",
22713
+ metadata: {
22714
+ dashboardName
22715
+ }
22716
+ });
22717
+ return data?.viewerTenants || [];
22718
+ };
22719
+ const getOwnerViewerTenants = async (ownerTenant) => {
22720
+ if (!populatedClient) {
22721
+ return [];
22722
+ }
22723
+ const { data } = await quillFetchWithToken({
22724
+ client: populatedClient,
22725
+ task: "viewer-tenants-by-owner",
22726
+ metadata: {
22727
+ tenantField: ownerTenant
22728
+ }
22729
+ });
22730
+ return data?.viewerTenants || [];
22731
+ };
22732
+ const getMappedTenants = async (tenantsParam, dashboardName) => {
22733
+ if (!populatedClient) {
22734
+ return {};
22735
+ }
22736
+ const { data, queries } = await quillFetchWithToken({
22737
+ client: populatedClient,
22738
+ task: "mapped-tenants",
22739
+ metadata: {
22740
+ tenants: tenantsParam,
22741
+ dashboardName
22742
+ }
22743
+ });
22744
+ const childTenants = data.queryOrder;
22745
+ const queryResults = queries.queryResults.map((result) => {
22746
+ return result?.rows?.map((row) => ({
22747
+ value: row["flag"],
22748
+ label: row["label"]
22749
+ })) ?? null;
22750
+ });
22751
+ const mappedTenants = {};
22752
+ await Promise.all(
22753
+ childTenants.map(
22754
+ async (tenant, index) => {
22755
+ mappedTenants[tenant.tenantField] = queryResults[index];
22756
+ }
22757
+ )
22758
+ );
22759
+ return mappedTenants;
22760
+ };
22761
+ const fetchViewerTenantsForDashboard = useCallback(
22762
+ async (dashboardName) => {
22763
+ if (!populatedClient) return;
22764
+ if (viewerTenantsRequests.current.has(dashboardName)) {
22765
+ return;
22766
+ }
22767
+ if (viewerTenants[dashboardName]) {
22768
+ return;
22769
+ }
22770
+ viewerTenantsRequests.current.add(dashboardName);
22771
+ setIsLoadingViewerTenants(true);
22772
+ try {
22773
+ const viewerTenantsData = await getDashboardViewerTenants(dashboardName);
22774
+ setViewerTenants((prev) => ({
22775
+ ...prev,
22776
+ [dashboardName]: viewerTenantsData
22777
+ }));
22778
+ } catch (error) {
22779
+ console.error("Error fetching viewer tenants:", error);
22780
+ } finally {
22781
+ viewerTenantsRequests.current.delete(dashboardName);
22782
+ setIsLoadingViewerTenants(false);
22783
+ }
22784
+ },
22785
+ [populatedClient]
22786
+ );
22787
+ const fetchMappedTenantsForDashboard = async (dashboardName) => {
22788
+ await getMappedTenantsForDashboard(dashboardName);
22789
+ return;
22790
+ };
22791
+ const getMappedTenantsForDashboard = useCallback(
22792
+ async (dashboardName) => {
22793
+ if (!populatedClient || !tenants) return void 0;
22794
+ const tenantsChanged = !equal(prevTenants.current, tenants);
22795
+ if (childTenantMappings[dashboardName] && !tenantsChanged) {
22796
+ return childTenantMappings[dashboardName];
22797
+ }
22798
+ if (mappedTenantsRequests.current.has(dashboardName) && !tenantsChanged) {
22799
+ return new Promise((resolve) => {
22800
+ const checkInterval = setInterval(() => {
22801
+ if (!mappedTenantsRequests.current.has(dashboardName)) {
22802
+ clearInterval(checkInterval);
22803
+ resolve(childTenantMappings[dashboardName]);
22804
+ }
22805
+ }, 100);
22806
+ });
22807
+ }
22808
+ prevTenants.current = tenants;
22809
+ mappedTenantsRequests.current.add(dashboardName);
22810
+ setIsLoadingMappedTenants(true);
22811
+ try {
22812
+ const mappedTenants = await getMappedTenants(tenants, dashboardName);
22813
+ setChildTenantMappings((prev) => ({
22814
+ ...prev,
22815
+ [dashboardName]: mappedTenants
22816
+ }));
22817
+ return mappedTenants;
22818
+ } catch (error) {
22819
+ console.error("Error fetching mapped tenants:", error);
22820
+ setChildTenantMappings((prev) => ({
22821
+ ...prev,
22822
+ [dashboardName]: {}
22823
+ }));
22824
+ return void 0;
22825
+ } finally {
22826
+ mappedTenantsRequests.current.delete(dashboardName);
22827
+ setIsLoadingMappedTenants(false);
22828
+ }
22829
+ },
22830
+ [populatedClient, tenants, childTenantMappings]
22831
+ );
22832
+ const getViewerTenantsByOwner = useCallback(
22833
+ async (ownerTenant) => {
22834
+ if (!populatedClient) return [];
22835
+ if (viewerTenantsByOwner[ownerTenant]) {
22836
+ return viewerTenantsByOwner[ownerTenant];
22837
+ }
22838
+ if (viewerTenantsByOwnerRequests.current.has(ownerTenant)) {
22839
+ return new Promise((resolve) => {
22840
+ const checkInterval = setInterval(() => {
22841
+ if (!viewerTenantsByOwnerRequests.current.has(ownerTenant)) {
22842
+ clearInterval(checkInterval);
22843
+ resolve(viewerTenantsByOwner[ownerTenant] || []);
22844
+ }
22845
+ }, 100);
22846
+ });
22847
+ }
22848
+ viewerTenantsByOwnerRequests.current.add(ownerTenant);
22849
+ setIsLoadingViewerTenants(true);
22850
+ try {
22851
+ const viewerTenantsData = await getOwnerViewerTenants(ownerTenant);
22852
+ setViewerTenantsByOwner((prev) => ({
22853
+ ...prev,
22854
+ [ownerTenant]: viewerTenantsData
22855
+ }));
22856
+ return viewerTenantsData;
22857
+ } catch (error) {
22858
+ console.error("Error fetching viewer tenants by owner:", error);
22859
+ return [];
22860
+ } finally {
22861
+ viewerTenantsByOwnerRequests.current.delete(ownerTenant);
22862
+ setIsLoadingViewerTenants(false);
22863
+ }
22864
+ },
22865
+ [populatedClient, viewerTenantsByOwner]
22866
+ );
22867
+ const fetchTenantFilterOptions = async (dashboardName, filter) => {
22868
+ const mappings = await getMappedTenantsForDashboard(dashboardName);
22869
+ const options = mappings?.[filter.field] ?? [];
22870
+ dashboardFiltersDispatch({
22871
+ type: "UPDATE_DASHBOARD_FILTER",
22872
+ dashboardName,
22873
+ filterName: filter.label,
22874
+ data: {
22875
+ filter: { ...filter, options },
22876
+ loading: false
22877
+ }
22878
+ });
22879
+ };
22271
22880
  useEffect(() => {
22272
22881
  async function updateClientAndSchema(publicKey2) {
22273
22882
  if (!publicKey2 || populatedClient?.clientId === publicKey2 && populatedClient?.allTenantTypes?.length)
@@ -22426,7 +23035,17 @@ var ContextProvider = ({
22426
23035
  {
22427
23036
  value: {
22428
23037
  tenants: populatedClient?.currentTenants ?? tenants,
22429
- flags: populatedClient?.currentFlags ?? flags
23038
+ flags: populatedClient?.currentFlags ?? flags,
23039
+ childTenantMappings,
23040
+ viewerTenants,
23041
+ viewerTenantsByOwner,
23042
+ isLoadingMappedTenants,
23043
+ isLoadingViewerTenants,
23044
+ fetchViewerTenantsForDashboard,
23045
+ // fetchViewerTenantsByOwner,
23046
+ fetchMappedTenantsForDashboard,
23047
+ getMappedTenantsForDashboard,
23048
+ getViewerTenantsByOwner
22430
23049
  },
22431
23050
  children
22432
23051
  }
@@ -22514,7 +23133,7 @@ var useDashboardInternal = (dashboardName, customFilters) => {
22514
23133
  );
22515
23134
  if (!fetchFromServer && Object.keys(dashboardFilters[dashboardName] ?? {}).length && // there exists no non date filter that has undefined options
22516
23135
  Object.values(dashboardFilters[dashboardName] ?? {}).every(
22517
- (filter) => filter.filter.filterType === "date_range" /* Date */ || filter.filter.options
23136
+ (filter) => filter.filter.filterType === "date_range" /* Date */ || filter.filter.filterType === "tenant" /* Tenant */ || filter.filter.options
22518
23137
  )) {
22519
23138
  return;
22520
23139
  }
@@ -22531,6 +23150,9 @@ var useDashboardInternal = (dashboardName, customFilters) => {
22531
23150
  ...updatedDashboard?.filters?.map((filter) => ({
22532
23151
  ...filter,
22533
23152
  query: void 0
23153
+ })) ?? [],
23154
+ ...updatedDashboard?.tenantFilters?.map((filter) => ({
23155
+ ...filter
22534
23156
  })) ?? []
22535
23157
  ],
22536
23158
  void 0,
@@ -22721,8 +23343,10 @@ var useDashboards = () => {
22721
23343
  (a, b) => (a.createdAt?.getTime() ?? 0) - (b.createdAt?.getTime() ?? 0)
22722
23344
  );
22723
23345
  }, [dashboardConfig]);
23346
+ const { getMappedTenantsForDashboard } = useContext(TenantContext);
22724
23347
  const createDashboard = async ({
22725
23348
  name: name2,
23349
+ tenantFilters,
22726
23350
  filters,
22727
23351
  dateFilter,
22728
23352
  dashboardOwners
@@ -22739,6 +23363,7 @@ var useDashboards = () => {
22739
23363
  tenantKeys: dashboardOwners,
22740
23364
  dashboardId: name2,
22741
23365
  name: name2,
23366
+ allTenantFilters: tenantFilters ?? [],
22742
23367
  filters,
22743
23368
  dateFilter
22744
23369
  },
@@ -22747,6 +23372,7 @@ var useDashboards = () => {
22747
23372
  });
22748
23373
  const body = {
22749
23374
  newDashboardName: name2.trim(),
23375
+ tenantFilters,
22750
23376
  filters,
22751
23377
  dateFilter,
22752
23378
  name: name2.trim(),
@@ -22799,6 +23425,7 @@ var useDashboards = () => {
22799
23425
  const updateDashboard = async (name2, {
22800
23426
  newName,
22801
23427
  filters,
23428
+ tenantFilters,
22802
23429
  dateFilter,
22803
23430
  customFilters,
22804
23431
  tenantKeys
@@ -22820,6 +23447,7 @@ var useDashboards = () => {
22820
23447
  const body = {
22821
23448
  newDashboardName: newName.trim(),
22822
23449
  filters,
23450
+ tenantFilters,
22823
23451
  dateFilter: dateFilter ?? null,
22824
23452
  name: name2.trim(),
22825
23453
  task: "edit-dashboard",
@@ -22849,6 +23477,7 @@ var useDashboards = () => {
22849
23477
  config: {
22850
23478
  ...dashboard,
22851
23479
  ...updated.data.dashboard,
23480
+ allTenantFilters: tenantFilters ?? [],
22852
23481
  dateFilter: updated.data.dashboard.dateFilter ? {
22853
23482
  ...updated.data.dashboard.dateFilter,
22854
23483
  presetOptions: updated.data.dashboard.dateFilter.presetOptions?.map(
@@ -22943,6 +23572,8 @@ var useDashboards = () => {
22943
23572
  endDate: !range.endDate || range.endDate instanceof Date ? range.endDate : new Date(range.endDate)
22944
23573
  // when range.endDate is a string
22945
23574
  } : void 0;
23575
+ const mappedTenants = await getMappedTenantsForDashboard(newName);
23576
+ const mappedTenantKeys = Object.keys(mappedTenants ?? {});
22946
23577
  const newFilters = [
22947
23578
  ...updatedDateFilter ? [updatedDateFilter] : [],
22948
23579
  ...updated.data.dashboard.filters.map(
@@ -22952,14 +23583,22 @@ var useDashboards = () => {
22952
23583
  values: oldFilters?.[f.label]?.filter?.values,
22953
23584
  operator: oldFilters?.[f.label]?.filter?.operator
22954
23585
  })
22955
- ) ?? []
23586
+ ) ?? [],
23587
+ ...(updated.data.dashboard.tenantFilters?.map(
23588
+ (f) => ({
23589
+ ...f,
23590
+ values: oldFilters?.[f.label]?.filter?.values
23591
+ })
23592
+ ) ?? []).filter((filter) => {
23593
+ return mappedTenantKeys.includes(filter.field);
23594
+ })
22956
23595
  ].map((f) => {
22957
23596
  if (f.filterType === "date_range" /* Date */) {
22958
23597
  return {
22959
23598
  ...f,
22960
- startDate: dashboardFilters[name2]?.[f.label]?.filter?.startDate,
22961
- endDate: dashboardFilters[name2]?.[f.label]?.filter?.endDate,
22962
- preset: dashboardFilters[name2]?.[f.label]?.filter?.preset
23599
+ startDate: dashboardFilters[name2]?.[f.label]?.filter?.startDate ?? f.startDate,
23600
+ endDate: dashboardFilters[name2]?.[f.label]?.filter?.endDate ?? f.endDate,
23601
+ preset: dashboardFilters[name2]?.[f.label]?.filter?.preset ?? f.preset
22963
23602
  };
22964
23603
  } else {
22965
23604
  return {
@@ -23101,6 +23740,20 @@ var useDashboard = (dashboardName) => {
23101
23740
  endDate: value.endDate
23102
23741
  };
23103
23742
  }
23743
+ } else if (f.filterType === "tenant" /* Tenant */) {
23744
+ const value = update.value;
23745
+ let values;
23746
+ if (Array.isArray(value)) {
23747
+ values = value;
23748
+ } else if (typeof value === "string") {
23749
+ values = [value];
23750
+ } else {
23751
+ values = [];
23752
+ }
23753
+ return {
23754
+ ...f,
23755
+ values
23756
+ };
23104
23757
  }
23105
23758
  return f;
23106
23759
  });
@@ -23560,7 +24213,7 @@ var useExport = (reportId, {
23560
24213
  } else {
23561
24214
  const rows = report.rows;
23562
24215
  for (let i = 0; i < rows.length; i += maximumRowsPerPage) {
23563
- const remainingRows = (rows.length - i) * maximumRowsPerPage;
24216
+ const remainingRows = rows.length - i;
23564
24217
  const availableSpace = maximumRowsPerPage - currentCount;
23565
24218
  const rowsToAdd = Math.min(remainingRows, availableSpace);
23566
24219
  currentCount += rowsToAdd;
@@ -25128,7 +25781,7 @@ var MemoizedButton = ({
25128
25781
  }) => {
25129
25782
  const [theme] = useContext4(ThemeContext);
25130
25783
  return /* @__PURE__ */ jsx26(
25131
- QuillToolTip,
25784
+ QuillToolTipPortal,
25132
25785
  {
25133
25786
  enabled: !!tooltipText && tooltipText !== "",
25134
25787
  text: tooltipText ?? "",
@@ -26365,6 +27018,140 @@ var QuillToolTip = ({
26365
27018
  /* @__PURE__ */ jsx26("div", { className: "tooltip-text", style: { ...textStyle }, children: text })
26366
27019
  ] }) : children;
26367
27020
  };
27021
+ var QuillToolTipPortal = ({
27022
+ children,
27023
+ text,
27024
+ enabled = true,
27025
+ containerStyle = {},
27026
+ textStyle = {},
27027
+ mirror = false
27028
+ }) => {
27029
+ const [theme] = useContext4(ThemeContext);
27030
+ const [isOpen, setIsOpen] = useState6(false);
27031
+ const tooltipRef = useRef3(null);
27032
+ const triggerRef = useRef3(null);
27033
+ const [tooltipPosition, setTooltipPosition] = useState6(void 0);
27034
+ const updatePosition = () => {
27035
+ if (triggerRef.current && tooltipRef.current) {
27036
+ const rect = triggerRef.current.getBoundingClientRect();
27037
+ const tooltipRect = tooltipRef.current.getBoundingClientRect();
27038
+ const viewportWidth = window.innerWidth;
27039
+ let top = rect.top + window.scrollY - tooltipRect.height - 8;
27040
+ let left = rect.left + window.scrollX;
27041
+ if (!mirror) {
27042
+ left = rect.left + rect.width / 2 - tooltipRect.width / 2 + window.scrollX;
27043
+ } else {
27044
+ left = rect.right - tooltipRect.width + window.scrollX;
27045
+ }
27046
+ if (left + tooltipRect.width > viewportWidth) {
27047
+ left = viewportWidth - tooltipRect.width - 16;
27048
+ }
27049
+ if (left < 16) {
27050
+ left = 16;
27051
+ }
27052
+ if (top < window.scrollY + 16) {
27053
+ top = rect.bottom + window.scrollY + 8;
27054
+ }
27055
+ setTooltipPosition({ top, left });
27056
+ }
27057
+ };
27058
+ useEffect6(() => {
27059
+ if (isOpen) {
27060
+ const timer2 = setTimeout(() => {
27061
+ updatePosition();
27062
+ }, 0);
27063
+ window.addEventListener("resize", updatePosition, { passive: true });
27064
+ window.addEventListener("scroll", updatePosition, { passive: true });
27065
+ return () => {
27066
+ clearTimeout(timer2);
27067
+ window.removeEventListener("resize", updatePosition);
27068
+ window.removeEventListener("scroll", updatePosition);
27069
+ };
27070
+ }
27071
+ }, [isOpen]);
27072
+ if (!enabled) {
27073
+ return /* @__PURE__ */ jsx26(Fragment2, { children });
27074
+ }
27075
+ return /* @__PURE__ */ jsxs18(
27076
+ "div",
27077
+ {
27078
+ ref: triggerRef,
27079
+ style: {
27080
+ display: "inline-block",
27081
+ position: "relative",
27082
+ ...containerStyle
27083
+ },
27084
+ onMouseEnter: () => setIsOpen(true),
27085
+ onMouseLeave: () => setIsOpen(false),
27086
+ children: [
27087
+ children,
27088
+ isOpen && createPortal(
27089
+ /* @__PURE__ */ jsxs18(
27090
+ "div",
27091
+ {
27092
+ ref: tooltipRef,
27093
+ style: {
27094
+ visibility: tooltipPosition ? "visible" : "hidden",
27095
+ position: "absolute",
27096
+ top: `${tooltipPosition?.top ?? 0}px`,
27097
+ left: `${tooltipPosition?.left ?? 0}px`,
27098
+ backgroundColor: "#ffffff",
27099
+ color: "#212121",
27100
+ textAlign: "center",
27101
+ borderRadius: 5,
27102
+ zIndex: 100,
27103
+ padding: 10,
27104
+ fontFamily: theme?.fontFamily,
27105
+ fontWeight: 600,
27106
+ fontSize: "small",
27107
+ whiteSpace: "nowrap",
27108
+ borderWidth: 1,
27109
+ borderStyle: "solid",
27110
+ borderColor: "#e7e7e7",
27111
+ boxShadow: "0px 1px 8px rgba(0, 0, 0, 0.07)",
27112
+ ...textStyle
27113
+ },
27114
+ children: [
27115
+ text,
27116
+ /* @__PURE__ */ jsx26(
27117
+ "div",
27118
+ {
27119
+ style: {
27120
+ position: "absolute",
27121
+ top: "100%",
27122
+ left: "50%",
27123
+ marginLeft: -6,
27124
+ borderWidth: 6,
27125
+ borderStyle: "solid",
27126
+ borderColor: "transparent",
27127
+ borderTopColor: "#e7e7e7"
27128
+ }
27129
+ }
27130
+ ),
27131
+ /* @__PURE__ */ jsx26(
27132
+ "div",
27133
+ {
27134
+ style: {
27135
+ position: "absolute",
27136
+ top: "100%",
27137
+ left: "50%",
27138
+ marginLeft: -5,
27139
+ borderWidth: 5,
27140
+ borderStyle: "solid",
27141
+ borderColor: "transparent",
27142
+ borderTopColor: "#ffffff"
27143
+ }
27144
+ }
27145
+ )
27146
+ ]
27147
+ }
27148
+ ),
27149
+ document.body
27150
+ )
27151
+ ]
27152
+ }
27153
+ );
27154
+ };
26368
27155
  var QuillChartBuilderCheckboxComponent = ({
26369
27156
  isChecked,
26370
27157
  label,
@@ -29467,7 +30254,7 @@ function QuillMultiSelectComponentWithCombo({
29467
30254
  );
29468
30255
  const potentialOptions = useMemo8(() => {
29469
30256
  return value.filter((opt) => !optionValues.has(opt ?? "")).map((opt) => ({
29470
- label: opt === "" ? "-" : opt ?? "-",
30257
+ label: opt === "" ? "-" : opt?.toString() ?? "-",
29471
30258
  value: opt ?? ""
29472
30259
  })).concat(options);
29473
30260
  }, [value, options]);
@@ -29484,7 +30271,9 @@ function QuillMultiSelectComponentWithCombo({
29484
30271
  if (matchingOptions.length === options.length && allSelectedLabel) {
29485
30272
  return allSelectedLabel;
29486
30273
  }
29487
- return matchingOptions.map((elem) => elem.label ?? "-").join(", ");
30274
+ return matchingOptions.map(
30275
+ (elem) => elem.label ?? "-"
30276
+ ).join(", ");
29488
30277
  }, [options, value]);
29489
30278
  const [selectAllCheckboxState, setSelectAllCheckboxState] = useState10(
29490
30279
  (() => {
@@ -30215,7 +31004,7 @@ function QuillSelectComponentWithCombo({
30215
31004
  textOverflow: "ellipsis",
30216
31005
  whiteSpace: "nowrap",
30217
31006
  overflow: "hidden",
30218
- fontWeight: value?.length || isLoading ? void 0 : 300
31007
+ fontWeight: value?.toString()?.length || isLoading ? void 0 : 300
30219
31008
  },
30220
31009
  children: selectedLabel
30221
31010
  }
@@ -30557,6 +31346,51 @@ function DashboardFilter2({
30557
31346
  ]
30558
31347
  }
30559
31348
  ) });
31349
+ } else if (filter.filterType === "tenant") {
31350
+ if (filter.multiSelect) {
31351
+ return /* @__PURE__ */ jsx42("div", { style: containerStyle, children: /* @__PURE__ */ jsx42(
31352
+ QuillMultiSelectComponentWithCombo,
31353
+ {
31354
+ label: filter.label,
31355
+ value: filter.values ?? [],
31356
+ onChange: (e) => {
31357
+ if (Array.isArray(e.target.value) && e.target.value.length === 0) {
31358
+ onChangeFilter(filter, void 0);
31359
+ return;
31360
+ }
31361
+ onChangeFilter(filter, e.target.value);
31362
+ },
31363
+ options: [
31364
+ ...filter.options ? filter.options.map((elem) => ({
31365
+ label: elem.label,
31366
+ value: elem.value
31367
+ })) : []
31368
+ ],
31369
+ width: 200,
31370
+ isLoading,
31371
+ disabled
31372
+ }
31373
+ ) });
31374
+ }
31375
+ return /* @__PURE__ */ jsx42("div", { style: containerStyle, children: /* @__PURE__ */ jsx42(
31376
+ QuillSelectComponentWithCombo,
31377
+ {
31378
+ label: filter.label,
31379
+ value: filter.values?.[0] ?? "",
31380
+ onChange: (e) => {
31381
+ onChangeFilter(filter, e.target.value);
31382
+ },
31383
+ options: [
31384
+ ...filter.options ? filter.options.map((elem) => ({
31385
+ label: elem.label,
31386
+ value: elem.value
31387
+ })) : []
31388
+ ],
31389
+ width: 200,
31390
+ isLoading,
31391
+ disabled
31392
+ }
31393
+ ) });
30560
31394
  }
30561
31395
  return null;
30562
31396
  }
@@ -34046,11 +34880,13 @@ function Chart({
34046
34880
  useEffect15(() => {
34047
34881
  setFilterValues(
34048
34882
  Object.values(reportFilters[reportId] ?? {}).reduce((acc, f) => {
34049
- acc[f.filter.label] = f.filter.filterType === "string" ? f.filter.stringFilterType === "multiselect" ? { values: f.filter.values, operator: "IN" } : { selectedValue: f.filter.selectedValue } : {
34883
+ 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" ? {
34050
34884
  startDate: f.filter.startDate,
34051
34885
  endDate: f.filter.endDate,
34052
34886
  preset: f.filter.preset,
34053
34887
  comparisonRange: f.filter.comparisonRange
34888
+ } : {
34889
+ values: f.filter.values
34054
34890
  };
34055
34891
  return acc;
34056
34892
  }, {})
@@ -34174,6 +35010,10 @@ function Chart({
34174
35010
  }
34175
35011
  };
34176
35012
  }
35013
+ } else if (filter.filterType === "tenant" /* Tenant */) {
35014
+ filterValue = {
35015
+ values: value ? Array.isArray(value) ? value : [value] : []
35016
+ };
34177
35017
  }
34178
35018
  setFilterValues((filterValues2) => ({
34179
35019
  ...filterValues2,
@@ -36827,11 +37667,13 @@ function Dashboard({
36827
37667
  useEffect18(() => {
36828
37668
  setFilterValues(
36829
37669
  Object.values(populatedDashboardFilters ?? {}).reduce((acc, f) => {
36830
- acc[f.label] = f.filterType === "string" ? f.stringFilterType === "multiselect" ? { values: f.values, operator: "IN" } : { selectedValue: f.selectedValue } : {
37670
+ acc[f.label] = f.filterType === "string" ? f.stringFilterType === "multiselect" ? { values: f.values, operator: "IN" } : { selectedValue: f.selectedValue } : f.filterType === "date_range" ? {
36831
37671
  startDate: f.startDate,
36832
37672
  endDate: f.endDate,
36833
37673
  preset: f.preset,
36834
37674
  comparisonRange: f.comparisonRange
37675
+ } : {
37676
+ values: f.values
36835
37677
  };
36836
37678
  return acc;
36837
37679
  }, {})
@@ -36976,6 +37818,10 @@ function Dashboard({
36976
37818
  }
36977
37819
  };
36978
37820
  }
37821
+ } else if (filter.filterType === "tenant" /* Tenant */) {
37822
+ filterValue = {
37823
+ values: value ? Array.isArray(value) ? value : [value] : []
37824
+ };
36979
37825
  }
36980
37826
  setFilterValues((filterValues2) => ({
36981
37827
  ...filterValues2,
@@ -37962,7 +38808,7 @@ import {
37962
38808
  useEffect as useEffect24,
37963
38809
  useRef as useRef18,
37964
38810
  useMemo as useMemo22,
37965
- useCallback as useCallback2
38811
+ useCallback as useCallback3
37966
38812
  } from "react";
37967
38813
  import MonacoEditor from "@monaco-editor/react";
37968
38814
 
@@ -37977,7 +38823,7 @@ import {
37977
38823
 
37978
38824
  // src/internals/ReportBuilder/PivotModal.tsx
37979
38825
  import {
37980
- useCallback,
38826
+ useCallback as useCallback2,
37981
38827
  useContext as useContext23,
37982
38828
  useMemo as useMemo18,
37983
38829
  useState as useState24,
@@ -38833,7 +39679,7 @@ var PivotModal = ({
38833
39679
  setIsOpen(false);
38834
39680
  setPopUpTitle("Add pivot");
38835
39681
  };
38836
- const onCommitPivot = useCallback(() => {
39682
+ const onCommitPivot = useCallback2(() => {
38837
39683
  const errors2 = [];
38838
39684
  if ((pivotAggregations?.length ?? 0) === 0) {
38839
39685
  errors2.push("You must have at least one aggregation");
@@ -38971,7 +39817,7 @@ var PivotModal = ({
38971
39817
  const onEditRecommendedPivot = (pivot) => {
38972
39818
  onEditPivot(pivot, null);
38973
39819
  };
38974
- const refreshPivots = useCallback(async () => {
39820
+ const refreshPivots = useCallback2(async () => {
38975
39821
  if (!client) {
38976
39822
  return;
38977
39823
  }
@@ -40387,6 +41233,10 @@ function InternalChart({
40387
41233
  }
40388
41234
  };
40389
41235
  }
41236
+ } else if (filter.filterType === "tenant" /* Tenant */) {
41237
+ filterValue = {
41238
+ values: value ? Array.isArray(value) ? value : [value] : []
41239
+ };
40390
41240
  }
40391
41241
  setFilterValues((filterValues2) => ({
40392
41242
  ...filterValues2,
@@ -41213,6 +42063,7 @@ var ListboxTextInput2 = ({
41213
42063
  };
41214
42064
 
41215
42065
  // src/ChartBuilder.tsx
42066
+ var import_pluralize = __toESM(require_pluralize(), 1);
41216
42067
  import { Fragment as Fragment13, jsx as jsx65, jsxs as jsxs47 } from "react/jsx-runtime";
41217
42068
  var CHART_TYPES = [
41218
42069
  "column",
@@ -41659,7 +42510,7 @@ function ChartBuilder({
41659
42510
  const validFilter = useMemo21(() => {
41660
42511
  return specificDashboardFilters.reduce(
41661
42512
  (acc, filter) => {
41662
- if (filter.filterType === "date_range") {
42513
+ if (filter.filterType === "date_range" || filter.filterType === "tenant") {
41663
42514
  acc[filter.label] = true;
41664
42515
  return acc;
41665
42516
  }
@@ -42802,6 +43653,30 @@ function ChartBuilder({
42802
43653
  setIsSubmitting(false);
42803
43654
  setTriggeredEditChart(false);
42804
43655
  };
43656
+ const memoizedTooltipText = useMemo21(() => {
43657
+ const getTooltipText = () => {
43658
+ if (formData.name === "") {
43659
+ return "Please enter a name for the chart";
43660
+ }
43661
+ if (formData.dashboardName === "") {
43662
+ return "Please select a dashboard";
43663
+ }
43664
+ if (formData.chartType === "") {
43665
+ return "Please select a chart type";
43666
+ }
43667
+ if (filterIssues.length !== 0) {
43668
+ return "Please fix the filter issues";
43669
+ }
43670
+ if (Object.values(validFilter).includes(false)) {
43671
+ return "Please fix the filter issues";
43672
+ }
43673
+ if (currentDashboard?.tenantKeys && customTenantAccess && Object.values(formFlags ?? {}).every((value) => !value.length)) {
43674
+ return "Please fix the tenant issues";
43675
+ }
43676
+ return "";
43677
+ };
43678
+ return getTooltipText();
43679
+ }, [formData, filterIssues, validFilter, formFlags, currentDashboard]);
42805
43680
  isHorizontalView = windowWidth < 1200 ? false : isHorizontalView;
42806
43681
  if (!schemaData.schema) {
42807
43682
  return /* @__PURE__ */ jsx65("div", { children: "No schema" });
@@ -43891,7 +44766,7 @@ function ChartBuilder({
43891
44766
  })) ?? [],
43892
44767
  width: 200,
43893
44768
  emptyLabel: dashboardOwner.scope === "database" ? "No tags supplied" : void 0,
43894
- allSelectedLabel: "All " + dashboardOwner.name + "s",
44769
+ allSelectedLabel: "All " + (0, import_pluralize.default)(dashboardOwner.name),
43895
44770
  style: {
43896
44771
  display: customTenantAccess || containsCustomFields ? "inline" : "none",
43897
44772
  marginTop: -1,
@@ -43916,7 +44791,7 @@ function ChartBuilder({
43916
44791
  {}
43917
44792
  ) ?? {},
43918
44793
  width: 200,
43919
- allSelectedLabel: "All " + dashboardOwner.name + "s",
44794
+ allSelectedLabel: "All " + (0, import_pluralize.default)(dashboardOwner.name),
43920
44795
  style: {
43921
44796
  display: customTenantAccess || containsCustomFields ? "inline" : "none",
43922
44797
  marginTop: -1,
@@ -44021,7 +44896,7 @@ function ChartBuilder({
44021
44896
  gap: 6
44022
44897
  },
44023
44898
  children: specificDashboardFilters.filter((f) => {
44024
- return f.filterType !== "date_range";
44899
+ return f.filterType === "string";
44025
44900
  }).map((filter, index) => /* @__PURE__ */ jsxs47(ChartBuilderInputRowContainer, { children: [
44026
44901
  /* @__PURE__ */ jsx65(
44027
44902
  TextInputComponent,
@@ -44199,6 +45074,7 @@ function ChartBuilder({
44199
45074
  disabled: formData.name === "" || formData.dashboardName === "" || formData.chartType === "" || filterIssues.length !== 0 || Object.values(validFilter).includes(false) || currentDashboard?.tenantKeys && customTenantAccess && Object.values(formFlags ?? {}).every(
44200
45075
  (value) => !value.length
44201
45076
  ),
45077
+ tooltipText: memoizedTooltipText,
44202
45078
  label: buttonLabel ? buttonLabel : report ? "Save changes" : "Add to dashboard"
44203
45079
  }
44204
45080
  )
@@ -45045,7 +45921,7 @@ function SQLEditor({
45045
45921
  onCloseChartBuilder && onCloseChartBuilder();
45046
45922
  }
45047
45923
  }, [isChartBuilderOpen]);
45048
- const handleRunSqlPrompt = useCallback2(async () => {
45924
+ const handleRunSqlPrompt = useCallback3(async () => {
45049
45925
  if (!client || sqlResponseLoading) {
45050
45926
  return;
45051
45927
  }
@@ -45063,7 +45939,7 @@ function SQLEditor({
45063
45939
  setQuery(resp.message);
45064
45940
  setSqlResponseLoading(false);
45065
45941
  }, [sqlPrompt, sqlResponseLoading]);
45066
- const debounceRunSqlPrompt = useCallback2(
45942
+ const debounceRunSqlPrompt = useCallback3(
45067
45943
  createDebounce(handleRunSqlPrompt, 500),
45068
45944
  [handleRunSqlPrompt]
45069
45945
  );
@@ -50197,7 +51073,8 @@ var SaveReport = ({
50197
51073
  reportBuilder,
50198
51074
  setIsOpen
50199
51075
  }
50200
- )
51076
+ ),
51077
+ submitButtonLabel
50201
51078
  }) => {
50202
51079
  return /* @__PURE__ */ jsxs59("div", { children: [
50203
51080
  SaveTrigger,
@@ -50240,7 +51117,7 @@ var SaveReport = ({
50240
51117
  FormContainer: ChartBuilderFormContainer,
50241
51118
  hideDateRangeFilter: true,
50242
51119
  hideDeleteButton: true,
50243
- buttonLabel: !!reportBuilder.reportId ? "Save changes" : "Add to dashboard",
51120
+ buttonLabel: submitButtonLabel ?? (!!reportBuilder.reportId ? "Save changes" : "Add to dashboard"),
50244
51121
  onClickChartElement,
50245
51122
  isEditingMode: true
50246
51123
  }
@@ -50339,7 +51216,8 @@ function ReportBuilder({
50339
51216
  hideCopySQL = true,
50340
51217
  isChartBuilderHorizontalView = true,
50341
51218
  onClickChartElement,
50342
- onRequestAddVirtualTable
51219
+ onRequestAddVirtualTable,
51220
+ submitButtonLabel
50343
51221
  }) {
50344
51222
  const [theme] = useContext32(ThemeContext);
50345
51223
  const parentRef = useRef20(null);
@@ -50727,7 +51605,7 @@ function ReportBuilder({
50727
51605
  setIsChartBuilderOpen(true);
50728
51606
  },
50729
51607
  disabled: !!errorMessage || !!pivotError || tableLoading || loading || !!unresolvedReportMessage,
50730
- label: reportId ? "Save changes" : "Add to dashboard",
51608
+ label: submitButtonLabel ?? (reportId ? "Save changes" : "Add to dashboard"),
50731
51609
  tooltipText: unresolvedReportMessage
50732
51610
  }
50733
51611
  )
@@ -50773,7 +51651,8 @@ function ReportBuilder({
50773
51651
  ErrorMessageComponent,
50774
51652
  PivotRowContainer,
50775
51653
  PivotColumnContainer,
50776
- onClickChartElement
51654
+ onClickChartElement,
51655
+ submitButtonLabel
50777
51656
  }
50778
51657
  ),
50779
51658
  isSaveQueryModalOpen && /* @__PURE__ */ jsx81(
@@ -51056,27 +51935,65 @@ function StaticChart({
51056
51935
  );
51057
51936
  }
51058
51937
 
51938
+ // src/hooks/useTenants.ts
51939
+ import { useContext as useContext34, useEffect as useEffect30 } from "react";
51940
+ var useTenants = (dashboardName) => {
51941
+ const {
51942
+ tenants,
51943
+ flags,
51944
+ childTenantMappings,
51945
+ viewerTenants,
51946
+ isLoadingMappedTenants,
51947
+ isLoadingViewerTenants,
51948
+ fetchViewerTenantsForDashboard,
51949
+ fetchMappedTenantsForDashboard,
51950
+ getMappedTenantsForDashboard,
51951
+ getViewerTenantsByOwner
51952
+ } = useContext34(TenantContext);
51953
+ useEffect30(() => {
51954
+ if (dashboardName) {
51955
+ fetchViewerTenantsForDashboard(dashboardName);
51956
+ }
51957
+ }, [dashboardName, fetchViewerTenantsForDashboard]);
51958
+ useEffect30(() => {
51959
+ if (dashboardName) {
51960
+ fetchMappedTenantsForDashboard(dashboardName);
51961
+ }
51962
+ }, [dashboardName, fetchMappedTenantsForDashboard]);
51963
+ return {
51964
+ tenants,
51965
+ flags,
51966
+ childTenantMappings: dashboardName ? childTenantMappings[dashboardName] || {} : {},
51967
+ mappedTenants: dashboardName ? childTenantMappings[dashboardName] || {} : {},
51968
+ viewerTenants: dashboardName ? viewerTenants[dashboardName] || [] : [],
51969
+ isLoadingMappedTenants,
51970
+ isLoadingViewerTenants,
51971
+ getMappedTenantsForDashboard,
51972
+ getViewerTenantsByOwner
51973
+ };
51974
+ };
51975
+
51059
51976
  // src/hooks/useQuill.ts
51060
- import { useContext as useContext34, useEffect as useEffect30, useMemo as useMemo27, useState as useState37 } from "react";
51977
+ import { useContext as useContext35, useEffect as useEffect31, useMemo as useMemo27, useState as useState37 } from "react";
51061
51978
  var useQuill = (reportId, pagination) => {
51062
- const { reports, reportsDispatch, fetchIndividualReport } = useContext34(ReportsContext);
51979
+ const { reports, reportsDispatch, fetchIndividualReport } = useContext35(ReportsContext);
51063
51980
  const { allReportsById } = useAllReports();
51064
- const { getToken } = useContext34(FetchContext);
51981
+ const { getToken } = useContext35(FetchContext);
51065
51982
  const dashboardReport = useMemo27(() => {
51066
51983
  return allReportsById[reportId ?? ""];
51067
51984
  }, [allReportsById[reportId ?? ""]]);
51068
- const { dashboardFilters, dashboardCustomFilters } = useContext34(
51985
+ const { dashboardFilters, dashboardCustomFilters } = useContext35(
51069
51986
  DashboardFiltersContext
51070
51987
  );
51071
- const { reportFilters, customReportFilters, reportFiltersDispatch } = useContext34(ReportFiltersContext);
51988
+ const { reportFilters, customReportFilters, reportFiltersDispatch } = useContext35(ReportFiltersContext);
51072
51989
  const specificReportFilters = useMemo27(() => {
51073
51990
  if (!reportId) return null;
51074
51991
  return Object.values(reportFilters[reportId] ?? []).map((f) => f.filter);
51075
51992
  }, [reportFilters, reportId]);
51076
- const [schemaData] = useContext34(SchemaDataContext);
51077
- const [client, isClientLoading] = useContext34(ClientContext);
51078
- const { tenants } = useContext34(TenantContext);
51079
- const { eventTracking } = useContext34(EventTrackingContext);
51993
+ const [schemaData] = useContext35(SchemaDataContext);
51994
+ const [client, isClientLoading] = useContext35(ClientContext);
51995
+ const { tenants } = useContext35(TenantContext);
51996
+ const { eventTracking } = useContext35(EventTrackingContext);
51080
51997
  const [loading, setLoading] = useState37(true);
51081
51998
  const [error, setError] = useState37(void 0);
51082
51999
  const [previousPage, setPreviousPage] = useState37(0);
@@ -51237,7 +52154,7 @@ var useQuill = (reportId, pagination) => {
51237
52154
  setLoading(false);
51238
52155
  }
51239
52156
  };
51240
- useEffect30(() => {
52157
+ useEffect31(() => {
51241
52158
  if (isClientLoading) return;
51242
52159
  if (reportId && specificReportFilters) {
51243
52160
  fetchReportHelper(reportId, {
@@ -51303,7 +52220,7 @@ var useMemoizedRows = (reportId) => {
51303
52220
  };
51304
52221
 
51305
52222
  // src/hooks/useAskQuill.tsx
51306
- import { useContext as useContext35, useEffect as useEffect31, useState as useState38 } from "react";
52223
+ import { useContext as useContext36, useEffect as useEffect32, useState as useState38 } from "react";
51307
52224
  function convertColumnInternalToAskQuillColumn(columns) {
51308
52225
  return columns.map((column) => {
51309
52226
  let convertedFieldType = FieldType.String;
@@ -51327,11 +52244,11 @@ function convertColumnInternalToAskQuillColumn(columns) {
51327
52244
  });
51328
52245
  }
51329
52246
  var useAskQuill = (dashboardName) => {
51330
- const [client] = useContext35(ClientContext);
51331
- const [schemaData] = useContext35(SchemaDataContext);
51332
- const { tenants } = useContext35(TenantContext);
51333
- const { getToken } = useContext35(FetchContext);
51334
- const { eventTracking } = useContext35(EventTrackingContext);
52247
+ const [client] = useContext36(ClientContext);
52248
+ const [schemaData] = useContext36(SchemaDataContext);
52249
+ const { tenants } = useContext36(TenantContext);
52250
+ const { getToken } = useContext36(FetchContext);
52251
+ const { eventTracking } = useContext36(EventTrackingContext);
51335
52252
  const [astInfo, setAstInfo] = useState38(void 0);
51336
52253
  const [data, setData] = useState38({
51337
52254
  rows: [],
@@ -51545,7 +52462,7 @@ var useAskQuill = (dashboardName) => {
51545
52462
  });
51546
52463
  setLoading(false);
51547
52464
  };
51548
- useEffect31(() => {
52465
+ useEffect32(() => {
51549
52466
  setAsk(() => askHelper);
51550
52467
  }, [schemaData.schema]);
51551
52468
  return {
@@ -51559,12 +52476,12 @@ var useAskQuill = (dashboardName) => {
51559
52476
  };
51560
52477
 
51561
52478
  // src/hooks/useVirtualTables.tsx
51562
- import { useContext as useContext36, useState as useState39 } from "react";
52479
+ import { useContext as useContext37, useState as useState39 } from "react";
51563
52480
  var useVirtualTables = () => {
51564
- const [schemaData, setSchemaData] = useContext36(SchemaDataContext);
51565
- const { tenants } = useContext36(TenantContext);
51566
- const { getToken, quillFetchWithToken } = useContext36(FetchContext);
51567
- const { eventTracking } = useContext36(EventTrackingContext);
52481
+ const [schemaData, setSchemaData] = useContext37(SchemaDataContext);
52482
+ const { tenants } = useContext37(TenantContext);
52483
+ const { getToken, quillFetchWithToken } = useContext37(FetchContext);
52484
+ const { eventTracking } = useContext37(EventTrackingContext);
51568
52485
  const [loadingTables, setLoadingTables] = useState39({});
51569
52486
  const handleReload = async (client, caller) => {
51570
52487
  setSchemaData({ ...schemaData, isSchemaLoading: true });
@@ -51733,5 +52650,6 @@ export {
51733
52650
  useQuill,
51734
52651
  useReportBuilder,
51735
52652
  useReports,
52653
+ useTenants,
51736
52654
  useVirtualTables
51737
52655
  };