@quillsql/react 2.11.12 → 2.11.14
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/cjs/ChartBuilder.d.ts.map +1 -1
- package/dist/cjs/ChartBuilder.js +1 -1
- package/dist/cjs/Dashboard.js +1 -1
- package/dist/cjs/ReportBuilder.d.ts.map +1 -1
- package/dist/cjs/ReportBuilder.js +354 -197
- package/dist/cjs/SQLEditor.d.ts.map +1 -1
- package/dist/cjs/SQLEditor.js +1 -0
- package/dist/cjs/components/Chart/ChartTooltipFrame.d.ts.map +1 -1
- package/dist/cjs/components/Chart/ChartTooltipFrame.js +1 -0
- package/dist/cjs/components/Chart/LineChart.d.ts.map +1 -1
- package/dist/cjs/components/Chart/LineChart.js +3 -0
- package/dist/cjs/components/Dashboard/MetricComponent.js +2 -2
- package/dist/cjs/components/QuillCard.d.ts.map +1 -1
- package/dist/cjs/components/QuillCard.js +2 -4
- package/dist/cjs/components/QuillSelect.d.ts.map +1 -1
- package/dist/cjs/components/QuillSelect.js +7 -1
- package/dist/cjs/components/QuillTable.d.ts.map +1 -1
- package/dist/cjs/components/QuillTable.js +2 -2
- package/dist/cjs/components/ReportBuilder/AddColumnPopover.js +3 -3
- package/dist/cjs/components/ReportBuilder/AddLimitPopover.d.ts +3 -0
- package/dist/cjs/components/ReportBuilder/AddLimitPopover.d.ts.map +1 -0
- package/dist/cjs/components/ReportBuilder/AddLimitPopover.js +43 -0
- package/dist/cjs/components/ReportBuilder/AddSortPopover.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/AddSortPopover.js +10 -4
- package/dist/cjs/components/ReportBuilder/bigDateMap.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/bigDateMap.js +2 -1
- package/dist/cjs/components/ReportBuilder/convert.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/convert.js +38 -12
- package/dist/cjs/components/ReportBuilder/ui.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/ui.js +4 -3
- package/dist/cjs/components/ReportBuilder/util.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/util.js +7 -5
- package/dist/cjs/components/UiComponents.js +2 -2
- package/dist/cjs/internals/ReportBuilder/PivotList.d.ts.map +1 -1
- package/dist/cjs/internals/ReportBuilder/PivotList.js +28 -2
- package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts +2 -1
- package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
- package/dist/cjs/internals/ReportBuilder/PivotModal.js +49 -32
- package/dist/cjs/utils/getDomain.d.ts.map +1 -1
- package/dist/cjs/utils/getDomain.js +3 -0
- package/dist/esm/ChartBuilder.d.ts.map +1 -1
- package/dist/esm/ChartBuilder.js +1 -1
- package/dist/esm/Dashboard.js +1 -1
- package/dist/esm/ReportBuilder.d.ts.map +1 -1
- package/dist/esm/ReportBuilder.js +354 -197
- package/dist/esm/SQLEditor.d.ts.map +1 -1
- package/dist/esm/SQLEditor.js +1 -0
- package/dist/esm/components/Chart/ChartTooltipFrame.d.ts.map +1 -1
- package/dist/esm/components/Chart/ChartTooltipFrame.js +1 -0
- package/dist/esm/components/Chart/LineChart.d.ts.map +1 -1
- package/dist/esm/components/Chart/LineChart.js +3 -0
- package/dist/esm/components/Dashboard/MetricComponent.js +2 -2
- package/dist/esm/components/QuillCard.d.ts.map +1 -1
- package/dist/esm/components/QuillCard.js +2 -4
- package/dist/esm/components/QuillSelect.d.ts.map +1 -1
- package/dist/esm/components/QuillSelect.js +7 -1
- package/dist/esm/components/QuillTable.d.ts.map +1 -1
- package/dist/esm/components/QuillTable.js +2 -2
- package/dist/esm/components/ReportBuilder/AddColumnPopover.js +3 -3
- package/dist/esm/components/ReportBuilder/AddLimitPopover.d.ts +3 -0
- package/dist/esm/components/ReportBuilder/AddLimitPopover.d.ts.map +1 -0
- package/dist/esm/components/ReportBuilder/AddLimitPopover.js +38 -0
- package/dist/esm/components/ReportBuilder/AddSortPopover.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/AddSortPopover.js +10 -4
- package/dist/esm/components/ReportBuilder/bigDateMap.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/bigDateMap.js +2 -1
- package/dist/esm/components/ReportBuilder/convert.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/convert.js +38 -12
- package/dist/esm/components/ReportBuilder/ui.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/ui.js +4 -3
- package/dist/esm/components/ReportBuilder/util.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/util.js +7 -5
- package/dist/esm/components/UiComponents.js +2 -2
- package/dist/esm/internals/ReportBuilder/PivotList.d.ts.map +1 -1
- package/dist/esm/internals/ReportBuilder/PivotList.js +28 -2
- package/dist/esm/internals/ReportBuilder/PivotModal.d.ts +2 -1
- package/dist/esm/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
- package/dist/esm/internals/ReportBuilder/PivotModal.js +49 -32
- package/dist/esm/utils/getDomain.d.ts.map +1 -1
- package/dist/esm/utils/getDomain.js +3 -0
- package/package.json +2 -2
|
@@ -21,6 +21,8 @@ import { PivotModal, generatePivotTable, } from './internals/ReportBuilder/Pivot
|
|
|
21
21
|
import { PivotCard } from './internals/ReportBuilder/PivotList';
|
|
22
22
|
import QuillTable from './components/QuillTable';
|
|
23
23
|
import { QuillSelectComponent } from './components/QuillSelect';
|
|
24
|
+
import { snakeCaseToTitleCase } from './utils/textProcessing';
|
|
25
|
+
import { AddLimitPopover, LimitSentence, } from './components/ReportBuilder/AddLimitPopover';
|
|
24
26
|
/**
|
|
25
27
|
* Quill Report Builder
|
|
26
28
|
*
|
|
@@ -58,6 +60,8 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
58
60
|
const [showPivotPopover, setShowPivotPopover] = useState(false);
|
|
59
61
|
const [isEdittingPivot, setIsEdittingPivot] = useState(false);
|
|
60
62
|
const [selectedPivotIndex, setSelectedPivotIndex] = useState(-1);
|
|
63
|
+
const [initialLoad, setInitialLoad] = useState(true);
|
|
64
|
+
const [currentTable, setCurrentTable] = useState(initialTableName || '');
|
|
61
65
|
const parentRef = useRef(null);
|
|
62
66
|
const [theme] = useContext(ThemeContext);
|
|
63
67
|
const [pivotRowField, setPivotRowField] = useState(undefined);
|
|
@@ -85,7 +89,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
85
89
|
return columns.map((col) => ({
|
|
86
90
|
label: col,
|
|
87
91
|
name: col,
|
|
88
|
-
displayName: col,
|
|
92
|
+
displayName: snakeCaseToTitleCase(col),
|
|
89
93
|
field: col,
|
|
90
94
|
format: getPostgresBasicType(fields.find((f) => f.name === col))?.replace('number', 'whole_number') || 'string',
|
|
91
95
|
fieldType: schemaTables
|
|
@@ -117,6 +121,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
117
121
|
// setUniqueValues({});
|
|
118
122
|
setPivot(null);
|
|
119
123
|
setPivotData(null);
|
|
124
|
+
setRecommendedPivots([]);
|
|
120
125
|
}, 0);
|
|
121
126
|
};
|
|
122
127
|
useEffect(() => {
|
|
@@ -177,7 +182,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
177
182
|
}
|
|
178
183
|
setUniqueValues(newValues);
|
|
179
184
|
};
|
|
180
|
-
const fetchSqlQuery = async () => {
|
|
185
|
+
const fetchSqlQuery = async (ast, formData) => {
|
|
186
|
+
setLoading(true);
|
|
187
|
+
setErrorMessage('');
|
|
181
188
|
try {
|
|
182
189
|
const response = await fetch(`https://quill-344421.uc.r.appspot.com/sqlify`, {
|
|
183
190
|
method: 'POST',
|
|
@@ -185,32 +192,19 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
185
192
|
'Content-Type': 'application/json',
|
|
186
193
|
},
|
|
187
194
|
body: JSON.stringify({
|
|
188
|
-
ast: { ...
|
|
195
|
+
ast: { ...ast, where: formData },
|
|
189
196
|
publicKey: client.publicKey,
|
|
190
197
|
}),
|
|
191
198
|
});
|
|
192
199
|
const data = await response.json();
|
|
193
200
|
setActiveQuery(data.query);
|
|
194
|
-
fetchUponChange();
|
|
201
|
+
fetchUponChange(ast, formData);
|
|
195
202
|
}
|
|
196
203
|
catch (error) {
|
|
204
|
+
setLoading(false);
|
|
197
205
|
console.error(error);
|
|
198
206
|
}
|
|
199
207
|
};
|
|
200
|
-
useEffect(() => {
|
|
201
|
-
setErrorMessage('');
|
|
202
|
-
if (baseAst || formData) {
|
|
203
|
-
fetchSqlQuery();
|
|
204
|
-
}
|
|
205
|
-
}, [baseAst]);
|
|
206
|
-
// Returns an array of all the column names in the pivot config
|
|
207
|
-
// if there are any, otherwise returns [].
|
|
208
|
-
const getColumnsInPivot = () => {
|
|
209
|
-
if (!pivot)
|
|
210
|
-
return [];
|
|
211
|
-
const { valueField, rowField, columnField } = pivot;
|
|
212
|
-
return [valueField, rowField, columnField].filter(Boolean);
|
|
213
|
-
};
|
|
214
208
|
// It's just like getColumnsInPivot but we expand the columnField
|
|
215
209
|
// if there is one to include all the variants just like it would
|
|
216
210
|
// show up in the table. (eg. category -> ...[Fuel, Food, Other])
|
|
@@ -229,81 +223,78 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
229
223
|
result.push(valueField, rowField);
|
|
230
224
|
return result.filter(Boolean);
|
|
231
225
|
};
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
226
|
+
const fetchDistinctHelper = async (column, table) => {
|
|
227
|
+
try {
|
|
228
|
+
const query = `SELECT DISTINCT ${column} FROM ${table};`;
|
|
229
|
+
const response = await fetch(`https://quill-344421.uc.r.appspot.com/dashquery`, {
|
|
230
|
+
method: 'POST',
|
|
231
|
+
headers: {
|
|
232
|
+
'Content-Type': 'application/json',
|
|
233
|
+
},
|
|
234
|
+
body: JSON.stringify({
|
|
235
|
+
orgId: client.customerId,
|
|
236
|
+
publicKey: client.publicKey,
|
|
237
|
+
query: query,
|
|
238
|
+
}),
|
|
239
|
+
});
|
|
240
|
+
const data = await response.json();
|
|
241
|
+
if (data.errorMessage) {
|
|
242
|
+
// console.error(data.errorMessage);
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
const options = data.rows.map((r) => r[column]);
|
|
246
|
+
const newCheckboxValues = options.reduce((obj, col) => {
|
|
247
|
+
obj[col] = false;
|
|
248
|
+
return obj;
|
|
249
|
+
}, {});
|
|
250
|
+
return { table, column, values: newCheckboxValues };
|
|
251
|
+
}
|
|
252
|
+
catch (e) {
|
|
253
|
+
console.error(e);
|
|
254
|
+
return null;
|
|
235
255
|
}
|
|
236
|
-
}
|
|
256
|
+
};
|
|
237
257
|
useEffect(() => {
|
|
238
|
-
const
|
|
258
|
+
const fetchSchema = async () => {
|
|
239
259
|
try {
|
|
240
|
-
const
|
|
241
|
-
const response = await fetch(`https://quill-344421.uc.r.appspot.com/dashquery`, {
|
|
260
|
+
const response = await fetch(`${client.queryEndpoint}`, {
|
|
242
261
|
method: 'POST',
|
|
243
262
|
headers: {
|
|
263
|
+
...client.queryHeaders,
|
|
244
264
|
'Content-Type': 'application/json',
|
|
245
265
|
},
|
|
246
266
|
body: JSON.stringify({
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
267
|
+
metadata: {
|
|
268
|
+
clientId: client.publicKey,
|
|
269
|
+
publicKey: client.publicKey,
|
|
270
|
+
task: 'schema',
|
|
271
|
+
removeCustomerField: true,
|
|
272
|
+
},
|
|
250
273
|
}),
|
|
251
274
|
});
|
|
252
|
-
const
|
|
253
|
-
if (data.errorMessage) {
|
|
254
|
-
// console.error(data.errorMessage);
|
|
255
|
-
return null;
|
|
256
|
-
}
|
|
257
|
-
const options = data.rows.map((r) => r[column]);
|
|
258
|
-
const newCheckboxValues = options.reduce((obj, col) => {
|
|
259
|
-
obj[col] = false;
|
|
260
|
-
return obj;
|
|
261
|
-
}, {});
|
|
262
|
-
return { table, column, values: newCheckboxValues };
|
|
263
|
-
}
|
|
264
|
-
catch (e) {
|
|
265
|
-
console.error(e);
|
|
266
|
-
return null;
|
|
267
|
-
}
|
|
268
|
-
};
|
|
269
|
-
const fetchSchema = async () => {
|
|
270
|
-
try {
|
|
271
|
-
const response = await fetch(`https://quill-344421.uc.r.appspot.com/schema2/${client.publicKey}`).then((res) => res.json());
|
|
275
|
+
const results = await response.json();
|
|
272
276
|
// Filter out hidden columns on tables back from schema2.
|
|
273
|
-
const tables =
|
|
274
|
-
for (const table of tables) {
|
|
275
|
-
table.columns = table.columns.filter((column) =>
|
|
276
|
-
// Quick and dirty fix for removing org ids from response.
|
|
277
|
-
// TODO: Fix this on the backend or something.
|
|
278
|
-
column.isVisible && column.displayName !== 'pm_company_id');
|
|
279
|
-
}
|
|
277
|
+
const tables = results.data.tables || results.data.data.tables;
|
|
280
278
|
setSchemaTables(tables ?? []);
|
|
281
|
-
setOrderedColumnNames((tables ?? [])
|
|
282
|
-
|
|
283
|
-
.
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
newUniqueValues[table] = {};
|
|
301
|
-
}
|
|
302
|
-
newUniqueValues[table][column] = values;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
if (hashCode(uniqueValues) !== hashCode(newUniqueValues)) {
|
|
306
|
-
setUniqueValues(newUniqueValues);
|
|
279
|
+
setOrderedColumnNames((tables ?? []).flatMap((table) => table.columns
|
|
280
|
+
.map((c) => `${table.name}.${c.name}`)
|
|
281
|
+
.sort((a, b) => {
|
|
282
|
+
const aIsId = a.endsWith('.id') || a.endsWith('_id');
|
|
283
|
+
const bIsId = b.endsWith('.id') || b.endsWith('_id');
|
|
284
|
+
if (aIsId && !bIsId)
|
|
285
|
+
return 1;
|
|
286
|
+
if (bIsId && !aIsId)
|
|
287
|
+
return -1;
|
|
288
|
+
return 0;
|
|
289
|
+
})));
|
|
290
|
+
if (initialTableName && initialLoad) {
|
|
291
|
+
setInitialLoad(false);
|
|
292
|
+
setLoading(true);
|
|
293
|
+
await getDistinctValues(initialTableName, tables);
|
|
294
|
+
const columnsForTable = tables
|
|
295
|
+
.find((t) => t.name === initialTableName)
|
|
296
|
+
?.columns.map((c) => c.name);
|
|
297
|
+
await handleAsk(`get ${columnsForTable} from ${initialTableName}`);
|
|
307
298
|
}
|
|
308
299
|
}
|
|
309
300
|
catch (error) {
|
|
@@ -327,7 +318,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
327
318
|
const paths = globalPath.split('.').filter((p) => p);
|
|
328
319
|
if (paths.length === 0 && !isInsertion && !isReplaceSubtree) {
|
|
329
320
|
setFormData(null);
|
|
330
|
-
|
|
321
|
+
const newAst = deepCopy({
|
|
331
322
|
...defaultAST,
|
|
332
323
|
...baseAst,
|
|
333
324
|
...(!baseAst?.columns && {
|
|
@@ -341,12 +332,13 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
341
332
|
from: [{ ...defaultTable, table: initialTableName }],
|
|
342
333
|
}),
|
|
343
334
|
where: null,
|
|
344
|
-
})
|
|
335
|
+
});
|
|
336
|
+
setBaseAst(newAst);
|
|
337
|
+
fetchSqlQuery(newAst, null);
|
|
345
338
|
return;
|
|
346
339
|
}
|
|
347
340
|
if (!formData && isInsertion) {
|
|
348
|
-
|
|
349
|
-
setBaseAst(deepCopy({
|
|
341
|
+
const newAst = deepCopy({
|
|
350
342
|
...defaultAST,
|
|
351
343
|
...baseAst,
|
|
352
344
|
...(!baseAst?.columns && {
|
|
@@ -360,7 +352,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
360
352
|
from: [{ ...defaultTable, table: initialTableName }],
|
|
361
353
|
}),
|
|
362
354
|
where: value,
|
|
363
|
-
})
|
|
355
|
+
});
|
|
356
|
+
setFormData(value);
|
|
357
|
+
setBaseAst(newAst);
|
|
358
|
+
fetchSqlQuery(newAst, value);
|
|
364
359
|
return;
|
|
365
360
|
}
|
|
366
361
|
let newState = deepCopy(formData);
|
|
@@ -444,7 +439,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
444
439
|
}
|
|
445
440
|
}
|
|
446
441
|
setFormData(newState);
|
|
447
|
-
|
|
442
|
+
const newAst = {
|
|
448
443
|
...defaultAST,
|
|
449
444
|
...baseAst,
|
|
450
445
|
...(!baseAst?.columns && {
|
|
@@ -458,7 +453,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
458
453
|
from: [{ ...defaultTable, table: initialTableName }],
|
|
459
454
|
}),
|
|
460
455
|
where: { ...newState },
|
|
461
|
-
}
|
|
456
|
+
};
|
|
457
|
+
setBaseAst(newAst);
|
|
458
|
+
fetchSqlQuery(newAst, newState);
|
|
462
459
|
});
|
|
463
460
|
};
|
|
464
461
|
// TODO: Merge this function with the updateFormData function
|
|
@@ -607,6 +604,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
607
604
|
};
|
|
608
605
|
// Function to handle operator changes
|
|
609
606
|
const handleOperatorChange = (value, node, keyPrefix, column = null) => {
|
|
607
|
+
if (!keyPrefix) {
|
|
608
|
+
setTopLevelBinaryOperator(value);
|
|
609
|
+
}
|
|
610
610
|
if (isPending) {
|
|
611
611
|
updateActiveItem([{ path: keyPrefix + 'operator', value }], { column });
|
|
612
612
|
}
|
|
@@ -675,6 +675,23 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
675
675
|
.find((c) => c.name === columnName);
|
|
676
676
|
return column?.fieldType;
|
|
677
677
|
};
|
|
678
|
+
const emptyPivotColumns = () => {
|
|
679
|
+
if (pivot && pivot.rowField && pivot.columnField && pivot.valueField) {
|
|
680
|
+
return [
|
|
681
|
+
{ label: snakeCaseToTitleCase(pivot.rowField) },
|
|
682
|
+
{ label: snakeCaseToTitleCase(pivot.columnField) },
|
|
683
|
+
];
|
|
684
|
+
}
|
|
685
|
+
else if (pivot && pivot.rowField && pivot.valueField) {
|
|
686
|
+
return [
|
|
687
|
+
{ label: snakeCaseToTitleCase(pivot.rowField) },
|
|
688
|
+
{ label: snakeCaseToTitleCase(pivot.valueField) },
|
|
689
|
+
];
|
|
690
|
+
}
|
|
691
|
+
else {
|
|
692
|
+
return [{ label: snakeCaseToTitleCase(pivot.valueField) }];
|
|
693
|
+
}
|
|
694
|
+
};
|
|
678
695
|
/**
|
|
679
696
|
* Render form fields based on the type of the node
|
|
680
697
|
* @param node the AST or subtree to render recursively
|
|
@@ -721,7 +738,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
721
738
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
722
739
|
}
|
|
723
740
|
}, options: getAllPossibleColumns().map((column) => ({
|
|
724
|
-
label: column.displayName,
|
|
741
|
+
label: snakeCaseToTitleCase(column.displayName),
|
|
725
742
|
value: column.name,
|
|
726
743
|
})) }), _jsx(Select, { theme: theme, value: dateFilterType, onChange: (value) => {
|
|
727
744
|
if (value === dateFilterType)
|
|
@@ -815,7 +832,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
815
832
|
else if (isInTheLastInterval(node, client.databaseType)) {
|
|
816
833
|
const { dateColumn, dateFilterType, intervalCount, intervalType } = getDateFilterInfo(node);
|
|
817
834
|
const options = getAllPossibleColumns().map((column) => ({
|
|
818
|
-
label: column.displayName,
|
|
835
|
+
label: snakeCaseToTitleCase(column.displayName),
|
|
819
836
|
value: column.name,
|
|
820
837
|
}));
|
|
821
838
|
const plural = node.right.args.value[1].expr.value > 1 ? 's' : '';
|
|
@@ -866,7 +883,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
866
883
|
else if (isTheCurrentInterval(node, client.databaseType)) {
|
|
867
884
|
const { dateFilterType } = getDateFilterInfo(node);
|
|
868
885
|
const options = getAllPossibleColumns().map((column) => ({
|
|
869
|
-
label: column.displayName,
|
|
886
|
+
label: snakeCaseToTitleCase(column.displayName),
|
|
870
887
|
value: column.name,
|
|
871
888
|
}));
|
|
872
889
|
return (_jsxs("div", { style: {
|
|
@@ -911,7 +928,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
911
928
|
}
|
|
912
929
|
else if (isThePreviousInterval(node, client.databaseType)) {
|
|
913
930
|
const options = getAllPossibleColumns().map((column) => ({
|
|
914
|
-
label: column.displayName,
|
|
931
|
+
label: snakeCaseToTitleCase(column.displayName),
|
|
915
932
|
value: column.name,
|
|
916
933
|
}));
|
|
917
934
|
return (_jsxs("div", { style: {
|
|
@@ -972,7 +989,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
972
989
|
}
|
|
973
990
|
else if (isColumnComparison(node)) {
|
|
974
991
|
const options = getAllPossibleColumns().map((column) => ({
|
|
975
|
-
label: column.displayName,
|
|
992
|
+
label: snakeCaseToTitleCase(column.displayName),
|
|
976
993
|
value: column.name,
|
|
977
994
|
}));
|
|
978
995
|
// grab the value of the left child of the column comparison
|
|
@@ -1026,6 +1043,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1026
1043
|
gap: 12,
|
|
1027
1044
|
flexDirection: 'column',
|
|
1028
1045
|
width: '100%',
|
|
1046
|
+
padding: '6px 0px',
|
|
1029
1047
|
}, children: [_jsxs("div", { style: {
|
|
1030
1048
|
display: 'flex',
|
|
1031
1049
|
gap: 20,
|
|
@@ -1067,7 +1085,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1067
1085
|
else {
|
|
1068
1086
|
handleDeleteVariant(keyPrefix + 'right.' + 'value', key);
|
|
1069
1087
|
}
|
|
1070
|
-
} }), _jsx("span", { children: key })] }, key))) }, keyPrefix + 'right.'))] }));
|
|
1088
|
+
} }), _jsx("span", { style: { fontFamily: theme.fontFamily }, children: key })] }, key))) }, keyPrefix + 'right.'))] }));
|
|
1071
1089
|
}
|
|
1072
1090
|
else {
|
|
1073
1091
|
const columnName = node.left.column;
|
|
@@ -1121,7 +1139,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1121
1139
|
}
|
|
1122
1140
|
case 'column_ref': {
|
|
1123
1141
|
const options = getAllPossibleColumns().map((column) => ({
|
|
1124
|
-
label: column.displayName,
|
|
1142
|
+
label: snakeCaseToTitleCase(column.displayName),
|
|
1125
1143
|
value: column.name,
|
|
1126
1144
|
}));
|
|
1127
1145
|
return (_jsx(Select, { theme: theme, style: { width: '120px' }, value: node.column ?? options[0]?.value, onChange: (value) => {
|
|
@@ -1248,10 +1266,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1248
1266
|
isInTheCurrentIntervalSentence ??
|
|
1249
1267
|
isInTheLastIntervalSentence ??
|
|
1250
1268
|
isInThePreviousIntervalSentence ?? (_jsxs(_Fragment, { children: [node.left &&
|
|
1251
|
-
renderSentence(formData, node.left, keyPrefix + 'left.', false, false, isRow), isRow ? (' ' + OPS[node.operator] + ' ') : topLevelBinaryOperator === 'OR' ? (_jsx(TopLevelBooleanSwitch, { node: node, keyPrefix: keyPrefix, handleOperatorChange: handleOperatorChange, Select: Select })) : null, node.right &&
|
|
1269
|
+
renderSentence(formData, node.left, keyPrefix + 'left.', false, false, isRow), isRow ? (' ' + OPS[node.operator] + ' ') : isTopLevel || topLevelBinaryOperator === 'OR' ? (_jsx(TopLevelBooleanSwitch, { node: node, keyPrefix: keyPrefix, handleOperatorChange: handleOperatorChange, Select: Select })) : null, node.right &&
|
|
1252
1270
|
renderSentence(formData, node.right, keyPrefix + 'right.', false, false, isRow)] })) }));
|
|
1253
1271
|
case 'column_ref':
|
|
1254
|
-
return node.column;
|
|
1272
|
+
return snakeCaseToTitleCase(node.column);
|
|
1255
1273
|
case 'expr_list':
|
|
1256
1274
|
if (node.value.length === 1) {
|
|
1257
1275
|
const subQuery = renderSentence(formData, node.value[0]);
|
|
@@ -1283,10 +1301,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1283
1301
|
if (node.args.value.length < 1)
|
|
1284
1302
|
return null;
|
|
1285
1303
|
if (node.args.value[0].value) {
|
|
1286
|
-
return node.args.value[0].value.replaceAll('%', '');
|
|
1304
|
+
return snakeCaseToTitleCase(node.args.value[0].value.replaceAll('%', ''));
|
|
1287
1305
|
}
|
|
1288
1306
|
if (node.args.value[0].column)
|
|
1289
|
-
return node.args.value[0].column.replaceAll('%', '');
|
|
1307
|
+
return snakeCaseToTitleCase(node.args.value[0].column.replaceAll('%', ''));
|
|
1290
1308
|
return null;
|
|
1291
1309
|
}
|
|
1292
1310
|
if (node.name.toLowerCase() === 'current_date' ||
|
|
@@ -1323,37 +1341,22 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1323
1341
|
const tableNamesInQuery = baseAst.from.map((tbl) => tbl.table);
|
|
1324
1342
|
return schemaTables
|
|
1325
1343
|
.filter((t) => tableNamesInQuery.includes(t.displayName))
|
|
1326
|
-
.flatMap((table) => table.columns
|
|
1344
|
+
.flatMap((table) => table.columns
|
|
1345
|
+
.map((c) => ({
|
|
1327
1346
|
...c,
|
|
1328
1347
|
table: table.displayName,
|
|
1329
|
-
}))
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
})
|
|
1342
|
-
.filter((c) => isNumericColumnType(c.fieldType));
|
|
1343
|
-
};
|
|
1344
|
-
const getNonNumericColumns = () => {
|
|
1345
|
-
const allColumns = getAllPossibleColumns();
|
|
1346
|
-
const selectedColumnNames = selectedColumns.map((col) => col.split('.')[1]);
|
|
1347
|
-
return allColumns
|
|
1348
|
-
.filter((column) => selectedColumnNames.includes(column.name))
|
|
1349
|
-
.filter((c) => !isNumericColumnType(c.fieldType));
|
|
1350
|
-
};
|
|
1351
|
-
const getStringColumns = () => {
|
|
1352
|
-
const allColumns = getAllPossibleColumns();
|
|
1353
|
-
const selectedColumnNames = selectedColumns.map((col) => col.split('.')[1]);
|
|
1354
|
-
return allColumns
|
|
1355
|
-
.filter((column) => selectedColumnNames.includes(column.name))
|
|
1356
|
-
.filter((c) => isTextColumnType(c.fieldType));
|
|
1348
|
+
}))
|
|
1349
|
+
.sort((a, b) => {
|
|
1350
|
+
const aIsId = a.name.toLowerCase() === 'id' ||
|
|
1351
|
+
a.name.toLowerCase().endsWith('_id');
|
|
1352
|
+
const bIsId = b.name.toLowerCase() === 'id' ||
|
|
1353
|
+
b.name.toLowerCase().endsWith('_id');
|
|
1354
|
+
if (aIsId && !bIsId)
|
|
1355
|
+
return 1;
|
|
1356
|
+
if (bIsId && !aIsId)
|
|
1357
|
+
return -1;
|
|
1358
|
+
return 0;
|
|
1359
|
+
}));
|
|
1357
1360
|
};
|
|
1358
1361
|
/**
|
|
1359
1362
|
* Return whether all columns have been selected (used to hide select all
|
|
@@ -1377,26 +1380,6 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1377
1380
|
},
|
|
1378
1381
|
as: null,
|
|
1379
1382
|
});
|
|
1380
|
-
const SortableItem = ({ id, label, setSelectedColumns, selectedColumns, }) => {
|
|
1381
|
-
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: id });
|
|
1382
|
-
const style = {
|
|
1383
|
-
transform: DND_CSS.Transform.toString(transform),
|
|
1384
|
-
transition,
|
|
1385
|
-
};
|
|
1386
|
-
const handleSelect = () => {
|
|
1387
|
-
setSelectedColumns((selectedColumns) => {
|
|
1388
|
-
if (selectedColumns.includes(id)) {
|
|
1389
|
-
return selectedColumns.filter((column) => column !== id);
|
|
1390
|
-
}
|
|
1391
|
-
else {
|
|
1392
|
-
return [...selectedColumns, id];
|
|
1393
|
-
}
|
|
1394
|
-
});
|
|
1395
|
-
};
|
|
1396
|
-
return (_jsx("div", { style: { userSelect: 'none', ...style }, ref: setNodeRef, children: _jsx(SelectColumn, { selected: selectedColumns?.includes(id), setSelected: handleSelect, label: label, children: _jsx("div", { style: {
|
|
1397
|
-
cursor: 'grab',
|
|
1398
|
-
}, ...attributes, ...listeners, children: _jsx(HandleButton, {}) }) }) }));
|
|
1399
|
-
};
|
|
1400
1383
|
const AddConditionPopover = ({ onSave }) => {
|
|
1401
1384
|
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx("h1", { style: {
|
|
1402
1385
|
fontWeight: '600',
|
|
@@ -1410,8 +1393,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1410
1393
|
justifyContent: 'end',
|
|
1411
1394
|
}, children: _jsx(Button, { onClick: onSave, label: 'Add condition' }) })] }));
|
|
1412
1395
|
};
|
|
1413
|
-
const fetchUponChange = async () => {
|
|
1414
|
-
if
|
|
1396
|
+
const fetchUponChange = async (baseAst, newFormData) => {
|
|
1397
|
+
// if newFormData is null still use it
|
|
1398
|
+
const curFormData = newFormData !== undefined ? newFormData : formData;
|
|
1399
|
+
if ((curFormData || baseAst) && !loading) {
|
|
1415
1400
|
try {
|
|
1416
1401
|
setLoading(true);
|
|
1417
1402
|
const res2 = await fetch('https://quill-344421.uc.r.appspot.com/patterns', {
|
|
@@ -1420,7 +1405,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1420
1405
|
'Content-Type': 'application/json',
|
|
1421
1406
|
},
|
|
1422
1407
|
body: JSON.stringify({
|
|
1423
|
-
ast: { ...baseAst, where:
|
|
1408
|
+
ast: { ...baseAst, where: curFormData },
|
|
1424
1409
|
publicKey: client.publicKey,
|
|
1425
1410
|
orgId: client.customerId,
|
|
1426
1411
|
}),
|
|
@@ -1429,6 +1414,21 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1429
1414
|
if (data2.rows && data2.rows.length) {
|
|
1430
1415
|
const tables = getTableNames(baseAst);
|
|
1431
1416
|
const table = tables.length >= 1 ? tables[0] : initialTableName;
|
|
1417
|
+
if (table !== currentTable) {
|
|
1418
|
+
getDistinctValues(table);
|
|
1419
|
+
setCurrentTable(table);
|
|
1420
|
+
}
|
|
1421
|
+
const sortedFields = data2.fields.sort((a, b) => {
|
|
1422
|
+
const aIsId = a.name.toLowerCase() === 'id' ||
|
|
1423
|
+
a.name.toLowerCase().endsWith('_id');
|
|
1424
|
+
const bIsId = b.name.toLowerCase() === 'id' ||
|
|
1425
|
+
b.name.toLowerCase().endsWith('_id');
|
|
1426
|
+
if (aIsId && !bIsId)
|
|
1427
|
+
return 1;
|
|
1428
|
+
if (bIsId && !aIsId)
|
|
1429
|
+
return -1;
|
|
1430
|
+
return 0;
|
|
1431
|
+
});
|
|
1432
1432
|
if (pivot) {
|
|
1433
1433
|
// Do all of this to make sure we have the right unique columns when applying a pivot
|
|
1434
1434
|
let uniqueFormatted = {};
|
|
@@ -1439,7 +1439,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1439
1439
|
uniqueFormatted[pivot.columnField] = uniqueRecords;
|
|
1440
1440
|
const pivotedData = generatePivotTable(pivot, data2.rows, [null, null, null], false);
|
|
1441
1441
|
console.info(`%c[Pivot]: ${JSON.stringify(pivot)}`, 'color: dimgray');
|
|
1442
|
-
setPivotData(pivotedData);
|
|
1442
|
+
setPivotData(pivotedData || []);
|
|
1443
1443
|
setRows(data2.rows);
|
|
1444
1444
|
setFields(data2.fields);
|
|
1445
1445
|
}
|
|
@@ -1562,8 +1562,35 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1562
1562
|
}
|
|
1563
1563
|
return false;
|
|
1564
1564
|
};
|
|
1565
|
-
const
|
|
1566
|
-
|
|
1565
|
+
const getDistinctValues = async (table, overrideSchema) => {
|
|
1566
|
+
const schemaInfo = overrideSchema || schemaTables;
|
|
1567
|
+
const tableInfo = schemaInfo.find((tableInfo) => tableInfo.name === table);
|
|
1568
|
+
if (tableInfo) {
|
|
1569
|
+
const pendingFetches = [];
|
|
1570
|
+
for (let column of tableInfo.columns) {
|
|
1571
|
+
if (!isTextColumnType(column.fieldType))
|
|
1572
|
+
continue;
|
|
1573
|
+
const fetchPromise = fetchDistinctHelper(column.name, tableInfo.displayName);
|
|
1574
|
+
pendingFetches.push(fetchPromise);
|
|
1575
|
+
}
|
|
1576
|
+
const newUniqueValues = {};
|
|
1577
|
+
const resolvedPromises = await Promise.all(pendingFetches);
|
|
1578
|
+
for (const resolvedData of resolvedPromises) {
|
|
1579
|
+
if (resolvedData) {
|
|
1580
|
+
const { table, column, values } = resolvedData;
|
|
1581
|
+
if (!newUniqueValues[table]) {
|
|
1582
|
+
newUniqueValues[table] = {};
|
|
1583
|
+
}
|
|
1584
|
+
newUniqueValues[table][column] = values;
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
if (hashCode(uniqueValues) !== hashCode(newUniqueValues)) {
|
|
1588
|
+
setUniqueValues(newUniqueValues);
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
};
|
|
1592
|
+
const handleAsk = async (overridePrompt = '') => {
|
|
1593
|
+
if (!aiPrompt && !overridePrompt) {
|
|
1567
1594
|
return;
|
|
1568
1595
|
}
|
|
1569
1596
|
try {
|
|
@@ -1582,7 +1609,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1582
1609
|
method: 'POST',
|
|
1583
1610
|
headers: { 'Content-Type': 'application/json' },
|
|
1584
1611
|
body: JSON.stringify({
|
|
1585
|
-
initialQuestion: aiPrompt,
|
|
1612
|
+
initialQuestion: aiPrompt || overridePrompt,
|
|
1586
1613
|
publicKey: client.publicKey,
|
|
1587
1614
|
}),
|
|
1588
1615
|
});
|
|
@@ -1630,11 +1657,14 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1630
1657
|
newAst = removeNonSelectedTableReferences(newAst, tableAlias ?? table);
|
|
1631
1658
|
// newAst = convertDateComparison(newAst); // TODO
|
|
1632
1659
|
ast = newAst; // so we fetch data for newAst later.
|
|
1660
|
+
if (table !== currentTable) {
|
|
1661
|
+
getDistinctValues(table);
|
|
1662
|
+
setCurrentTable(table);
|
|
1663
|
+
}
|
|
1633
1664
|
setPivotRowField(groupByPivot?.rowField);
|
|
1634
1665
|
setPivotColumnField(groupByPivot?.columnField);
|
|
1635
1666
|
setPivotValueField(groupByPivot?.valueField);
|
|
1636
1667
|
setPivotAggregation(groupByPivot?.aggregationType);
|
|
1637
|
-
setPivot(groupByPivot);
|
|
1638
1668
|
setSelectedColumns(deepCopy(newAst).columns?.map((column) => {
|
|
1639
1669
|
if (column.expr.type === 'column_ref') {
|
|
1640
1670
|
return `${table}.${column.expr.column}`;
|
|
@@ -1645,7 +1675,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1645
1675
|
return `${table}.${column.expr.value}`;
|
|
1646
1676
|
}));
|
|
1647
1677
|
if (groupByPivot) {
|
|
1648
|
-
setBaseAst(deepCopy({ ...newAst, orderby: null }));
|
|
1678
|
+
setBaseAst(deepCopy({ ...newAst, orderby: null, limit: null }));
|
|
1649
1679
|
}
|
|
1650
1680
|
else {
|
|
1651
1681
|
setBaseAst(deepCopy({ ...newAst }));
|
|
@@ -1654,8 +1684,6 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1654
1684
|
setTopLevelBinaryOperator(
|
|
1655
1685
|
// @ts-ignore
|
|
1656
1686
|
newAst?.where ? newAst?.where?.operator : 'AND');
|
|
1657
|
-
if (groupByPivot)
|
|
1658
|
-
return; // the useEffect will handle the rest
|
|
1659
1687
|
}
|
|
1660
1688
|
const res2 = await fetch('https://quill-344421.uc.r.appspot.com/patterns', {
|
|
1661
1689
|
method: 'POST',
|
|
@@ -1671,11 +1699,13 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1671
1699
|
const data2 = await res2.json();
|
|
1672
1700
|
if (data2.rows && data2.rows.length) {
|
|
1673
1701
|
const tables = getTableNames(newAst);
|
|
1674
|
-
const table = tables.length >= 1 ? tables[0] : initialTableName;
|
|
1675
1702
|
if (groupByPivot) {
|
|
1676
|
-
const pivotedData = generatePivotTable(
|
|
1703
|
+
const pivotedData = generatePivotTable(
|
|
1704
|
+
// @ts-ignore
|
|
1705
|
+
groupByPivot, data2.rows, [null, null, null], false);
|
|
1677
1706
|
console.info(`%c[Pivot]: ${JSON.stringify(groupByPivot)}`, 'color: dimgray');
|
|
1678
1707
|
setPivotData(pivotedData);
|
|
1708
|
+
setPivot(groupByPivot);
|
|
1679
1709
|
setRows(data2.rows);
|
|
1680
1710
|
setFields(data2.fields);
|
|
1681
1711
|
}
|
|
@@ -1685,6 +1715,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1685
1715
|
}
|
|
1686
1716
|
}
|
|
1687
1717
|
else {
|
|
1718
|
+
setPivotData([]);
|
|
1688
1719
|
setRows([]);
|
|
1689
1720
|
setFields([]);
|
|
1690
1721
|
}
|
|
@@ -1703,7 +1734,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1703
1734
|
}
|
|
1704
1735
|
catch (e) {
|
|
1705
1736
|
console.error(e);
|
|
1706
|
-
setErrorMessage(
|
|
1737
|
+
setErrorMessage(`Error: Couldn't process your request, please re-word your prompt.`);
|
|
1707
1738
|
}
|
|
1708
1739
|
finally {
|
|
1709
1740
|
setLoading(false);
|
|
@@ -1729,11 +1760,17 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1729
1760
|
clearAllState();
|
|
1730
1761
|
return;
|
|
1731
1762
|
}
|
|
1732
|
-
const newAst = { ...baseAst, columns };
|
|
1733
|
-
setBaseAst(
|
|
1763
|
+
const newAst = deepCopy({ ...baseAst, columns });
|
|
1764
|
+
setBaseAst(newAst);
|
|
1765
|
+
fetchSqlQuery(newAst);
|
|
1734
1766
|
};
|
|
1735
1767
|
function TopLevelBooleanSwitch({ node, keyPrefix, handleOperatorChange, }) {
|
|
1736
|
-
return (_jsx("div", { style: { width: 'fit-content' }, children: _jsx(Tabs, { defaultValue: node.operator, options: DEFAULT_TAB_OPTIONS, onValueChange: (value) =>
|
|
1768
|
+
return (_jsx("div", { style: { width: 'fit-content' }, children: _jsx(Tabs, { defaultValue: node.operator, options: DEFAULT_TAB_OPTIONS, onValueChange: (value) => {
|
|
1769
|
+
if (loading) {
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
handleOperatorChange(value, node, keyPrefix);
|
|
1773
|
+
} }) }));
|
|
1737
1774
|
}
|
|
1738
1775
|
const DraggableItem = ({ id, label, onDelete }) => {
|
|
1739
1776
|
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: id });
|
|
@@ -1741,7 +1778,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1741
1778
|
transform: DND_CSS.Transform.toString(transform),
|
|
1742
1779
|
transition,
|
|
1743
1780
|
};
|
|
1744
|
-
return (_jsx("div", { style: { ...style }, ref: setNodeRef, children: _jsx(DraggableColumn, { label: label, onDelete: onDelete, children: _jsx("div", { style: {
|
|
1781
|
+
return (_jsx("div", { style: { ...style }, ref: setNodeRef, children: _jsx(DraggableColumn, { label: snakeCaseToTitleCase(label), onDelete: onDelete, children: _jsx("div", { style: {
|
|
1745
1782
|
cursor: 'grab',
|
|
1746
1783
|
}, ...attributes, ...listeners, children: _jsx(HandleButton, {}) }) }) }));
|
|
1747
1784
|
};
|
|
@@ -1779,6 +1816,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1779
1816
|
};
|
|
1780
1817
|
const newAst = baseAst ? newBaseAst : fallbackAST;
|
|
1781
1818
|
setBaseAst(newAst);
|
|
1819
|
+
fetchSqlQuery(newAst);
|
|
1782
1820
|
}
|
|
1783
1821
|
}
|
|
1784
1822
|
const columnNamesInAst = baseAst?.columns.map((col) => {
|
|
@@ -1802,18 +1840,6 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1802
1840
|
gap: 8,
|
|
1803
1841
|
}, children: [columnNamesInAst.map((name) => (_jsx(DraggableItem, { id: name, label: name, onDelete: () => handleDeleteColumn(name) }, name))), columnNamesInAst?.length > 0 && _jsx("div", { style: { height: 6 } })] }) }) }));
|
|
1804
1842
|
}
|
|
1805
|
-
const allNumericColumns = getNumericColumns().map((column) => ({
|
|
1806
|
-
label: column.displayName,
|
|
1807
|
-
value: column.name,
|
|
1808
|
-
}));
|
|
1809
|
-
const allNonNumericColumns = getNonNumericColumns().map((column) => ({
|
|
1810
|
-
label: column.displayName,
|
|
1811
|
-
value: column.name,
|
|
1812
|
-
}));
|
|
1813
|
-
const allStringColumns = getStringColumns().map((column) => ({
|
|
1814
|
-
label: column.displayName,
|
|
1815
|
-
value: column.name,
|
|
1816
|
-
}));
|
|
1817
1843
|
if (loading) {
|
|
1818
1844
|
return (_jsxs("div", { style: {
|
|
1819
1845
|
display: 'flex',
|
|
@@ -1824,7 +1850,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1824
1850
|
if (!openPopover) {
|
|
1825
1851
|
setOpenPopover('AddColumnPopover');
|
|
1826
1852
|
}
|
|
1827
|
-
}, label: 'Select columns' }),
|
|
1853
|
+
}, label: 'Select columns' }), label: "Select columns", onClose: () => {
|
|
1828
1854
|
setIsPending(false);
|
|
1829
1855
|
setActiveEditItem(null);
|
|
1830
1856
|
setActivePath(null);
|
|
@@ -1833,7 +1859,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1833
1859
|
setActiveEditItem(null);
|
|
1834
1860
|
setActivePath(null);
|
|
1835
1861
|
setOpenPopover(null);
|
|
1836
|
-
}, orderedColumnNames: orderedColumnNames, setOrderedColumnNames: setOrderedColumnNames, selectedColumns: selectedColumns, setSelectedColumns: setSelectedColumns, isSelectedAllColumns: isSelectedAllColumns, clearAllState: clearAllState, nameToColumn: nameToColumn, baseAst: baseAst, setBaseAst:
|
|
1862
|
+
}, orderedColumnNames: orderedColumnNames, setOrderedColumnNames: setOrderedColumnNames, selectedColumns: selectedColumns, setSelectedColumns: setSelectedColumns, isSelectedAllColumns: isSelectedAllColumns, clearAllState: clearAllState, nameToColumn: nameToColumn, baseAst: baseAst, setBaseAst: (newAst) => {
|
|
1863
|
+
setBaseAst(newAst);
|
|
1864
|
+
fetchSqlQuery(newAst);
|
|
1865
|
+
}, pivot: pivot, initialTableName: initialTableName, defaultAST: defaultAST, defaultTable: defaultTable, setPivot: setPivot, TextInput: TextInput, SelectColumn: SelectColumn, SecondaryButton: SecondaryButton, Button: Button, HandleButton: HandleButton }) }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeading, { label: "Filters" }), _jsx("div", { style: { height: 4, width: '100%' } }), formData && (_jsx("div", { style: {
|
|
1837
1866
|
display: 'flex',
|
|
1838
1867
|
flexDirection: 'column',
|
|
1839
1868
|
gap: 8,
|
|
@@ -1844,6 +1873,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1844
1873
|
gap: 2.5,
|
|
1845
1874
|
alignItems: 'flex-start',
|
|
1846
1875
|
}, children: [_jsx(Popover, { isOpen: openPopover === 'AddFilterPopover', title: 'Add filter', trigger: _jsx(SecondaryButton, { onClick: () => {
|
|
1876
|
+
if (!selectedColumns || selectedColumns.length === 0) {
|
|
1877
|
+
return;
|
|
1878
|
+
}
|
|
1847
1879
|
if (!openPopover) {
|
|
1848
1880
|
const value = orderedColumnNames[0];
|
|
1849
1881
|
const [_table, column] = value.split('.');
|
|
@@ -1930,14 +1962,18 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1930
1962
|
} }) }))] }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeading, { label: "Pivot" }), _jsx("div", { style: { height: 4, width: '100%' } }), _jsx(PivotModal, { pivotRowField: pivotRowField, setPivotRowField: setPivotRowField, pivotColumnField: pivotColumnField, setPivotColumnField: setPivotColumnField, pivotValueField: pivotValueField, setPivotValueField: setPivotValueField, pivotAggregation: pivotAggregation, setPivotAggregation: setPivotAggregation, createdPivots: createdPivots, setCreatedPivots: setCreatedPivots, recommendedPivots: recommendedPivots, setRecommendedPivots: setRecommendedPivots, popUpTitle: pivotPopUpTitle, setPopUpTitle: setPivotPopUpTitle, selectedTable: initialTableName, SelectComponent: Select, ButtonComponent: Button, PopoverComponent: PivotPopover, TextComponent: Text, isOpen: showPivotPopover, setIsOpen: setShowPivotPopover, showUpdatePivot: isEdittingPivot, setShowUpdatePivot: setIsEdittingPivot, parentRef: parentRef, data: rows, columns: processColumnsForChartBuilder(Object.keys(rows[0] ?? {})), triggerButtonText: 'Add pivot', selectedPivotIndex: selectedPivotIndex, setSelectedPivotIndex: setSelectedPivotIndex, removePivot: () => {
|
|
1931
1963
|
setPivot(null);
|
|
1932
1964
|
setPivotData(null);
|
|
1933
|
-
},
|
|
1965
|
+
},
|
|
1966
|
+
// TODOs
|
|
1967
|
+
selectPivot: (pivot) => {
|
|
1934
1968
|
if (!pivot)
|
|
1935
1969
|
return;
|
|
1936
1970
|
const newAst = { ...baseAst };
|
|
1937
1971
|
newAst.orderby = null;
|
|
1938
1972
|
setBaseAst(newAst); // trigger refetch
|
|
1939
1973
|
setPivot(pivot);
|
|
1940
|
-
|
|
1974
|
+
const pivotedData = generatePivotTable(pivot, rows, [null, null, null], false);
|
|
1975
|
+
setPivotData(pivotedData || []);
|
|
1976
|
+
}, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent: Label, HeaderComponent: Header, dateRange: [null, null, null], recommendPivotCount: 3, SecondaryButtonComponent: SecondaryButton }), pivot && (_jsx(PivotCard, { pivotTable: {
|
|
1941
1977
|
pivot: pivot,
|
|
1942
1978
|
rows: pivotData?.rows || [],
|
|
1943
1979
|
columns: pivotData?.columns || [],
|
|
@@ -1964,10 +2000,16 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1964
2000
|
}, columns: selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover: SortPopover, EditPopover: AddSortPopover, handleDelete: () => {
|
|
1965
2001
|
setPivot({ ...pivot, sort: false });
|
|
1966
2002
|
setBaseAst(deepCopy(baseAst));
|
|
2003
|
+
if (!pivot) {
|
|
2004
|
+
fetchSqlQuery(baseAst);
|
|
2005
|
+
}
|
|
1967
2006
|
}, onSave: (column, direction) => {
|
|
1968
2007
|
setPivot({ ...pivot, sort: true, sortDirection: direction });
|
|
1969
2008
|
setOpenPopover(null);
|
|
1970
2009
|
setBaseAst(deepCopy(baseAst));
|
|
2010
|
+
if (!pivot) {
|
|
2011
|
+
fetchSqlQuery(baseAst);
|
|
2012
|
+
}
|
|
1971
2013
|
} }, `sort-sentence-pivot`) })), baseAst && baseAst.orderby && (_jsx("div", { style: {
|
|
1972
2014
|
display: 'flex',
|
|
1973
2015
|
flexDirection: 'column',
|
|
@@ -1992,11 +2034,17 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1992
2034
|
setActivePath(null);
|
|
1993
2035
|
setOpenPopover(null);
|
|
1994
2036
|
setBaseAst(deepCopy(newAst));
|
|
2037
|
+
if (!pivot) {
|
|
2038
|
+
fetchSqlQuery(newAst);
|
|
2039
|
+
}
|
|
1995
2040
|
}, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover: SortPopover, EditPopover: AddSortPopover, handleDelete: () => {
|
|
1996
2041
|
const newAst = { ...baseAst };
|
|
1997
2042
|
newAst.orderby.splice(id, 1);
|
|
1998
2043
|
setBaseAst(deepCopy(newAst));
|
|
1999
|
-
|
|
2044
|
+
if (!pivot) {
|
|
2045
|
+
fetchSqlQuery(newAst);
|
|
2046
|
+
}
|
|
2047
|
+
} }, `sort-sentence-${id}`))) })), _jsx(Popover, { isOpen: openPopover === 'AddSortPopover', setIsOpen: () => { }, trigger: _jsx(SecondaryButton, { onClick: () => {
|
|
2000
2048
|
if (!openPopover) {
|
|
2001
2049
|
setOpenPopover('AddSortPopover');
|
|
2002
2050
|
}
|
|
@@ -2005,18 +2053,51 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2005
2053
|
setActiveEditItem(null);
|
|
2006
2054
|
setActivePath(null);
|
|
2007
2055
|
setOpenPopover(null);
|
|
2008
|
-
}, children: _jsx(AddSortPopover, { columns: selectedColumns, Select: Select, Button: Button, onSave: () => { } }) })
|
|
2056
|
+
}, children: _jsx(AddSortPopover, { columns: selectedColumns, Select: Select, Button: Button, onSave: () => { } }) }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeading, { label: "Limit" }), _jsx("div", { style: { height: 4, width: '100%' } }), baseAst && baseAst.limit ? (_jsx("div", { style: {
|
|
2057
|
+
display: 'flex',
|
|
2058
|
+
flexDirection: 'column',
|
|
2059
|
+
gap: 8,
|
|
2060
|
+
marginBottom: 12,
|
|
2061
|
+
}, children: _jsx(LimitSentence, { limit: baseAst.limit, setOpenPopover: setOpenPopover, LimitPopover: SortPopover, EditPopover: AddLimitPopover, handleDelete: () => {
|
|
2062
|
+
const newAst = { ...baseAst };
|
|
2063
|
+
newAst.limit = null;
|
|
2064
|
+
setBaseAst(deepCopy(newAst));
|
|
2065
|
+
fetchSqlQuery(newAst);
|
|
2066
|
+
}, onSave: (limit) => {
|
|
2067
|
+
const newAst = { ...baseAst };
|
|
2068
|
+
newAst.limit = {
|
|
2069
|
+
seperator: '',
|
|
2070
|
+
value: [
|
|
2071
|
+
{
|
|
2072
|
+
type: 'number',
|
|
2073
|
+
value: limit,
|
|
2074
|
+
},
|
|
2075
|
+
],
|
|
2076
|
+
};
|
|
2077
|
+
setOpenPopover(null);
|
|
2078
|
+
setBaseAst(deepCopy(newAst));
|
|
2079
|
+
fetchSqlQuery(newAst);
|
|
2080
|
+
} }) })) : (_jsx(Popover, { isOpen: openPopover === 'AddLimitPopover', setIsOpen: () => { }, trigger: _jsx(SecondaryButton, { onClick: () => {
|
|
2081
|
+
if (!openPopover) {
|
|
2082
|
+
setOpenPopover('AddLimitPopover');
|
|
2083
|
+
}
|
|
2084
|
+
}, label: 'Add limit' }), title: "Limit", onClose: () => {
|
|
2085
|
+
setIsPending(false);
|
|
2086
|
+
setActiveEditItem(null);
|
|
2087
|
+
setActivePath(null);
|
|
2088
|
+
setOpenPopover(null);
|
|
2089
|
+
}, children: _jsx(TextInput, { value: 0, type: "number", style: { width: 120, minHeight: 32 }, onChange: (e) => { } }) }))] }), _jsxs(Container, { children: [!hideAi && (_jsxs("form", { onSubmit: (event) => {
|
|
2009
2090
|
event.preventDefault();
|
|
2010
2091
|
}, style: {
|
|
2011
2092
|
display: 'flex',
|
|
2012
2093
|
flexDirection: 'row',
|
|
2013
2094
|
gap: 12,
|
|
2014
2095
|
padding: 1,
|
|
2015
|
-
}, children: [_jsx(TextInput, { placeholder:
|
|
2096
|
+
}, children: [_jsx(TextInput, { placeholder: baseAst ? 'Ask a follow-up question...' : 'Ask a question...', type: "text", style: { width: '100%', fontSize: 14 }, value: aiPrompt }), _jsx(Button, { onClick: () => { }, label: 'Ask AI' }), baseAst && (_jsx(SecondaryButton, { onClick: clearAllState, label: "New report" }))] })), _jsxs(_Fragment, { children: [_jsx(TableLoadingState, {}), _jsxs("div", { style: {
|
|
2016
2097
|
display: 'flex',
|
|
2017
2098
|
flexDirection: 'row',
|
|
2018
2099
|
gap: '12px',
|
|
2019
|
-
}, children: [_jsx("div", { style: { width: '100%' } }), _jsx(SecondaryButton, { onClick: () => copyToClipboard(activeQuery), label: isCopying ? '✅ Copied' : 'Copy SQL' }), _jsx(Button, { label: 'Add to dashboard', onClick: () => { } })] })] })
|
|
2100
|
+
}, children: [_jsx("div", { style: { width: '100%' } }), _jsx(SecondaryButton, { onClick: () => copyToClipboard(activeQuery), label: isCopying ? '✅ Copied' : 'Copy SQL' }), _jsx(Button, { label: 'Add to dashboard', onClick: () => { } })] })] })] }), _jsx("style", { children: `body{margin:0;}` })] }));
|
|
2020
2101
|
}
|
|
2021
2102
|
return (_jsxs("div", { ref: parentRef, style: {
|
|
2022
2103
|
display: 'flex',
|
|
@@ -2041,7 +2122,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2041
2122
|
setActiveEditItem(null);
|
|
2042
2123
|
setActivePath(null);
|
|
2043
2124
|
setOpenPopover(null);
|
|
2044
|
-
}, orderedColumnNames: orderedColumnNames, setOrderedColumnNames: setOrderedColumnNames, selectedColumns: selectedColumns, setSelectedColumns: setSelectedColumns, isSelectedAllColumns: isSelectedAllColumns, clearAllState: clearAllState, nameToColumn: nameToColumn, baseAst: baseAst, setBaseAst:
|
|
2125
|
+
}, orderedColumnNames: orderedColumnNames, setOrderedColumnNames: setOrderedColumnNames, selectedColumns: selectedColumns, setSelectedColumns: setSelectedColumns, isSelectedAllColumns: isSelectedAllColumns, clearAllState: clearAllState, nameToColumn: nameToColumn, baseAst: baseAst, setBaseAst: (ast) => {
|
|
2126
|
+
setBaseAst(ast);
|
|
2127
|
+
fetchSqlQuery(ast);
|
|
2128
|
+
}, pivot: pivot, initialTableName: initialTableName, defaultAST: defaultAST, defaultTable: defaultTable, setPivot: setPivot, TextInput: TextInput, SelectColumn: SelectColumn, SecondaryButton: SecondaryButton, Button: Button, HandleButton: HandleButton }) }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeading, { label: "Filters" }), _jsx("div", { style: { height: 4, width: '100%' } }), formData && (_jsx("div", { style: {
|
|
2045
2129
|
display: 'flex',
|
|
2046
2130
|
flexDirection: 'column',
|
|
2047
2131
|
gap: 8,
|
|
@@ -2052,6 +2136,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2052
2136
|
gap: 2.5,
|
|
2053
2137
|
alignItems: 'flex-start',
|
|
2054
2138
|
}, children: [_jsx(Popover, { title: 'Add filter', isOpen: openPopover === 'AddFilterPopover', trigger: _jsx(SecondaryButton, { onClick: () => {
|
|
2139
|
+
if (!selectedColumns || selectedColumns.length === 0) {
|
|
2140
|
+
return;
|
|
2141
|
+
}
|
|
2055
2142
|
if (!openPopover) {
|
|
2056
2143
|
const value = orderedColumnNames[0];
|
|
2057
2144
|
const [_table, column] = value.split('.');
|
|
@@ -2137,7 +2224,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2137
2224
|
setOpenPopover(null);
|
|
2138
2225
|
clearCheckboxes();
|
|
2139
2226
|
}
|
|
2140
|
-
} }) }))] }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeading, { label: "Pivot" }), _jsx("div", { style: { height: 4, width: '100%' } }), _jsx(PivotModal, { pivotRowField: pivotRowField, setPivotRowField: setPivotRowField, pivotColumnField: pivotColumnField, setPivotColumnField: setPivotColumnField, pivotValueField: pivotValueField, setPivotValueField: setPivotValueField, pivotAggregation: pivotAggregation, setPivotAggregation: setPivotAggregation, createdPivots: createdPivots, setCreatedPivots: setCreatedPivots, recommendedPivots: recommendedPivots, setRecommendedPivots: setRecommendedPivots, popUpTitle: pivotPopUpTitle, setPopUpTitle: setPivotPopUpTitle, selectedTable: initialTableName, SelectComponent: Select, ButtonComponent: Button, PopoverComponent: PivotPopover, TextComponent: Text, isOpen: showPivotPopover, setIsOpen: setShowPivotPopover, showUpdatePivot: isEdittingPivot, setShowUpdatePivot: setIsEdittingPivot, parentRef: parentRef, data: rows, columns: processColumnsForChartBuilder(Object.keys(rows[0] ?? {})), triggerButtonText: 'Add pivot', selectedPivotIndex: selectedPivotIndex, setSelectedPivotIndex: setSelectedPivotIndex, removePivot: () => {
|
|
2227
|
+
} }) }))] }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeading, { label: "Pivot" }), _jsx("div", { style: { height: 4, width: '100%' } }), _jsx(PivotModal, { pivotRowField: pivotRowField, setPivotRowField: setPivotRowField, pivotColumnField: pivotColumnField, setPivotColumnField: setPivotColumnField, pivotValueField: pivotValueField, setPivotValueField: setPivotValueField, pivotAggregation: pivotAggregation, setPivotAggregation: setPivotAggregation, createdPivots: createdPivots, setCreatedPivots: setCreatedPivots, recommendedPivots: recommendedPivots, setRecommendedPivots: setRecommendedPivots, popUpTitle: pivotPopUpTitle, setPopUpTitle: setPivotPopUpTitle, selectedTable: initialTableName, SelectComponent: Select, ButtonComponent: Button, SecondaryButtonComponent: SecondaryButton, PopoverComponent: PivotPopover, TextComponent: Text, isOpen: showPivotPopover, setIsOpen: setShowPivotPopover, showUpdatePivot: isEdittingPivot, setShowUpdatePivot: setIsEdittingPivot, parentRef: parentRef, data: rows, columns: processColumnsForChartBuilder(Object.keys(rows[0] ?? {})), triggerButtonText: 'Add pivot', selectedPivotIndex: selectedPivotIndex, setSelectedPivotIndex: setSelectedPivotIndex, removePivot: () => {
|
|
2141
2228
|
setPivot(null);
|
|
2142
2229
|
setPivotData(null);
|
|
2143
2230
|
}, selectPivot: (pivot) => {
|
|
@@ -2151,7 +2238,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2151
2238
|
}
|
|
2152
2239
|
setBaseAst(newAst); // trigger refetch
|
|
2153
2240
|
setPivot(pivot);
|
|
2154
|
-
|
|
2241
|
+
const pivotedData = generatePivotTable(pivot, rows, [null, null, null], false);
|
|
2242
|
+
setPivotData(pivotedData || []);
|
|
2243
|
+
}, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent: Label, HeaderComponent: Header, dateRange: [null, null, null], recommendPivotCount: 3 }), pivot && (_jsx(PivotCard, { pivotTable: {
|
|
2155
2244
|
pivot: pivot,
|
|
2156
2245
|
rows: pivotData?.rows || [],
|
|
2157
2246
|
columns: pivotData?.columns || [],
|
|
@@ -2166,7 +2255,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2166
2255
|
}, selectedPivotIndex: -1, onEditPivot: () => { }, ButtonComponent: Button, HeaderComponent: Header, showEdit: false, onClose: () => {
|
|
2167
2256
|
setPivot(null);
|
|
2168
2257
|
setPivotData(null);
|
|
2169
|
-
setBaseAst(deepCopy(baseAst));
|
|
2258
|
+
setBaseAst(deepCopy(baseAst));
|
|
2170
2259
|
}, minHeight: 180, LabelComponent: Label, TextComponent: Text })), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeading, { label: "Sort" }), _jsx("div", { style: { height: 4, width: '100%' } }), pivot && pivot.sort && (_jsx("div", { style: {
|
|
2171
2260
|
display: 'flex',
|
|
2172
2261
|
flexDirection: 'column',
|
|
@@ -2175,13 +2264,25 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2175
2264
|
}, children: _jsx(SortSentence, { sortData: {
|
|
2176
2265
|
type: pivot.sortDirection,
|
|
2177
2266
|
expr: { type: 'column_ref', column: pivot.rowField },
|
|
2178
|
-
}, columns: selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover: SortPopover, EditPopover: AddSortPopover, handleDelete: () => {
|
|
2179
|
-
|
|
2267
|
+
}, columns: pivot ? [`.${pivot.rowField}`] : selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover: SortPopover, EditPopover: AddSortPopover, handleDelete: () => {
|
|
2268
|
+
if (pivot) {
|
|
2269
|
+
setPivot({ ...pivot, sort: false });
|
|
2270
|
+
const pivotedData = generatePivotTable({ ...pivot, sort: false }, rows, [null, null, null], false);
|
|
2271
|
+
setPivotData(pivotedData || []);
|
|
2272
|
+
return;
|
|
2273
|
+
}
|
|
2180
2274
|
setBaseAst(deepCopy(baseAst));
|
|
2275
|
+
fetchSqlQuery(deepCopy(baseAst));
|
|
2181
2276
|
}, onSave: (column, direction) => {
|
|
2182
|
-
|
|
2277
|
+
if (pivot) {
|
|
2278
|
+
setPivot({ ...pivot, sort: true, sortDirection: direction });
|
|
2279
|
+
const pivotedData = generatePivotTable({ ...pivot, sort: true, sortDirection: direction }, rows, [null, null, null], false);
|
|
2280
|
+
setPivotData(pivotedData || []);
|
|
2281
|
+
return;
|
|
2282
|
+
}
|
|
2183
2283
|
setOpenPopover(null);
|
|
2184
2284
|
setBaseAst(deepCopy(baseAst));
|
|
2285
|
+
fetchSqlQuery(deepCopy(baseAst));
|
|
2185
2286
|
} }, `sort-sentence-pivot`) })), baseAst && baseAst.orderby && (_jsx("div", { style: {
|
|
2186
2287
|
display: 'flex',
|
|
2187
2288
|
flexDirection: 'column',
|
|
@@ -2195,6 +2296,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2195
2296
|
const newAst = { ...baseAst };
|
|
2196
2297
|
newAst.orderby.splice(id, 1);
|
|
2197
2298
|
setBaseAst(deepCopy(newAst));
|
|
2299
|
+
fetchSqlQuery(deepCopy(newAst));
|
|
2198
2300
|
}, onSave: (column, direction) => {
|
|
2199
2301
|
if (pivot) {
|
|
2200
2302
|
setPivot({
|
|
@@ -2222,6 +2324,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2222
2324
|
setActivePath(null);
|
|
2223
2325
|
setOpenPopover(null);
|
|
2224
2326
|
setBaseAst(deepCopy(newAst));
|
|
2327
|
+
fetchSqlQuery(deepCopy(newAst));
|
|
2225
2328
|
} }, `sort-sentence-${id}`))) })), _jsx(Popover, { isOpen: openPopover === 'AddSortPopover', trigger: _jsx(SecondaryButton, { onClick: () => {
|
|
2226
2329
|
if (!openPopover) {
|
|
2227
2330
|
setOpenPopover('AddSortPopover');
|
|
@@ -2236,6 +2339,8 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2236
2339
|
return;
|
|
2237
2340
|
if (pivot) {
|
|
2238
2341
|
setPivot({ ...pivot, sort: true, sortDirection: direction });
|
|
2342
|
+
const pivotedData = generatePivotTable({ ...pivot, sort: true, sortDirection: direction }, rows, [null, null, null], false);
|
|
2343
|
+
setPivotData(pivotedData || []);
|
|
2239
2344
|
setActivePath(null);
|
|
2240
2345
|
setOpenPopover(null);
|
|
2241
2346
|
setBaseAst(deepCopy(baseAst));
|
|
@@ -2252,7 +2357,58 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2252
2357
|
setActivePath(null);
|
|
2253
2358
|
setOpenPopover(null);
|
|
2254
2359
|
setBaseAst(deepCopy(newAst));
|
|
2255
|
-
|
|
2360
|
+
fetchSqlQuery(deepCopy(newAst));
|
|
2361
|
+
} }) }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeading, { label: "Limit" }), _jsx("div", { style: { height: 4, width: '100%' } }), baseAst && baseAst.limit ? (_jsx("div", { style: {
|
|
2362
|
+
display: 'flex',
|
|
2363
|
+
flexDirection: 'column',
|
|
2364
|
+
gap: 8,
|
|
2365
|
+
marginBottom: 12,
|
|
2366
|
+
}, children: _jsx(LimitSentence, { limit: baseAst.limit, setOpenPopover: setOpenPopover, LimitPopover: SortPopover, EditPopover: AddLimitPopover, handleDelete: () => {
|
|
2367
|
+
const newAst = { ...baseAst };
|
|
2368
|
+
newAst.limit = null;
|
|
2369
|
+
setBaseAst(deepCopy(newAst));
|
|
2370
|
+
fetchSqlQuery(deepCopy(newAst));
|
|
2371
|
+
}, onSave: (limit) => {
|
|
2372
|
+
const newAst = { ...baseAst };
|
|
2373
|
+
newAst.limit = {
|
|
2374
|
+
seperator: '',
|
|
2375
|
+
value: [
|
|
2376
|
+
{
|
|
2377
|
+
type: 'number',
|
|
2378
|
+
value: limit,
|
|
2379
|
+
},
|
|
2380
|
+
],
|
|
2381
|
+
};
|
|
2382
|
+
setOpenPopover(null);
|
|
2383
|
+
setBaseAst(deepCopy(newAst));
|
|
2384
|
+
fetchSqlQuery(deepCopy(newAst));
|
|
2385
|
+
} }) })) : (_jsx(Popover, { isOpen: openPopover === 'AddLimitPopover', setIsOpen: () => { }, trigger: _jsx(SecondaryButton, { onClick: () => {
|
|
2386
|
+
if (!baseAst) {
|
|
2387
|
+
return;
|
|
2388
|
+
}
|
|
2389
|
+
if (!openPopover) {
|
|
2390
|
+
setOpenPopover('AddLimitPopover');
|
|
2391
|
+
}
|
|
2392
|
+
}, label: 'Add limit' }), title: "Limit", onClose: () => {
|
|
2393
|
+
setIsPending(false);
|
|
2394
|
+
setActiveEditItem(null);
|
|
2395
|
+
setActivePath(null);
|
|
2396
|
+
setOpenPopover(null);
|
|
2397
|
+
}, children: _jsx(AddLimitPopover, { TextInput: TextInput, onSave: (limit) => {
|
|
2398
|
+
const newAst = { ...baseAst };
|
|
2399
|
+
newAst.limit = {
|
|
2400
|
+
seperator: '',
|
|
2401
|
+
value: [
|
|
2402
|
+
{
|
|
2403
|
+
type: 'number',
|
|
2404
|
+
value: Number(limit),
|
|
2405
|
+
},
|
|
2406
|
+
],
|
|
2407
|
+
};
|
|
2408
|
+
setOpenPopover(null);
|
|
2409
|
+
setBaseAst(deepCopy(newAst));
|
|
2410
|
+
fetchSqlQuery(deepCopy(newAst));
|
|
2411
|
+
} }) }))] }), _jsxs(Container, { children: [!hideAi && (_jsxs("form", { onSubmit: (event) => {
|
|
2256
2412
|
event.preventDefault();
|
|
2257
2413
|
handleAsk();
|
|
2258
2414
|
}, style: {
|
|
@@ -2263,9 +2419,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2263
2419
|
}, children: [_jsx(TextInput, { type: "text", value: aiPrompt, style: { width: '100%', fontSize: 14 }, onChange: (e) => setAiPrompt(e.target.value), placeholder: baseAst ? 'Ask a follow-up question...' : 'Ask a question...' }), _jsx(Button, { onClick: handleAsk, label: 'Ask AI' }), baseAst && (_jsx(SecondaryButton, { label: 'New report', onClick: clearAllState }))] })), baseAst && (_jsx(_Fragment, { children: loading && errorMessage.length === 0 ? (_jsx(TableLoadingState, {})) : (_jsx(Table, { rows: applyFormatting({
|
|
2264
2420
|
rows: pivotData?.rows || rows,
|
|
2265
2421
|
fields: pivotData?.fields || fields,
|
|
2266
|
-
}, baseAst?.columns ?? []), columns:
|
|
2267
|
-
|
|
2268
|
-
|
|
2422
|
+
}, baseAst?.columns ?? []), columns: pivot
|
|
2423
|
+
? pivotData?.columns || emptyPivotColumns()
|
|
2424
|
+
: enforceOrderOnColumns(Object.keys(rows[0] ?? {})).map((c) => {
|
|
2425
|
+
return { label: snakeCaseToTitleCase(c), field: c };
|
|
2269
2426
|
}), error: errorMessage, rowsPerPage: 20 })) })), _jsxs("div", { style: {
|
|
2270
2427
|
display: 'flex',
|
|
2271
2428
|
flexDirection: 'row',
|