@quillsql/react 2.11.13 → 2.11.15

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 (37) hide show
  1. package/dist/cjs/ReportBuilder.d.ts.map +1 -1
  2. package/dist/cjs/ReportBuilder.js +206 -139
  3. package/dist/cjs/components/Dashboard/MetricComponent.js +2 -2
  4. package/dist/cjs/components/QuillCard.d.ts.map +1 -1
  5. package/dist/cjs/components/QuillCard.js +2 -4
  6. package/dist/cjs/components/QuillTable.d.ts.map +1 -1
  7. package/dist/cjs/components/QuillTable.js +2 -2
  8. package/dist/cjs/components/ReportBuilder/AddSortPopover.js +2 -2
  9. package/dist/cjs/components/ReportBuilder/convert.d.ts.map +1 -1
  10. package/dist/cjs/components/ReportBuilder/convert.js +38 -12
  11. package/dist/cjs/components/ReportBuilder/ui.d.ts.map +1 -1
  12. package/dist/cjs/components/ReportBuilder/ui.js +14 -2
  13. package/dist/cjs/components/UiComponents.d.ts.map +1 -1
  14. package/dist/cjs/components/UiComponents.js +14 -9
  15. package/dist/cjs/internals/ReportBuilder/PivotList.d.ts.map +1 -1
  16. package/dist/cjs/internals/ReportBuilder/PivotList.js +28 -2
  17. package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
  18. package/dist/cjs/internals/ReportBuilder/PivotModal.js +23 -3
  19. package/dist/esm/ReportBuilder.d.ts.map +1 -1
  20. package/dist/esm/ReportBuilder.js +206 -139
  21. package/dist/esm/components/Dashboard/MetricComponent.js +2 -2
  22. package/dist/esm/components/QuillCard.d.ts.map +1 -1
  23. package/dist/esm/components/QuillCard.js +2 -4
  24. package/dist/esm/components/QuillTable.d.ts.map +1 -1
  25. package/dist/esm/components/QuillTable.js +2 -2
  26. package/dist/esm/components/ReportBuilder/AddSortPopover.js +2 -2
  27. package/dist/esm/components/ReportBuilder/convert.d.ts.map +1 -1
  28. package/dist/esm/components/ReportBuilder/convert.js +38 -12
  29. package/dist/esm/components/ReportBuilder/ui.d.ts.map +1 -1
  30. package/dist/esm/components/ReportBuilder/ui.js +14 -2
  31. package/dist/esm/components/UiComponents.d.ts.map +1 -1
  32. package/dist/esm/components/UiComponents.js +14 -9
  33. package/dist/esm/internals/ReportBuilder/PivotList.d.ts.map +1 -1
  34. package/dist/esm/internals/ReportBuilder/PivotList.js +28 -2
  35. package/dist/esm/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
  36. package/dist/esm/internals/ReportBuilder/PivotModal.js +23 -3
  37. package/package.json +1 -1
@@ -60,6 +60,8 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
60
60
  const [showPivotPopover, setShowPivotPopover] = useState(false);
61
61
  const [isEdittingPivot, setIsEdittingPivot] = useState(false);
62
62
  const [selectedPivotIndex, setSelectedPivotIndex] = useState(-1);
63
+ const [initialLoad, setInitialLoad] = useState(true);
64
+ const [currentTable, setCurrentTable] = useState(initialTableName || '');
63
65
  const parentRef = useRef(null);
64
66
  const [theme] = useContext(ThemeContext);
65
67
  const [pivotRowField, setPivotRowField] = useState(undefined);
@@ -180,7 +182,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
180
182
  }
181
183
  setUniqueValues(newValues);
182
184
  };
183
- const fetchSqlQuery = async () => {
185
+ const fetchSqlQuery = async (ast, formData) => {
186
+ setLoading(true);
187
+ setErrorMessage('');
184
188
  try {
185
189
  const response = await fetch(`https://quill-344421.uc.r.appspot.com/sqlify`, {
186
190
  method: 'POST',
@@ -188,32 +192,19 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
188
192
  'Content-Type': 'application/json',
189
193
  },
190
194
  body: JSON.stringify({
191
- ast: { ...baseAst, where: formData },
195
+ ast: { ...ast, where: formData },
192
196
  publicKey: client.publicKey,
193
197
  }),
194
198
  });
195
199
  const data = await response.json();
196
200
  setActiveQuery(data.query);
197
- fetchUponChange();
201
+ fetchUponChange(ast, formData);
198
202
  }
199
203
  catch (error) {
204
+ setLoading(false);
200
205
  console.error(error);
201
206
  }
202
207
  };
