@quillsql/react 2.12.26 → 2.12.28

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.
Files changed (139) hide show
  1. package/dist/cjs/Chart.d.ts +17 -2
  2. package/dist/cjs/Chart.d.ts.map +1 -1
  3. package/dist/cjs/Chart.js +137 -90
  4. package/dist/cjs/ChartBuilder.d.ts +3 -3
  5. package/dist/cjs/ChartBuilder.d.ts.map +1 -1
  6. package/dist/cjs/ChartBuilder.js +30 -23
  7. package/dist/cjs/ChartEditor.d.ts.map +1 -1
  8. package/dist/cjs/ChartEditor.js +66 -26
  9. package/dist/cjs/Context.d.ts +1 -0
  10. package/dist/cjs/Context.d.ts.map +1 -1
  11. package/dist/cjs/Context.js +17 -2
  12. package/dist/cjs/Dashboard.d.ts +6 -1
  13. package/dist/cjs/Dashboard.d.ts.map +1 -1
  14. package/dist/cjs/Dashboard.js +3 -1
  15. package/dist/cjs/ReportBuilder.d.ts +1 -1
  16. package/dist/cjs/ReportBuilder.d.ts.map +1 -1
  17. package/dist/cjs/ReportBuilder.js +12 -10
  18. package/dist/cjs/SQLEditor.d.ts +10 -1
  19. package/dist/cjs/SQLEditor.d.ts.map +1 -1
  20. package/dist/cjs/SQLEditor.js +27 -3
  21. package/dist/cjs/Table.d.ts +15 -1
  22. package/dist/cjs/Table.d.ts.map +1 -1
  23. package/dist/cjs/Table.js +143 -59
  24. package/dist/cjs/components/Chart/ChartTooltip.d.ts.map +1 -1
  25. package/dist/cjs/components/Chart/ChartTooltip.js +5 -4
  26. package/dist/cjs/components/Dashboard/DashboardFilter.d.ts.map +1 -1
  27. package/dist/cjs/components/Dashboard/DashboardFilter.js +1 -1
  28. package/dist/cjs/components/Dashboard/DataLoader.d.ts.map +1 -1
  29. package/dist/cjs/components/Dashboard/DataLoader.js +52 -15
  30. package/dist/cjs/components/Dashboard/MetricComponent.d.ts.map +1 -1
  31. package/dist/cjs/components/Dashboard/MetricComponent.js +7 -1
  32. package/dist/cjs/components/Dashboard/TableComponent.d.ts +16 -2
  33. package/dist/cjs/components/Dashboard/TableComponent.d.ts.map +1 -1
  34. package/dist/cjs/components/Dashboard/TableComponent.js +2 -14
  35. package/dist/cjs/components/QuillTable.d.ts +2 -2
  36. package/dist/cjs/components/QuillTable.d.ts.map +1 -1
  37. package/dist/cjs/components/QuillTable.js +7 -5
  38. package/dist/cjs/components/UiComponents.d.ts +3 -3
  39. package/dist/cjs/components/UiComponents.d.ts.map +1 -1
  40. package/dist/cjs/components/UiComponents.js +4 -4
  41. package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts +16 -1
  42. package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
  43. package/dist/cjs/internals/ReportBuilder/PivotModal.js +155 -80
  44. package/dist/cjs/utils/constants.d.ts +2 -0
  45. package/dist/cjs/utils/constants.d.ts.map +1 -0
  46. package/dist/cjs/utils/constants.js +4 -0
  47. package/dist/cjs/utils/dashboard.d.ts +1 -0
  48. package/dist/cjs/utils/dashboard.d.ts.map +1 -1
  49. package/dist/cjs/utils/dashboard.js +46 -97
  50. package/dist/cjs/utils/dataFetcher.d.ts.map +1 -1
  51. package/dist/cjs/utils/dataFetcher.js +56 -13
  52. package/dist/cjs/utils/dates.d.ts +8 -0
  53. package/dist/cjs/utils/dates.d.ts.map +1 -1
  54. package/dist/cjs/utils/dates.js +34 -1
  55. package/dist/cjs/utils/filterProcessing.d.ts +2 -0
  56. package/dist/cjs/utils/filterProcessing.d.ts.map +1 -1
  57. package/dist/cjs/utils/filterProcessing.js +129 -1
  58. package/dist/cjs/utils/logging.d.ts +2 -0
  59. package/dist/cjs/utils/logging.d.ts.map +1 -0
  60. package/dist/cjs/utils/logging.js +10 -0
  61. package/dist/cjs/utils/pivotConstructor.d.ts +6 -0
  62. package/dist/cjs/utils/pivotConstructor.d.ts.map +1 -0
  63. package/dist/cjs/utils/pivotConstructor.js +87 -0
  64. package/dist/cjs/utils/queryConstructor.d.ts +2 -1
  65. package/dist/cjs/utils/queryConstructor.d.ts.map +1 -1
  66. package/dist/cjs/utils/queryConstructor.js +46 -11
  67. package/dist/cjs/utils/tableProcessing.d.ts +22 -0
  68. package/dist/cjs/utils/tableProcessing.d.ts.map +1 -1
  69. package/dist/cjs/utils/tableProcessing.js +87 -1
  70. package/dist/esm/Chart.d.ts +17 -2
  71. package/dist/esm/Chart.d.ts.map +1 -1
  72. package/dist/esm/Chart.js +140 -93
  73. package/dist/esm/ChartBuilder.d.ts +3 -3
  74. package/dist/esm/ChartBuilder.d.ts.map +1 -1
  75. package/dist/esm/ChartBuilder.js +30 -23
  76. package/dist/esm/ChartEditor.d.ts.map +1 -1
  77. package/dist/esm/ChartEditor.js +66 -26
  78. package/dist/esm/Context.d.ts +1 -0
  79. package/dist/esm/Context.d.ts.map +1 -1
  80. package/dist/esm/Context.js +16 -1
  81. package/dist/esm/Dashboard.d.ts +6 -1
  82. package/dist/esm/Dashboard.d.ts.map +1 -1
  83. package/dist/esm/Dashboard.js +3 -1
  84. package/dist/esm/ReportBuilder.d.ts +1 -1
  85. package/dist/esm/ReportBuilder.d.ts.map +1 -1
  86. package/dist/esm/ReportBuilder.js +13 -11
  87. package/dist/esm/SQLEditor.d.ts +10 -1
  88. package/dist/esm/SQLEditor.d.ts.map +1 -1
  89. package/dist/esm/SQLEditor.js +27 -3
  90. package/dist/esm/Table.d.ts +15 -1
  91. package/dist/esm/Table.d.ts.map +1 -1
  92. package/dist/esm/Table.js +146 -62
  93. package/dist/esm/components/Chart/ChartTooltip.d.ts.map +1 -1
  94. package/dist/esm/components/Chart/ChartTooltip.js +5 -4
  95. package/dist/esm/components/Dashboard/DashboardFilter.d.ts.map +1 -1
  96. package/dist/esm/components/Dashboard/DashboardFilter.js +1 -1
  97. package/dist/esm/components/Dashboard/DataLoader.d.ts.map +1 -1
  98. package/dist/esm/components/Dashboard/DataLoader.js +52 -15
  99. package/dist/esm/components/Dashboard/MetricComponent.d.ts.map +1 -1
  100. package/dist/esm/components/Dashboard/MetricComponent.js +7 -1
  101. package/dist/esm/components/Dashboard/TableComponent.d.ts +16 -2
  102. package/dist/esm/components/Dashboard/TableComponent.d.ts.map +1 -1
  103. package/dist/esm/components/Dashboard/TableComponent.js +2 -14
  104. package/dist/esm/components/QuillTable.d.ts +2 -2
  105. package/dist/esm/components/QuillTable.d.ts.map +1 -1
  106. package/dist/esm/components/QuillTable.js +7 -5
  107. package/dist/esm/components/UiComponents.d.ts +3 -3
  108. package/dist/esm/components/UiComponents.d.ts.map +1 -1
  109. package/dist/esm/components/UiComponents.js +4 -4
  110. package/dist/esm/internals/ReportBuilder/PivotModal.d.ts +16 -1
  111. package/dist/esm/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
  112. package/dist/esm/internals/ReportBuilder/PivotModal.js +153 -80
  113. package/dist/esm/utils/constants.d.ts +2 -0
  114. package/dist/esm/utils/constants.d.ts.map +1 -0
  115. package/dist/esm/utils/constants.js +1 -0
  116. package/dist/esm/utils/dashboard.d.ts +1 -0
  117. package/dist/esm/utils/dashboard.d.ts.map +1 -1
  118. package/dist/esm/utils/dashboard.js +45 -97
  119. package/dist/esm/utils/dataFetcher.d.ts.map +1 -1
  120. package/dist/esm/utils/dataFetcher.js +56 -13
  121. package/dist/esm/utils/dates.d.ts +8 -0
  122. package/dist/esm/utils/dates.d.ts.map +1 -1
  123. package/dist/esm/utils/dates.js +31 -0
  124. package/dist/esm/utils/filterProcessing.d.ts +2 -0
  125. package/dist/esm/utils/filterProcessing.d.ts.map +1 -1
  126. package/dist/esm/utils/filterProcessing.js +126 -0
  127. package/dist/esm/utils/logging.d.ts +2 -0
  128. package/dist/esm/utils/logging.d.ts.map +1 -0
  129. package/dist/esm/utils/logging.js +6 -0
  130. package/dist/esm/utils/pivotConstructor.d.ts +6 -0
  131. package/dist/esm/utils/pivotConstructor.d.ts.map +1 -0
  132. package/dist/esm/utils/pivotConstructor.js +83 -0
  133. package/dist/esm/utils/queryConstructor.d.ts +2 -1
  134. package/dist/esm/utils/queryConstructor.d.ts.map +1 -1
  135. package/dist/esm/utils/queryConstructor.js +44 -10
  136. package/dist/esm/utils/tableProcessing.d.ts +22 -0
  137. package/dist/esm/utils/tableProcessing.d.ts.map +1 -1
  138. package/dist/esm/utils/tableProcessing.js +85 -1
  139. package/package.json +1 -1