203
- useEffect(() => {
204
- setErrorMessage('');
205
- if (baseAst || formData) {
206
- fetchSqlQuery();
207
- }
208
- }, [baseAst]);
209
- // Returns an array of all the column names in the pivot config
210
- // if there are any, otherwise returns [].
211
- const getColumnsInPivot = () => {
212
- if (!pivot)
213
- return [];
214
- const { valueField, rowField, columnField } = pivot;
215
- return [valueField, rowField, columnField].filter(Boolean);
216
- };
217
208
  // It's just like getColumnsInPivot but we expand the columnField
218
209
  // if there is one to include all the variants just like it would
219
210
  // show up in the table. (eg. category -> ...[Fuel, Food, Other])
@@ -232,43 +223,38 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
232
223
  result.push(valueField, rowField);
233
224
  return result.filter(Boolean);
234
225
  };
235
- useEffect(() => {
236
- if (errorMessage) {
237
- console.error(errorMessage);
238
- }
239
- }, [errorMessage]);
240
- useEffect(() => {
241
- const fetchDistinctHelper = async (column, table) => {
242
- try {
243
- const query = `SELECT DISTINCT ${column} FROM ${table};`;
244
- const response = await fetch(`https://quill-344421.uc.r.appspot.com/dashquery`, {
245
- method: 'POST',
246
- headers: {
247
- 'Content-Type': 'application/json',
248
- },
249
- body: JSON.stringify({
250
- orgId: client.customerId,
251
- publicKey: client.publicKey,
252
- query: query,
253
- }),
254
- });
255
- const data = await response.json();
256
- if (data.errorMessage) {
257
- // console.error(data.errorMessage);
258
- return null;
259
- }
260
- const options = data.rows.map((r) => r[column]);
261
- const newCheckboxValues = options.reduce((obj, col) => {
262
- obj[col] = false;
263
- return obj;
264
- }, {});
265
- return { table, column, values: newCheckboxValues };
266
- }
267
- catch (e) {
268
- console.error(e);
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);
269
243
  return null;
270
244
  }
271
- };
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;
255
+ }
256
+ };
257
+ useEffect(() => {
272
258
  const fetchSchema = async () => {
273
259
  try {
274
260
  const response = await fetch(`${client.queryEndpoint}`, {
@@ -301,31 +287,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
301
287
  return -1;
302
288
  return 0;
303
289
  })));
304
- // Fetch all the unique values in parallel
305
- const pendingFetches = [];
306
- for (let table of tables ?? []) {
307
- for (let column of table.columns) {
308
- if (!isTextColumnType(column.fieldType))
309
- continue;
310
- const fetchPromise = fetchDistinctHelper(column.name, table.displayName);
311
- pendingFetches.push(fetchPromise);
312
- }
313
- }
314
- const newUniqueValues = {};
315
- const resolvedPromises = await Promise.all(pendingFetches);
316
- for (const resolvedData of resolvedPromises) {
317
- if (resolvedData) {
318
- const { table, column, values } = resolvedData;
319
- if (!newUniqueValues[table]) {
320
- newUniqueValues[table] = {};
321
- }
322
- newUniqueValues[table][column] = values;
323
- }
324
- }
325
- if (hashCode(uniqueValues) !== hashCode(newUniqueValues)) {
326
- setUniqueValues(newUniqueValues);
327
- }
328
- if (initialTableName) {
290
+ if (initialTableName && initialLoad) {
291
+ setInitialLoad(false);
292
+ setLoading(true);
293
+ await getDistinctValues(initialTableName, tables);
329
294
  const columnsForTable = tables
330
295
  .find((t) => t.name === initialTableName)
331
296
  ?.columns.map((c) => c.name);
@@ -353,7 +318,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
353
318
  const paths = globalPath.split('.').filter((p) => p);
354
319
  if (paths.length === 0 && !isInsertion && !isReplaceSubtree) {
355
320
  setFormData(null);
356
- setBaseAst(deepCopy({
321
+ const newAst = deepCopy({
357
322
  ...defaultAST,
358
323
  ...baseAst,
359
324
  ...(!baseAst?.columns && {
@@ -367,12 +332,13 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
367
332
  from: [{ ...defaultTable, table: initialTableName }],
368
333
  }),
369
334
  where: null,
370
- }));
335
+ });
336
+ setBaseAst(newAst);
337
+ fetchSqlQuery(newAst, null);
371
338
  return;
372
339
  }
373
340
  if (!formData && isInsertion) {
374
- setFormData(value);
375
- setBaseAst(deepCopy({
341
+ const newAst = deepCopy({
376
342
  ...defaultAST,
377
343
  ...baseAst,
378
344
  ...(!baseAst?.columns && {
@@ -386,7 +352,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
386
352
  from: [{ ...defaultTable, table: initialTableName }],
387
353
  }),
388
354
  where: value,
389
- }));
355
+ });
356
+ setFormData(value);
357
+ setBaseAst(newAst);
358
+ fetchSqlQuery(newAst, value);
390
359
  return;
391
360
  }
392
361
  let newState = deepCopy(formData);
@@ -470,7 +439,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
470
439
  }
471
440
  }
472
441
  setFormData(newState);
473
- setBaseAst({
442
+ const newAst = {
474
443
  ...defaultAST,
475
444
  ...baseAst,
476
445
  ...(!baseAst?.columns && {
@@ -484,7 +453,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
484
453
  from: [{ ...defaultTable, table: initialTableName }],
485
454
  }),
486
455
  where: { ...newState },
487
- });
456
+ };
457
+ setBaseAst(newAst);
458
+ fetchSqlQuery(newAst, newState);
488
459
  });
489
460
  };
490
461
  // TODO: Merge this function with the updateFormData function
@@ -704,6 +675,23 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
704
675
  .find((c) => c.name === columnName);
705
676
  return column?.fieldType;
706
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
+ };
707
695
  /**
708
696
  * Render form fields based on the type of the node
709
697
  * @param node the AST or subtree to render recursively
@@ -1097,7 +1085,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1097
1085
  else {
1098
1086
  handleDeleteVariant(keyPrefix + 'right.' + 'value', key);
1099
1087
  }
1100
- } }), _jsx("span", { children: key })] }, key))) }, keyPrefix + 'right.'))] }));
1088
+ } }), _jsx("span", { style: { fontFamily: theme.fontFamily }, children: key })] }, key))) }, keyPrefix + 'right.'))] }));
1101
1089
  }
1102
1090
  else {
1103
1091
  const columnName = node.left.column;
@@ -1370,33 +1358,6 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1370
1358
  return 0;
1371
1359
  }));
1372
1360
  };
1373
- const getDateColumns = () => {
1374
- const allColumns = getAllPossibleColumns();
1375
- return allColumns.filter((c) => isDateishColumnType(c.fieldType));
1376
- };
1377
- const getNumericColumns = () => {
1378
- const allColumns = getAllPossibleColumns();
1379
- const selectedColumnNames = selectedColumns.map((col) => col.split('.')[1]);
1380
- return allColumns
1381
- .filter((column) => {
1382
- return selectedColumnNames.includes(column.name);
1383
- })
1384
- .filter((c) => isNumericColumnType(c.fieldType));
1385
- };
1386
- const getNonNumericColumns = () => {
1387
- const allColumns = getAllPossibleColumns();
1388
- const selectedColumnNames = selectedColumns.map((col) => col.split('.')[1]);
1389
- return allColumns
1390
- .filter((column) => selectedColumnNames.includes(column.name))
1391
- .filter((c) => !isNumericColumnType(c.fieldType));
1392
- };
1393
- const getStringColumns = () => {
1394
- const allColumns = getAllPossibleColumns();
1395
- const selectedColumnNames = selectedColumns.map((col) => col.split('.')[1]);
1396
- return allColumns
1397
- .filter((column) => selectedColumnNames.includes(column.name))
1398
- .filter((c) => isTextColumnType(c.fieldType));
1399
- };
1400
1361
  /**
1401
1362
  * Return whether all columns have been selected (used to hide select all
1402
1363
  * and show clear button).
@@ -1432,8 +1393,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1432
1393
  justifyContent: 'end',
1433
1394
  }, children: _jsx(Button, { onClick: onSave, label: 'Add condition' }) })] }));
1434
1395
  };
1435
- const fetchUponChange = async () => {
1436
- if ((formData || baseAst) && !loading) {
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) {
1437
1400
  try {
1438
1401
  setLoading(true);
1439
1402
  const res2 = await fetch('https://quill-344421.uc.r.appspot.com/patterns', {
@@ -1442,7 +1405,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1442
1405
  'Content-Type': 'application/json',
1443
1406
  },
1444
1407
  body: JSON.stringify({
1445
- ast: { ...baseAst, where: formData },
1408
+ ast: { ...baseAst, where: curFormData },
1446
1409
  publicKey: client.publicKey,
1447
1410
  orgId: client.customerId,
1448
1411
  }),
@@ -1451,6 +1414,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1451
1414
  if (data2.rows && data2.rows.length) {
1452
1415
  const tables = getTableNames(baseAst);
1453
1416
  const table = tables.length >= 1 ? tables[0] : initialTableName;
1417
+ if (table !== currentTable) {
1418
+ getDistinctValues(table);
1419
+ setCurrentTable(table);
1420
+ }
1454
1421
  const sortedFields = data2.fields.sort((a, b) => {
1455
1422
  const aIsId = a.name.toLowerCase() === 'id' ||
1456
1423
  a.name.toLowerCase().endsWith('_id');
@@ -1472,7 +1439,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1472
1439
  uniqueFormatted[pivot.columnField] = uniqueRecords;
1473
1440
  const pivotedData = generatePivotTable(pivot, data2.rows, [null, null, null], false);
1474
1441
  console.info(`%c[Pivot]: ${JSON.stringify(pivot)}`, 'color: dimgray');
1475
- setPivotData(pivotedData);
1442
+ setPivotData(pivotedData || []);
1476
1443
  setRows(data2.rows);
1477
1444
  setFields(data2.fields);
1478
1445
  }
@@ -1595,6 +1562,33 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1595
1562
  }
1596
1563
  return false;
1597
1564
  };
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
+ };
1598
1592
  const handleAsk = async (overridePrompt = '') => {
1599
1593
  if (!aiPrompt && !overridePrompt) {
1600
1594
  return;
@@ -1663,11 +1657,14 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1663
1657
  newAst = removeNonSelectedTableReferences(newAst, tableAlias ?? table);
1664
1658
  // newAst = convertDateComparison(newAst); // TODO
1665
1659
  ast = newAst; // so we fetch data for newAst later.
1660
+ if (table !== currentTable) {
1661
+ getDistinctValues(table);
1662
+ setCurrentTable(table);
1663
+ }
1666
1664
  setPivotRowField(groupByPivot?.rowField);
1667
1665
  setPivotColumnField(groupByPivot?.columnField);
1668
1666
  setPivotValueField(groupByPivot?.valueField);
1669
1667
  setPivotAggregation(groupByPivot?.aggregationType);
1670
- setPivot(groupByPivot);
1671
1668
  setSelectedColumns(deepCopy(newAst).columns?.map((column) => {
1672
1669
  if (column.expr.type === 'column_ref') {
1673
1670
  return `${table}.${column.expr.column}`;
@@ -1678,7 +1675,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1678
1675
  return `${table}.${column.expr.value}`;
1679
1676
  }));
1680
1677
  if (groupByPivot) {
1681
- setBaseAst(deepCopy({ ...newAst, orderby: null }));
1678
+ setBaseAst(deepCopy({ ...newAst, orderby: null, limit: null }));
1682
1679
  }
1683
1680
  else {
1684
1681
  setBaseAst(deepCopy({ ...newAst }));
@@ -1687,8 +1684,6 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1687
1684
  setTopLevelBinaryOperator(
1688
1685
  // @ts-ignore
1689
1686
  newAst?.where ? newAst?.where?.operator : 'AND');
1690
- if (groupByPivot)
1691
- return; // the useEffect will handle the rest
1692
1687
  }
1693
1688
  const res2 = await fetch('https://quill-344421.uc.r.appspot.com/patterns', {
1694
1689
  method: 'POST',
@@ -1704,11 +1699,13 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1704
1699
  const data2 = await res2.json();
1705
1700
  if (data2.rows && data2.rows.length) {
1706
1701
  const tables = getTableNames(newAst);
1707
- const table = tables.length >= 1 ? tables[0] : initialTableName;
1708
1702
  if (groupByPivot) {
1709
- const pivotedData = generatePivotTable(pivot, data2.rows, [null, null, null], false);
1703
+ const pivotedData = generatePivotTable(
1704
+ // @ts-ignore
1705
+ groupByPivot, data2.rows, [null, null, null], false);
1710
1706
  console.info(`%c[Pivot]: ${JSON.stringify(groupByPivot)}`, 'color: dimgray');
1711
1707
  setPivotData(pivotedData);
1708
+ setPivot(groupByPivot);
1712
1709
  setRows(data2.rows);
1713
1710
  setFields(data2.fields);
1714
1711
  }
@@ -1718,6 +1715,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1718
1715
  }
1719
1716
  }
1720
1717
  else {
1718
+ setPivotData([]);
1721
1719
  setRows([]);
1722
1720
  setFields([]);
1723
1721
  }
@@ -1736,7 +1734,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1736
1734
  }
1737
1735
  catch (e) {
1738
1736
  console.error(e);
1739
- setErrorMessage(`${e.name}: ${e.message}`);
1737
+ setErrorMessage(`Error: Couldn't process your request, please re-word your prompt.`);
1740
1738
  }
1741
1739
  finally {
1742
1740
  setLoading(false);
@@ -1762,11 +1760,17 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1762
1760
  clearAllState();
1763
1761
  return;
1764
1762
  }
1765
- const newAst = { ...baseAst, columns };
1766
- setBaseAst(deepCopy(newAst));
1763
+ const newAst = deepCopy({ ...baseAst, columns });
1764
+ setBaseAst(newAst);
1765
+ fetchSqlQuery(newAst);
1767
1766
  };
1768
1767
  function TopLevelBooleanSwitch({ node, keyPrefix, handleOperatorChange, }) {
1769
- return (_jsx("div", { style: { width: 'fit-content' }, children: _jsx(Tabs, { defaultValue: node.operator, options: DEFAULT_TAB_OPTIONS, onValueChange: (value) => handleOperatorChange(value, node, keyPrefix) }) }));
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
+ } }) }));
1770
1774
  }
1771
1775
  const DraggableItem = ({ id, label, onDelete }) => {
1772
1776
  const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: id });
@@ -1812,6 +1816,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1812
1816
  };
1813
1817
  const newAst = baseAst ? newBaseAst : fallbackAST;
1814
1818
  setBaseAst(newAst);
1819
+ fetchSqlQuery(newAst);
1815
1820
  }
1816
1821
  }
1817
1822
  const columnNamesInAst = baseAst?.columns.map((col) => {
@@ -1854,7 +1859,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1854
1859
  setActiveEditItem(null);
1855
1860
  setActivePath(null);
1856
1861
  setOpenPopover(null);
1857
- }, orderedColumnNames: orderedColumnNames, setOrderedColumnNames: setOrderedColumnNames, selectedColumns: selectedColumns, setSelectedColumns: setSelectedColumns, isSelectedAllColumns: isSelectedAllColumns, clearAllState: clearAllState, nameToColumn: nameToColumn, baseAst: baseAst, setBaseAst: setBaseAst, 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: {
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: {
1858
1866
  display: 'flex',
1859
1867
  flexDirection: 'column',
1860
1868
  gap: 8,
@@ -1865,6 +1873,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1865
1873
  gap: 2.5,
1866
1874
  alignItems: 'flex-start',
1867
1875
  }, children: [_jsx(Popover, { isOpen: openPopover === 'AddFilterPopover', title: 'Add filter', trigger: _jsx(SecondaryButton, { onClick: () => {
1876
+ if (!selectedColumns || selectedColumns.length === 0) {
1877
+ return;
1878
+ }
1868
1879
  if (!openPopover) {
1869
1880
  const value = orderedColumnNames[0];
1870
1881
  const [_table, column] = value.split('.');
@@ -1951,14 +1962,18 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1951
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: () => {
1952
1963
  setPivot(null);
1953
1964
  setPivotData(null);
1954
- }, selectPivot: (pivot) => {
1965
+ },
1966
+ // TODOs
1967
+ selectPivot: (pivot) => {
1955
1968
  if (!pivot)
1956
1969
  return;
1957
1970
  const newAst = { ...baseAst };
1958
1971
  newAst.orderby = null;
1959
1972
  setBaseAst(newAst); // trigger refetch
1960
1973
  setPivot(pivot);
1961
- }, selectPivotOnEdit: true, showTrigger: !pivot || !pivotData, theme: theme, LabelComponent: Label, HeaderComponent: Header, dateRange: [null, null, null], recommendPivotCount: 3, SecondaryButtonComponent: SecondaryButton }), pivot && pivotData && (_jsx(PivotCard, { pivotTable: {
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: {
1962
1977
  pivot: pivot,
1963
1978
  rows: pivotData?.rows || [],
1964
1979
  columns: pivotData?.columns || [],
@@ -1985,10 +2000,16 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
1985
2000
  }, columns: selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover: SortPopover, EditPopover: AddSortPopover, handleDelete: () => {
1986
2001
  setPivot({ ...pivot, sort: false });
1987
2002
  setBaseAst(deepCopy(baseAst));
2003
+ if (!pivot) {
2004
+ fetchSqlQuery(baseAst);
2005
+ }
1988
2006
  }, onSave: (column, direction) => {
1989
2007
  setPivot({ ...pivot, sort: true, sortDirection: direction });
1990
2008
  setOpenPopover(null);
1991
2009
  setBaseAst(deepCopy(baseAst));
2010
+ if (!pivot) {
2011
+ fetchSqlQuery(baseAst);
2012
+ }
1992
2013
  } }, `sort-sentence-pivot`) })), baseAst && baseAst.orderby && (_jsx("div", { style: {
1993
2014
  display: 'flex',
1994
2015
  flexDirection: 'column',
@@ -2013,11 +2034,20 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2013
2034
  setActivePath(null);
2014
2035
  setOpenPopover(null);
2015
2036
  setBaseAst(deepCopy(newAst));
2037
+ if (!pivot) {
2038
+ fetchSqlQuery(newAst);
2039
+ }
2016
2040
  }, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover: SortPopover, EditPopover: AddSortPopover, handleDelete: () => {
2017
2041
  const newAst = { ...baseAst };
2018
2042
  newAst.orderby.splice(id, 1);
2019
2043
  setBaseAst(deepCopy(newAst));
2044
+ if (!pivot) {
2045
+ fetchSqlQuery(newAst);
2046
+ }
2020
2047
  } }, `sort-sentence-${id}`))) })), _jsx(Popover, { isOpen: openPopover === 'AddSortPopover', setIsOpen: () => { }, trigger: _jsx(SecondaryButton, { onClick: () => {
2048
+ if (!selectedColumns || selectedColumns.length === 0) {
2049
+ return;
2050
+ }
2021
2051
  if (!openPopover) {
2022
2052
  setOpenPopover('AddSortPopover');
2023
2053
  }
@@ -2035,6 +2065,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2035
2065
  const newAst = { ...baseAst };
2036
2066
  newAst.limit = null;
2037
2067
  setBaseAst(deepCopy(newAst));
2068
+ fetchSqlQuery(newAst);
2038
2069
  }, onSave: (limit) => {
2039
2070
  const newAst = { ...baseAst };
2040
2071
  newAst.limit = {
@@ -2048,6 +2079,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2048
2079
  };
2049
2080
  setOpenPopover(null);
2050
2081
  setBaseAst(deepCopy(newAst));
2082
+ fetchSqlQuery(newAst);
2051
2083
  } }) })) : (_jsx(Popover, { isOpen: openPopover === 'AddLimitPopover', setIsOpen: () => { }, trigger: _jsx(SecondaryButton, { onClick: () => {
2052
2084
  if (!openPopover) {
2053
2085
  setOpenPopover('AddLimitPopover');
@@ -2064,11 +2096,11 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2064
2096
  flexDirection: 'row',
2065
2097
  gap: 12,
2066
2098
  padding: 1,
2067
- }, 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" }))] })), baseAst && (_jsxs(_Fragment, { children: [_jsx(TableLoadingState, {}), _jsxs("div", { style: {
2099
+ }, 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: {
2068
2100
  display: 'flex',
2069
2101
  flexDirection: 'row',
2070
2102
  gap: '12px',
2071
- }, 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;}` })] }));
2103
+ }, 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;}` })] }));
2072
2104
  }
2073
2105
  return (_jsxs("div", { ref: parentRef, style: {
2074
2106
  display: 'flex',
@@ -2093,7 +2125,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2093
2125
  setActiveEditItem(null);
2094
2126
  setActivePath(null);
2095
2127
  setOpenPopover(null);
2096
- }, orderedColumnNames: orderedColumnNames, setOrderedColumnNames: setOrderedColumnNames, selectedColumns: selectedColumns, setSelectedColumns: setSelectedColumns, isSelectedAllColumns: isSelectedAllColumns, clearAllState: clearAllState, nameToColumn: nameToColumn, baseAst: baseAst, setBaseAst: setBaseAst, 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: {
2128
+ }, orderedColumnNames: orderedColumnNames, setOrderedColumnNames: setOrderedColumnNames, selectedColumns: selectedColumns, setSelectedColumns: setSelectedColumns, isSelectedAllColumns: isSelectedAllColumns, clearAllState: clearAllState, nameToColumn: nameToColumn, baseAst: baseAst, setBaseAst: (ast) => {
2129
+ setBaseAst(ast);
2130
+ fetchSqlQuery(ast);
2131
+ }, 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: {
2097
2132
  display: 'flex',
2098
2133
  flexDirection: 'column',
2099
2134
  gap: 8,
@@ -2104,6 +2139,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2104
2139
  gap: 2.5,
2105
2140
  alignItems: 'flex-start',
2106
2141
  }, children: [_jsx(Popover, { title: 'Add filter', isOpen: openPopover === 'AddFilterPopover', trigger: _jsx(SecondaryButton, { onClick: () => {
2142
+ if (!selectedColumns || selectedColumns.length === 0) {
2143
+ return;
2144
+ }
2107
2145
  if (!openPopover) {
2108
2146
  const value = orderedColumnNames[0];
2109
2147
  const [_table, column] = value.split('.');
@@ -2203,7 +2241,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2203
2241
  }
2204
2242
  setBaseAst(newAst); // trigger refetch
2205
2243
  setPivot(pivot);
2206
- }, selectPivotOnEdit: true, showTrigger: !pivot || !pivotData, theme: theme, LabelComponent: Label, HeaderComponent: Header, dateRange: [null, null, null], recommendPivotCount: 3 }), pivot && pivotData && (_jsx(PivotCard, { pivotTable: {
2244
+ const pivotedData = generatePivotTable(pivot, rows, [null, null, null], false);
2245
+ setPivotData(pivotedData || []);
2246
+ }, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent: Label, HeaderComponent: Header, dateRange: [null, null, null], recommendPivotCount: 3 }), pivot && (_jsx(PivotCard, { pivotTable: {
2207
2247
  pivot: pivot,
2208
2248
  rows: pivotData?.rows || [],
2209
2249
  columns: pivotData?.columns || [],
@@ -2218,7 +2258,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2218
2258
  }, selectedPivotIndex: -1, onEditPivot: () => { }, ButtonComponent: Button, HeaderComponent: Header, showEdit: false, onClose: () => {
2219
2259
  setPivot(null);
2220
2260
  setPivotData(null);
2221
- setBaseAst(deepCopy(baseAst)); // trigger refetch
2261
+ setBaseAst(deepCopy(baseAst));
2222
2262
  }, 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: {
2223
2263
  display: 'flex',
2224
2264
  flexDirection: 'column',
@@ -2227,13 +2267,25 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2227
2267
  }, children: _jsx(SortSentence, { sortData: {
2228
2268
  type: pivot.sortDirection,
2229
2269
  expr: { type: 'column_ref', column: pivot.rowField },
2230
- }, columns: selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover: SortPopover, EditPopover: AddSortPopover, handleDelete: () => {
2231
- setPivot({ ...pivot, sort: false });
2270
+ }, columns: pivot ? [`.${pivot.rowField}`] : selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover: SortPopover, EditPopover: AddSortPopover, handleDelete: () => {
2271
+ if (pivot) {
2272
+ setPivot({ ...pivot, sort: false });
2273
+ const pivotedData = generatePivotTable({ ...pivot, sort: false }, rows, [null, null, null], false);
2274
+ setPivotData(pivotedData || []);
2275
+ return;
2276
+ }
2232
2277
  setBaseAst(deepCopy(baseAst));
2278
+ fetchSqlQuery(deepCopy(baseAst));
2233
2279
  }, onSave: (column, direction) => {
2234
- setPivot({ ...pivot, sort: true, sortDirection: direction });
2280
+ if (pivot) {
2281
+ setPivot({ ...pivot, sort: true, sortDirection: direction });
2282
+ const pivotedData = generatePivotTable({ ...pivot, sort: true, sortDirection: direction }, rows, [null, null, null], false);
2283
+ setPivotData(pivotedData || []);
2284
+ return;
2285
+ }
2235
2286
  setOpenPopover(null);
2236
2287
  setBaseAst(deepCopy(baseAst));
2288
+ fetchSqlQuery(deepCopy(baseAst));
2237
2289
  } }, `sort-sentence-pivot`) })), baseAst && baseAst.orderby && (_jsx("div", { style: {
2238
2290
  display: 'flex',
2239
2291
  flexDirection: 'column',
@@ -2247,6 +2299,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2247
2299
  const newAst = { ...baseAst };
2248
2300
  newAst.orderby.splice(id, 1);
2249
2301
  setBaseAst(deepCopy(newAst));
2302
+ fetchSqlQuery(deepCopy(newAst));
2250
2303
  }, onSave: (column, direction) => {
2251
2304
  if (pivot) {
2252
2305
  setPivot({
@@ -2274,7 +2327,11 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2274
2327
  setActivePath(null);
2275
2328
  setOpenPopover(null);
2276
2329
  setBaseAst(deepCopy(newAst));
2330
+ fetchSqlQuery(deepCopy(newAst));
2277
2331
  } }, `sort-sentence-${id}`))) })), _jsx(Popover, { isOpen: openPopover === 'AddSortPopover', trigger: _jsx(SecondaryButton, { onClick: () => {
2332
+ if (!selectedColumns || selectedColumns.length === 0) {
2333
+ return;
2334
+ }
2278
2335
  if (!openPopover) {
2279
2336
  setOpenPopover('AddSortPopover');
2280
2337
  }
@@ -2288,6 +2345,8 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2288
2345
  return;
2289
2346
  if (pivot) {
2290
2347
  setPivot({ ...pivot, sort: true, sortDirection: direction });
2348
+ const pivotedData = generatePivotTable({ ...pivot, sort: true, sortDirection: direction }, rows, [null, null, null], false);
2349
+ setPivotData(pivotedData || []);
2291
2350
  setActivePath(null);
2292
2351
  setOpenPopover(null);
2293
2352
  setBaseAst(deepCopy(baseAst));
@@ -2304,6 +2363,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2304
2363
  setActivePath(null);
2305
2364
  setOpenPopover(null);
2306
2365
  setBaseAst(deepCopy(newAst));
2366
+ fetchSqlQuery(deepCopy(newAst));
2307
2367
  } }) }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeading, { label: "Limit" }), _jsx("div", { style: { height: 4, width: '100%' } }), baseAst && baseAst.limit ? (_jsx("div", { style: {
2308
2368
  display: 'flex',
2309
2369
  flexDirection: 'column',
@@ -2313,6 +2373,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2313
2373
  const newAst = { ...baseAst };
2314
2374
  newAst.limit = null;
2315
2375
  setBaseAst(deepCopy(newAst));
2376
+ fetchSqlQuery(deepCopy(newAst));
2316
2377
  }, onSave: (limit) => {
2317
2378
  const newAst = { ...baseAst };
2318
2379
  newAst.limit = {
@@ -2326,7 +2387,11 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2326
2387
  };
2327
2388
  setOpenPopover(null);
2328
2389
  setBaseAst(deepCopy(newAst));
2390
+ fetchSqlQuery(deepCopy(newAst));
2329
2391
  } }) })) : (_jsx(Popover, { isOpen: openPopover === 'AddLimitPopover', setIsOpen: () => { }, trigger: _jsx(SecondaryButton, { onClick: () => {
2392
+ if (!selectedColumns || selectedColumns.length === 0) {
2393
+ return;
2394
+ }
2330
2395
  if (!baseAst) {
2331
2396
  return;
2332
2397
  }
@@ -2351,6 +2416,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2351
2416
  };
2352
2417
  setOpenPopover(null);
2353
2418
  setBaseAst(deepCopy(newAst));
2419
+ fetchSqlQuery(deepCopy(newAst));
2354
2420
  } }) }))] }), _jsxs(Container, { children: [!hideAi && (_jsxs("form", { onSubmit: (event) => {
2355
2421
  event.preventDefault();
2356
2422
  handleAsk();
@@ -2362,8 +2428,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
2362
2428
  }, 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({
2363
2429
  rows: pivotData?.rows || rows,
2364
2430
  fields: pivotData?.fields || fields,
2365
- }, baseAst?.columns ?? []), columns: pivotData?.columns ||
2366
- enforceOrderOnColumns(Object.keys(rows[0] ?? {})).map((c) => {
2431
+ }, baseAst?.columns ?? []), columns: pivot
2432
+ ? pivotData?.columns || emptyPivotColumns()
2433
+ : enforceOrderOnColumns(Object.keys(rows[0] ?? {})).map((c) => {
2367
2434
  return { label: snakeCaseToTitleCase(c), field: c };
2368
2435
  }), error: errorMessage, rowsPerPage: 20 })) })), _jsxs("div", { style: {
2369
2436
  display: 'flex',