@@ -1,9 +1,9 @@
1
1
  import { valueFormatter } from './valueFormatter';
2
- import { generatePivotTable, generatePivotTableYAxis, getDateRange, getDateString, } from '../internals/ReportBuilder/PivotModal';
2
+ import { generatePivotTable, generatePivotTableYAxis, } from '../internals/ReportBuilder/PivotModal';
3
3
  import { snakeAndCamelCaseToTitleCase } from './textProcessing';
4
- import { generatePivotQuery } from './queryConstructor';
5
4
  import { getData } from './dataFetcher';
6
- import { differenceInDays } from 'date-fns';
5
+ import { getDateBucketFromRange } from './dates';
6
+ import { generatePivotWithSQL } from './pivotConstructor';
7
7
  const defaultDashboardItem = {
8
8
  id: '',
9
9
  name: '',
@@ -67,8 +67,10 @@ export async function cleanDashboardItem(item, dashboardFilters, client, dateBuc
67
67
  xAxisFormat: item.xAxisFormat,
68
68
  order: item.order,
69
69
  filtersApplied: item.filtersApplied,
70
+ rowCount: parseInt(item.rowCount),
70
71
  sort: item.sort,
71
72
  page: item.page,
73
+ itemQuery: item.itemQuery,
72
74
  };
73
75
  }
74
76
  /**
@@ -118,106 +120,34 @@ async function getPivotTable(report, dashboardFilters, client, dateBucketInitial
118
120
  }
119
121
  const pivot = report?.pivot;
120
122
  const data = report || {};
121
- if (client && client.databaseType.toLowerCase() === 'postgresql') {
123
+ if (pivot && client && client.databaseType.toLowerCase() === 'postgresql') {
124
+ if (report.rowCount === 0) {
125
+ return { rows: [], columns: [] };
126
+ }
122
127
  try {
123
- let dateRange = undefined;
124
- let comparisonInterval = undefined;
125
128
  let dateBucket = dateBucketInitial;
126
- if (!dateBucket && pivot.rowFieldType !== 'string' && pivot.rowField) {
127
- let filterDateRange = undefined;
128
- if (dateFilter) {
129
- filterDateRange = {
130
- start: dateFilter.startDate,
131
- end: dateFilter.endDate,
132
- };
133
- }
134
- dateRange = getDateRange(filterDateRange, pivot.rowField, data.rows);
135
- const difference = differenceInDays(dateRange.end, dateRange.start);
136
- if (difference < 14) {
137
- dateBucket = 'day';
138
- }
139
- else if (difference < 60) {
140
- dateBucket = 'week';
141
- }
142
- else if (difference < 365 * 3) {
143
- dateBucket = 'month';
144
- }
145
- else {
146
- dateBucket = 'year';
147
- }
129
+ let filterDateRange = undefined;
130
+ if (dateFilter) {
131
+ filterDateRange = {
132
+ start: dateFilter.startDate,
133
+ end: dateFilter.endDate,
134
+ };
148
135
  }
149
- if (dateFilter && dateFilter && dateFilter.comparisonRange) {
150
- const comparisonRange = differenceInDays(dateFilter?.comparisonRange.endDate, dateFilter?.comparisonRange.startDate);
151
- if (!isNaN(comparisonRange)) {
152
- if (dateBucket === 'month') {
153
- comparisonInterval = comparisonRange / 30 + ' month';
154
- }
155
- else if (dateBucket === 'year') {
156
- comparisonInterval = comparisonRange / 365 + ' year';
157
- }
158
- else {
159
- comparisonInterval = comparisonRange + ' day';
160
- }
161
- }
136
+ else if (report.dateRange) {
137
+ filterDateRange = report.dateRange;
162
138
  }
163
- const sqlQuery = generatePivotQuery(pivot, report.itemQuery, report.rows, dateBucket, comparisonInterval);
164
- if (sqlQuery && report.rows.length > 0) {
165
- const hostedBody = {
166
- metadata: {
167
- preQueries: [sqlQuery],
168
- task: 'query',
169
- orgId: client.customerId || '*',
170
- clientId: client.publicKey,
171
- databaseType: client?.databaseType,
172
- getCustomFields: false,
173
- runQueryConfig: {
174
- overridePost: true,
175
- convertDatatypes: true,
176
- },
177
- },
178
- };
179
- const cloudBody = { ...hostedBody };
180
- const resp = await getData(client, 'query', 'same-origin', hostedBody, cloudBody);
181
- // With our current design we have to remove the second row field but leave the first for comparison purposes.
182
- const rows = resp.queryResults[0].rows;
183
- const columns = resp.queryResults[0].fields
184
- .map((field) => ({
185
- field: field.name,
186
- label: field.name.replace('comparison_', 'comparison '),
187
- }))
188
- .filter((field, index) => field.field !== 'comparison_' + pivot.rowField || index === 0);
189
- if (pivot.rowFieldType !== 'string') {
190
- rows.forEach((row) => {
191
- row[pivot.rowField] = getDateString(row[pivot.rowField], undefined, dateBucket);
192
- });
193
- // add a row for each date in the range that doesn't have a value
194
- if (pivot.rowFieldType !== 'string') {
195
- const dateSet = new Set(rows.map((row) => row[pivot.rowField]));
196
- // create a loop that will go through each formatted date and add a row if it doesn't exist going to the current date
197
- for (let date = dateFilter.startDate; date <= dateFilter.endDate; date = new Date(date.getTime() + 24 * 60 * 60 * 1000)) {
198
- const formattedDate = getDateString(date.toDateString(), undefined, dateBucket);
199
- if (!dateSet.has(formattedDate)) {
200
- const newRow = {};
201
- newRow[pivot.rowField] = formattedDate;
202
- rows.push(newRow);
203
- dateSet.add(formattedDate);
204
- }
205
- // order the rows by the date field
206
- rows.sort((a, b) => {
207
- return new Date(a[pivot.rowField]) < new Date(b[pivot.rowField])
208
- ? -1
209
- : 1;
210
- });
211
- }
212
- }
213
- }
214
- return {
215
- rows: rows,
216
- columns: columns,
217
- };
139
+ if (!dateBucket && filterDateRange) {
140
+ dateBucket = getDateBucketFromRange(filterDateRange);
218
141
  }
142
+ const pivotTable = await generatePivotWithSQL(pivot, report, client, dateBucket, dateFilter, report.distinctStrings);
143
+ if (pivotTable) {
144
+ return pivotTable;
145
+ }
146
+ throw new Error('Error generating pivot table');
147
+ }
148
+ catch (e) {
149
+ throw new Error('Error generating pivot table: ' + e);
219
150
  }
220
- catch (e) { }
221
151
  }
222
152
  return pivot && data.rows
223
153
  ? generatePivotTable(pivot, JSON.parse(JSON.stringify(data.rows)), // deep copy
@@ -274,3 +204,21 @@ function extractPivotedYAxis(pivotTable, itemInfo, config = undefined) {
274
204
  }
275
205
  return fields;
276
206
  }
207
+ export async function getDashboard(dashboardName, client) {
208
+ const searchParams = new URLSearchParams({
209
+ publicKey: client.publicKey,
210
+ orgId: client.customerId,
211
+ name: dashboardName,
212
+ }).toString();
213
+ const hostedBody = {
214
+ metadata: {
215
+ name: dashboardName,
216
+ task: 'config',
217
+ clientId: client.publicKey,
218
+ orgId: client.customerId || '*',
219
+ databaseType: client.databaseType,
220
+ },
221
+ };
222
+ const resp = await getData(client, `dashconfig?${searchParams}`, 'omit', hostedBody, null, 'GET');
223
+ return resp;
224
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"dataFetcher.d.ts","sourceRoot":"","sources":["../../../src/utils/dataFetcher.tsx"],"names":[],"mappings":"AAEA,wBAAsB,OAAO,CAC3B,MAAM,EAAE,GAAG,EACX,kBAAkB,EAAE,MAAM,EAC1B,MAAM,EAAE,kBAAkB,EAC1B,iBAAiB,EAAE,GAAG,EACtB,gBAAgB,EAAE,GAAG,EACrB,MAAM,SAAS,gBAgEhB;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,GAAG,EACX,kBAAkB,EAAE,MAAM,EAC1B,gBAAgB,EAAE,GAAG,EACrB,MAAM,SAAS,gBAgChB"}
1
+ {"version":3,"file":"dataFetcher.d.ts","sourceRoot":"","sources":["../../../src/utils/dataFetcher.tsx"],"names":[],"mappings":"AAqBA,wBAAsB,OAAO,CAC3B,MAAM,EAAE,GAAG,EACX,kBAAkB,EAAE,MAAM,EAC1B,MAAM,EAAE,kBAAkB,EAC1B,iBAAiB,EAAE,GAAG,EACtB,gBAAgB,EAAE,GAAG,EACrB,MAAM,SAAS,gBAmGhB;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,GAAG,EACX,kBAAkB,EAAE,MAAM,EAC1B,gBAAgB,EAAE,GAAG,EACrB,MAAM,SAAS,gBAgChB"}
@@ -1,3 +1,22 @@
1
+ function parseData(rows, queryType) {
2
+ if (!rows || rows.length === 0)
3
+ return [];
4
+ switch (queryType) {
5
+ case 'dateRange':
6
+ return {
7
+ start: new Date(rows[0]?.min_date),
8
+ end: new Date(rows[0]?.max_date),
9
+ };
10
+ case 'rowCount':
11
+ return parseInt(rows[0]?.count);
12
+ case 'distinctStrings':
13
+ return rows.map((row) => {
14
+ return row['column_field'];
15
+ });
16
+ default:
17
+ return rows;
18
+ }
19
+ }
1
20
  // this function gets the data either from the self hosted endpoint or
2
21
  // our cloud server
3
22
  export async function getData(client, cloudQueryEndpoint, noCred, hostedRequestBody, cloudRequestBody, method = 'POST') {
@@ -18,21 +37,45 @@ export async function getData(client, cloudQueryEndpoint, noCred, hostedRequestB
18
37
  return { success: false, errorMessage: responseJson.error };
19
38
  }
20
39
  let result;
21
- if (responseJson.data?.data) {
22
- result = {
23
- fields: responseJson?.data.queries?.queryResults[0]?.fields,
24
- ...responseJson.data.data,
25
- rows: responseJson?.data.queries?.queryResults[0]?.rows,
26
- compareRows: responseJson?.data.queries?.queryResults[1]?.rows,
27
- };
40
+ if (hostedRequestBody &&
41
+ hostedRequestBody.metadata &&
42
+ hostedRequestBody.metadata.task === 'report') {
43
+ if (responseJson.data?.data) {
44
+ result = {
45
+ fields: responseJson?.data.queries?.queryResults[0]?.fields,
46
+ ...responseJson.data.data,
47
+ };
48
+ responseJson.data.data.queryOrder.forEach((queryKey, index) => {
49
+ result[queryKey] = parseData(responseJson.queries.queryResults[index].rows, queryKey);
50
+ });
51
+ }
52
+ else {
53
+ result = {
54
+ fields: responseJson?.queries?.queryResults[0]?.fields,
55
+ ...responseJson.data,
56
+ };
57
+ responseJson.data.queryOrder.forEach((queryKey, index) => {
58
+ result[queryKey] = parseData(responseJson.queries.queryResults[index].rows, queryKey);
59
+ });
60
+ }
28
61
  }
29
62
  else {
30
- result = {
31
- fields: responseJson?.queries?.queryResults[0]?.fields,
32
- ...responseJson.data,
33
- rows: responseJson?.queries?.queryResults[0]?.rows,
34
- compareRows: responseJson?.queries?.queryResults[1]?.rows,
35
- };
63
+ if (responseJson.data?.data) {
64
+ result = {
65
+ fields: responseJson?.data.queries?.queryResults[0]?.fields,
66
+ ...responseJson.data.data,
67
+ rows: responseJson?.data.queries?.queryResults[0]?.rows,
68
+ compareRows: responseJson?.data.queries?.queryResults[1]?.rows,
69
+ };
70
+ }
71
+ else {
72
+ result = {
73
+ fields: responseJson?.queries?.queryResults[0]?.fields,
74
+ ...responseJson.data,
75
+ rows: responseJson?.queries?.queryResults[0]?.rows,
76
+ compareRows: responseJson?.queries?.queryResults[1]?.rows,
77
+ };
78
+ }
36
79
  }
37
80
  if (responseJson.data.columns &&
38
81
  responseJson.data.fields &&
@@ -7,4 +7,12 @@ export declare function convertComparisonRange(primaryRange: string, comparisonR
7
7
  * Returns whether the xAxisFormat is a date format.
8
8
  */
9
9
  export declare function isDateFormat(xAxisFormat: string): boolean;
10
+ export declare function getComparisonInterval(comparisonRange: {
11
+ startDate: Date;
12
+ endDate: Date;
13
+ }, dateBucket?: string): string | undefined;
14
+ export declare function getDateBucketFromRange(dateRange: {
15
+ start: Date;
16
+ end: Date;
17
+ }): "month" | "week" | "day" | "year";
10
18
  //# sourceMappingURL=dates.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dates.d.ts","sourceRoot":"","sources":["../../../src/utils/dates.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,UAYxB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,WAY/C"}
1
+ {"version":3,"file":"dates.d.ts","sourceRoot":"","sources":["../../../src/utils/dates.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,UAYxB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,WAa/C;AAED,wBAAgB,qBAAqB,CACnC,eAAe,EAAE;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,IAAI,CAAC;CACf,EACD,UAAU,CAAC,EAAE,MAAM,sBAepB;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,qCAW3E"}
@@ -1,3 +1,4 @@
1
+ import { differenceInDays } from 'date-fns';
1
2
  import { COMPARISON_OPTIONS } from '../DateRangePicker/dateRangePickerUtils';
2
3
  /**
3
4
  * Converts the comparison range label to match the date filter range if the
@@ -23,6 +24,7 @@ export function convertComparisonRange(primaryRange, comparisonRange) {
23
24
  export function isDateFormat(xAxisFormat) {
24
25
  const DATE_FORMATS = [
25
26
  'yyyy',
27
+ 'MMM_dd',
26
28
  'MMM_yyyy',
27
29
  'MMM_dd_yyyy',
28
30
  'hh_ap_pm',
@@ -33,3 +35,32 @@ export function isDateFormat(xAxisFormat) {
33
35
  const isDate = DATE_FORMATS.includes(xAxisFormat);
34
36
  return isDate;
35
37
  }
38
+ export function getComparisonInterval(comparisonRange, dateBucket) {
39
+ const dayCount = differenceInDays(comparisonRange.endDate, comparisonRange.startDate);
40
+ if (!isNaN(dayCount)) {
41
+ if (dateBucket === 'month') {
42
+ return dayCount / 30 + ' month';
43
+ }
44
+ else if (dateBucket === 'year') {
45
+ return dayCount / 365 + ' year';
46
+ }
47
+ else {
48
+ return dayCount + ' day';
49
+ }
50
+ }
51
+ }
52
+ export function getDateBucketFromRange(dateRange) {
53
+ const difference = differenceInDays(dateRange.end, dateRange.start);
54
+ if (difference < 14) {
55
+ return 'day';
56
+ }
57
+ else if (difference < 60) {
58
+ return 'week';
59
+ }
60
+ else if (difference < 365 * 3) {
61
+ return 'month';
62
+ }
63
+ else {
64
+ return 'year';
65
+ }
66
+ }
@@ -1,2 +1,4 @@
1
1
  export declare function findAndProcessDateFilter(filters: any[]): any;
2
+ export declare function processFilterFromBackend(filter: any, rows: any[]): any;
3
+ export declare function updateFilter(filter: any, value?: any, comparison?: any): any;
2
4
  //# sourceMappingURL=filterProcessing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"filterProcessing.d.ts","sourceRoot":"","sources":["../../../src/utils/filterProcessing.ts"],"names":[],"mappings":"AAAA,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,CAoB5D"}
1
+ {"version":3,"file":"filterProcessing.d.ts","sourceRoot":"","sources":["../../../src/utils/filterProcessing.ts"],"names":[],"mappings":"AAQA,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,CAoB5D;AAMD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,OA4BhE;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,GAAG,EACX,KAAK,GAAE,GAAU,EACjB,UAAU,GAAE,GAAU,OAuGvB"}
@@ -1,3 +1,4 @@
1
+ import { COMPARISON_RANGE, PRIMARY_RANGE, defaultOptionsV2, getRangeFromPresetOptions, } from '../DateRangePicker/dateRangePickerUtils';
1
2
  export function findAndProcessDateFilter(filters) {
2
3
  let dateFilter = filters.find((filter) => filter.filterType === 'date_range');
3
4
  if (dateFilter) {
@@ -19,3 +20,128 @@ export function findAndProcessDateFilter(filters) {
19
20
  function isValidDate(date) {
20
21
  return !isNaN(Date.parse(date));
21
22
  }
23
+ export function processFilterFromBackend(filter, rows) {
24
+ if (filter.filterType === 'date_range') {
25
+ return {
26
+ ...filter,
27
+ startDate: new Date(filter.startDate),
28
+ endDate: new Date(filter.endDate),
29
+ options: defaultOptionsV2,
30
+ comparisonRange: {
31
+ ...filter.comparisonRange,
32
+ value: filter.defaultComparisonRange,
33
+ },
34
+ };
35
+ }
36
+ if (filter.filterType === 'string') {
37
+ const options = rows.map((row) => row[filter.field]);
38
+ const distinctOptions = Array.from(new Set(options)).filter((value) => value !== undefined && value !== null);
39
+ return {
40
+ ...filter,
41
+ options: distinctOptions.map((option) => ({
42
+ label: option,
43
+ value: option,
44
+ })),
45
+ };
46
+ }
47
+ return filter;
48
+ }
49
+ export function updateFilter(filter, value = null, comparison = null) {
50
+ //for dateObjects only, since values are arrays for dateObjects
51
+ const { selectedValue: _, operator, ...filterWithoutSelectedValue } = filter; // _ is a throwaway variable
52
+ if (filter.filterType === 'string') {
53
+ let selectedValue = {};
54
+ if (value) {
55
+ if (filter.stringFilterType === 'multiselect') {
56
+ const parsedValue = JSON.parse(value);
57
+ if (parsedValue.length === 0) {
58
+ selectedValue = { values: [] };
59
+ }
60
+ else {
61
+ selectedValue = { values: parsedValue, operator: 'IN' };
62
+ }
63
+ }
64
+ else {
65
+ selectedValue = { selectedValue: value };
66
+ }
67
+ }
68
+ return {
69
+ ...filterWithoutSelectedValue,
70
+ ...selectedValue,
71
+ dashboardName: name,
72
+ };
73
+ }
74
+ if (filter.filterType === 'date' || filter.filterType === 'date_range') {
75
+ let presetsOptions = defaultOptionsV2;
76
+ if (filter.presetRanges) {
77
+ presetsOptions = filter.presetRanges.map((elem) => {
78
+ if (!elem.isStatic) {
79
+ return {
80
+ label: elem.label,
81
+ value: elem.value,
82
+ startDate: PRIMARY_RANGE[elem.value].start,
83
+ endDate: PRIMARY_RANGE[elem.value].end,
84
+ };
85
+ }
86
+ return {
87
+ label: elem.label,
88
+ value: elem.value,
89
+ startDate: new Date(elem.startDate),
90
+ endDate: new Date(elem.endDate),
91
+ };
92
+ });
93
+ }
94
+ if (comparison ||
95
+ (filter.comparison && filter.comparisonRange.value !== 'NO_COMPARISON')) {
96
+ let preset = '';
97
+ if (comparison) {
98
+ preset = filter.preset.label;
99
+ }
100
+ const key = comparison?.value || filter.comparisonRange.value;
101
+ let primaryRange = {
102
+ start: value ? value.startDate : filter.startDate,
103
+ end: value ? value.endDate : filter.endDate,
104
+ };
105
+ if (value && value.preset) {
106
+ preset = value.preset;
107
+ primaryRange = getRangeFromPresetOptions(value.preset, presetsOptions);
108
+ }
109
+ return {
110
+ startDate: primaryRange.start,
111
+ endDate: primaryRange.end,
112
+ filterType: 'date_range',
113
+ label: 'Date',
114
+ field: 'date_range',
115
+ preset: { label: preset },
116
+ options: filter.options,
117
+ comparison: true,
118
+ comparisonRange: {
119
+ startDate: COMPARISON_RANGE[key](primaryRange)?.start,
120
+ endDate: COMPARISON_RANGE[key](primaryRange)?.end,
121
+ value: key,
122
+ },
123
+ dashboardName: name,
124
+ };
125
+ }
126
+ else {
127
+ const primaryRange = value && value.preset
128
+ ? getRangeFromPresetOptions(value.preset, presetsOptions)
129
+ : {
130
+ start: value?.startDate || filter.startDate,
131
+ end: value?.endDate || filter.endDate,
132
+ };
133
+ const preset = value?.preset ? value.preset : '';
134
+ return {
135
+ ...filter,
136
+ preset: { label: preset },
137
+ startDate: primaryRange.start,
138
+ endDate: primaryRange.end,
139
+ filterType: 'date_range',
140
+ field: 'date_range',
141
+ options: filter.options,
142
+ label: 'Date',
143
+ dashboardName: name,
144
+ };
145
+ }
146
+ }
147
+ }
@@ -0,0 +1,2 @@
1
+ export declare function internalLog(message: string, ...optionalParams: any[]): void;
2
+ //# sourceMappingURL=logging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../../src/utils/logging.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,GAAG,EAAE,QAKpE"}
@@ -0,0 +1,6 @@
1
+ export function internalLog(message, ...optionalParams) {
2
+ if (process.env.QUILL_ENV === 'development') {
3
+ const completeMessage = `Quill: ${message}: ${optionalParams.join('\n')}`;
4
+ console.log(completeMessage);
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ import { Pivot } from '../internals/ReportBuilder/PivotModal';
2
+ export declare function generatePivotWithSQL(pivot: Pivot, report: any, client: any, dateBucket?: string, dateFilter?: any, distinctStrings?: any): Promise<{
3
+ rows: any;
4
+ columns: any;
5
+ } | undefined>;
6
+ //# sourceMappingURL=pivotConstructor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pivotConstructor.d.ts","sourceRoot":"","sources":["../../../src/utils/pivotConstructor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAiB,MAAM,uCAAuC,CAAC;AAK7E,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,GAAG,EACX,MAAM,EAAE,GAAG,EACX,UAAU,CAAC,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,GAAG,EAChB,eAAe,CAAC,EAAE,GAAG;;;eAkHtB"}
@@ -0,0 +1,83 @@
1
+ import { getDateString } from '../internals/ReportBuilder/PivotModal';
2
+ import { getData } from './dataFetcher';
3
+ import { getComparisonInterval } from './dates';
4
+ import { generatePivotQuery } from './queryConstructor';
5
+ export async function generatePivotWithSQL(pivot, report, client, dateBucket, dateFilter, distinctStrings) {
6
+ if (dateFilter && dateFilter.startDate) {
7
+ dateFilter.start = dateFilter.startDate;
8
+ dateFilter.end = dateFilter.endDate;
9
+ if (dateFilter.comparisonRange && dateFilter.comparisonRange.startDate) {
10
+ dateFilter.comparisonRange.start = dateFilter.comparisonRange.startDate;
11
+ dateFilter.comparisonRange.end = dateFilter.comparisonRange.endDate;
12
+ }
13
+ }
14
+ let comparisonInterval = undefined;
15
+ if (dateFilter && dateFilter.comparisonRange) {
16
+ comparisonInterval = getComparisonInterval({
17
+ startDate: dateFilter.comparisonRange.start,
18
+ endDate: dateFilter.comparisonRange.end,
19
+ }, dateBucket);
20
+ }
21
+ if (pivot.rowField && !pivot.rowFieldType) {
22
+ const rowColumn = report.columns.find((column) => column.field === pivot.rowField);
23
+ pivot.rowFieldType = rowColumn.format;
24
+ }
25
+ const sqlQuery = generatePivotQuery(pivot, report.itemQuery, report.rows, dateBucket, comparisonInterval, distinctStrings);
26
+ if (sqlQuery && report.rows.length > 0) {
27
+ const hostedBody = {
28
+ metadata: {
29
+ preQueries: [sqlQuery],
30
+ task: 'query',
31
+ orgId: client.customerId || '*',
32
+ clientId: client.publicKey,
33
+ databaseType: client?.databaseType,
34
+ getCustomFields: false,
35
+ runQueryConfig: {
36
+ overridePost: true,
37
+ convertDatatypes: true,
38
+ },
39
+ },
40
+ };
41
+ const cloudBody = { ...hostedBody };
42
+ const resp = await getData(client, 'query', 'same-origin', hostedBody, cloudBody);
43
+ // With our current design we have to remove the second row field but leave the first for comparison purposes.
44
+ const rows = resp.queryResults[0].rows;
45
+ const columns = resp.queryResults[0].fields
46
+ .map((field) => ({
47
+ field: field.name,
48
+ label: field.name.replace('comparison_', 'comparison '),
49
+ }))
50
+ .filter((field, index) => field.field !== 'comparison_' + pivot.rowField || index === 0);
51
+ if (pivot.rowField && !['string', 'varchar'].includes(pivot.rowFieldType)) {
52
+ rows.forEach((row) => {
53
+ row[pivot.rowField] = getDateString(row[pivot.rowField], undefined, dateBucket);
54
+ });
55
+ // add a row for each date in the range that doesn't have a value
56
+ if (pivot.rowField &&
57
+ !['string', 'varchar'].includes(pivot.rowFieldType) &&
58
+ dateFilter) {
59
+ const dateSet = new Set(rows.map((row) => row[pivot.rowField]));
60
+ // create a loop that will go through each formatted date and add a row if it doesn't exist going to the current date
61
+ for (let date = dateFilter.start ?? dateFilter.startDate; date <= dateFilter.end; date = new Date(date.getTime() + 24 * 60 * 60 * 1000)) {
62
+ const formattedDate = getDateString(date.toDateString(), undefined, dateBucket);
63
+ if (!dateSet.has(formattedDate)) {
64
+ const newRow = {};
65
+ newRow[pivot.rowField] = formattedDate;
66
+ rows.push(newRow);
67
+ dateSet.add(formattedDate);
68
+ }
69
+ // order the rows by the date field
70
+ rows.sort((a, b) => {
71
+ return new Date(a[pivot.rowField]) < new Date(b[pivot.rowField])
72
+ ? -1
73
+ : 1;
74
+ });
75
+ }
76
+ }
77
+ }
78
+ return {
79
+ rows: rows,
80
+ columns: columns,
81
+ };
82
+ }
83
+ }
@@ -1,4 +1,5 @@
1
1
  import { Pivot } from '../internals/ReportBuilder/PivotModal';
2
2
  export declare function generateDistinctQuery(stringFields: string[], query: string): string;
3
- export declare function generatePivotQuery(pivot: Pivot, itemQueries: string[], rows: any[], dateBucket?: string, comparisonInterval?: string): string | undefined;
3
+ export declare function generateMinMaxRangeQueries(columnFields: string[], query: string, databaseType: string): string;
4
+ export declare function generatePivotQuery(pivot: Pivot, itemQueries: string[], rows: any[], dateBucket?: string, comparisonInterval?: string, distinctStrings?: string[]): string | undefined;
4
5
  //# sourceMappingURL=queryConstructor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queryConstructor.d.ts","sourceRoot":"","sources":["../../../src/utils/queryConstructor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uCAAuC,CAAC;AAe9D,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,UAQ1E;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,MAAM,EAAE,EACrB,IAAI,EAAE,GAAG,EAAE,EACX,UAAU,CAAC,EAAE,MAAM,EACnB,kBAAkB,CAAC,EAAE,MAAM,GAC1B,MAAM,GAAG,SAAS,CAiBpB"}
1
+ {"version":3,"file":"queryConstructor.d.ts","sourceRoot":"","sources":["../../../src/utils/queryConstructor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uCAAuC,CAAC;AAe9D,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,UAQ1E;AAED,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,EAAE,EACtB,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,UAcrB;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,MAAM,EAAE,EACrB,IAAI,EAAE,GAAG,EAAE,EACX,UAAU,CAAC,EAAE,MAAM,EACnB,kBAAkB,CAAC,EAAE,MAAM,EAC3B,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,MAAM,GAAG,SAAS,CAuBpB"}