@quillsql/react 2.12.39 → 2.12.41

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 (201) hide show
  1. package/dist/cjs/Chart.js +1 -1
  2. package/dist/cjs/ChartBuilder.d.ts +1 -1
  3. package/dist/cjs/ChartBuilder.d.ts.map +1 -1
  4. package/dist/cjs/ChartBuilder.js +6 -6
  5. package/dist/cjs/Dashboard.d.ts +35 -3
  6. package/dist/cjs/Dashboard.d.ts.map +1 -1
  7. package/dist/cjs/Dashboard.js +72 -74
  8. package/dist/cjs/ReportBuilder.d.ts +1 -1
  9. package/dist/cjs/ReportBuilder.d.ts.map +1 -1
  10. package/dist/cjs/ReportBuilder.js +111 -1588
  11. package/dist/cjs/components/Chart/BarChart.d.ts.map +1 -1
  12. package/dist/cjs/components/Chart/BarChart.js +0 -9
  13. package/dist/cjs/components/Chart/LineChart.d.ts.map +1 -1
  14. package/dist/cjs/components/Chart/LineChart.js +1 -11
  15. package/dist/cjs/components/Dashboard/ChartComponent.d.ts.map +1 -1
  16. package/dist/cjs/components/Dashboard/ChartComponent.js +1 -0
  17. package/dist/cjs/components/Dashboard/DashboardTemplate.d.ts +12 -0
  18. package/dist/cjs/components/Dashboard/DashboardTemplate.d.ts.map +1 -0
  19. package/dist/cjs/components/Dashboard/DashboardTemplate.js +69 -0
  20. package/dist/cjs/components/Dashboard/DataLoader.js +1 -1
  21. package/dist/cjs/components/Dashboard/TemplateChartComponent.d.ts +4 -0
  22. package/dist/cjs/components/Dashboard/TemplateChartComponent.d.ts.map +1 -0
  23. package/dist/cjs/components/Dashboard/TemplateChartComponent.js +23 -0
  24. package/dist/cjs/components/Dashboard/TemplateMetricComponent.d.ts +4 -0
  25. package/dist/cjs/components/Dashboard/TemplateMetricComponent.d.ts.map +1 -0
  26. package/dist/cjs/components/Dashboard/TemplateMetricComponent.js +23 -0
  27. package/dist/cjs/components/Dashboard/TemplateTableComponent.d.ts +15 -0
  28. package/dist/cjs/components/Dashboard/TemplateTableComponent.d.ts.map +1 -0
  29. package/dist/cjs/components/Dashboard/TemplateTableComponent.js +23 -0
  30. package/dist/cjs/components/Dashboard/util.d.ts +6 -0
  31. package/dist/cjs/components/Dashboard/util.d.ts.map +1 -0
  32. package/dist/cjs/components/Dashboard/util.js +85 -0
  33. package/dist/cjs/components/ReportBuilder/FilterModal.js +32 -32
  34. package/dist/cjs/components/ReportBuilder/convert.d.ts +5 -31
  35. package/dist/cjs/components/ReportBuilder/convert.d.ts.map +1 -1
  36. package/dist/cjs/components/ReportBuilder/convert.js +1 -1
  37. package/dist/cjs/components/UiComponents.d.ts +1 -23
  38. package/dist/cjs/components/UiComponents.d.ts.map +1 -1
  39. package/dist/cjs/components/UiComponents.js +67 -25
  40. package/dist/cjs/hooks/useAskQuill.d.ts +27 -0
  41. package/dist/cjs/hooks/useAskQuill.d.ts.map +1 -0
  42. package/dist/cjs/hooks/useAskQuill.js +177 -0
  43. package/dist/cjs/hooks/useDashboard.d.ts.map +1 -1
  44. package/dist/cjs/hooks/useDashboard.js +7 -5
  45. package/dist/cjs/index.d.ts +1 -0
  46. package/dist/cjs/index.d.ts.map +1 -1
  47. package/dist/cjs/index.js +3 -1
  48. package/dist/cjs/internals/ReportBuilder/PivotForm.d.ts +3 -3
  49. package/dist/cjs/internals/ReportBuilder/PivotForm.d.ts.map +1 -1
  50. package/dist/cjs/internals/ReportBuilder/PivotForm.js +4 -2
  51. package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts +1 -15
  52. package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
  53. package/dist/cjs/internals/ReportBuilder/PivotModal.js +24 -24
  54. package/dist/cjs/models/Filter.d.ts +25 -19
  55. package/dist/cjs/models/Filter.d.ts.map +1 -1
  56. package/dist/cjs/models/Filter.js +2 -2
  57. package/dist/cjs/{components/ReportBuilder/pivot.d.ts → models/Pivot.d.ts} +13 -4
  58. package/dist/cjs/models/Pivot.d.ts.map +1 -0
  59. package/dist/cjs/models/Report.d.ts +5 -1
  60. package/dist/cjs/models/Report.d.ts.map +1 -1
  61. package/dist/cjs/models/Tables.d.ts +16 -0
  62. package/dist/cjs/models/Tables.d.ts.map +1 -1
  63. package/dist/cjs/utils/astFilterProcessing.js +27 -27
  64. package/dist/cjs/utils/astProcessing.d.ts +42 -0
  65. package/dist/cjs/utils/astProcessing.d.ts.map +1 -1
  66. package/dist/cjs/utils/astProcessing.js +210 -1
  67. package/dist/cjs/utils/constants.d.ts +1 -0
  68. package/dist/cjs/utils/constants.d.ts.map +1 -1
  69. package/dist/cjs/utils/constants.js +2 -1
  70. package/dist/cjs/utils/dashboard.d.ts.map +1 -1
  71. package/dist/cjs/utils/dashboard.js +2 -0
  72. package/dist/cjs/utils/dataFetcher.d.ts +4 -0
  73. package/dist/cjs/utils/dataFetcher.d.ts.map +1 -1
  74. package/dist/cjs/utils/dataFetcher.js +24 -1
  75. package/dist/cjs/utils/dates.d.ts +1 -1
  76. package/dist/cjs/utils/filterProcessing.d.ts +2 -2
  77. package/dist/cjs/utils/filterProcessing.d.ts.map +1 -1
  78. package/dist/cjs/utils/filterProcessing.js +6 -6
  79. package/dist/cjs/utils/pivotConstructor.d.ts +1 -1
  80. package/dist/cjs/utils/pivotConstructor.d.ts.map +1 -1
  81. package/dist/cjs/utils/pivotConstructor.js +7 -4
  82. package/dist/cjs/utils/pivotProcessing.d.ts +4 -4
  83. package/dist/cjs/utils/pivotProcessing.d.ts.map +1 -1
  84. package/dist/cjs/utils/pivotProcessing.js +21 -2
  85. package/dist/cjs/utils/queryConstructor.d.ts +1 -1
  86. package/dist/cjs/utils/queryConstructor.d.ts.map +1 -1
  87. package/dist/cjs/utils/queryConstructor.js +3 -3
  88. package/dist/cjs/utils/report.d.ts +25 -0
  89. package/dist/cjs/utils/report.d.ts.map +1 -1
  90. package/dist/cjs/utils/report.js +114 -2
  91. package/dist/cjs/utils/schema.d.ts.map +1 -1
  92. package/dist/cjs/utils/schema.js +1 -1
  93. package/dist/cjs/utils/tableProcessing.d.ts +18 -0
  94. package/dist/cjs/utils/tableProcessing.d.ts.map +1 -1
  95. package/dist/cjs/utils/tableProcessing.js +94 -1
  96. package/dist/esm/Chart.js +1 -1
  97. package/dist/esm/ChartBuilder.d.ts +1 -1
  98. package/dist/esm/ChartBuilder.d.ts.map +1 -1
  99. package/dist/esm/ChartBuilder.js +6 -6
  100. package/dist/esm/Dashboard.d.ts +35 -3
  101. package/dist/esm/Dashboard.d.ts.map +1 -1
  102. package/dist/esm/Dashboard.js +73 -75
  103. package/dist/esm/ReportBuilder.d.ts +1 -1
  104. package/dist/esm/ReportBuilder.d.ts.map +1 -1
  105. package/dist/esm/ReportBuilder.js +121 -1598
  106. package/dist/esm/components/Chart/BarChart.d.ts.map +1 -1
  107. package/dist/esm/components/Chart/BarChart.js +0 -9
  108. package/dist/esm/components/Chart/LineChart.d.ts.map +1 -1
  109. package/dist/esm/components/Chart/LineChart.js +1 -11
  110. package/dist/esm/components/Dashboard/ChartComponent.d.ts.map +1 -1
  111. package/dist/esm/components/Dashboard/ChartComponent.js +1 -0
  112. package/dist/esm/components/Dashboard/DashboardTemplate.d.ts +12 -0
  113. package/dist/esm/components/Dashboard/DashboardTemplate.d.ts.map +1 -0
  114. package/dist/esm/components/Dashboard/DashboardTemplate.js +63 -0
  115. package/dist/esm/components/Dashboard/DataLoader.js +1 -1
  116. package/dist/esm/components/Dashboard/TemplateChartComponent.d.ts +4 -0
  117. package/dist/esm/components/Dashboard/TemplateChartComponent.d.ts.map +1 -0
  118. package/dist/esm/components/Dashboard/TemplateChartComponent.js +17 -0
  119. package/dist/esm/components/Dashboard/TemplateMetricComponent.d.ts +4 -0
  120. package/dist/esm/components/Dashboard/TemplateMetricComponent.d.ts.map +1 -0
  121. package/dist/esm/components/Dashboard/TemplateMetricComponent.js +17 -0
  122. package/dist/esm/components/Dashboard/TemplateTableComponent.d.ts +15 -0
  123. package/dist/esm/components/Dashboard/TemplateTableComponent.d.ts.map +1 -0
  124. package/dist/esm/components/Dashboard/TemplateTableComponent.js +17 -0
  125. package/dist/esm/components/Dashboard/util.d.ts +6 -0
  126. package/dist/esm/components/Dashboard/util.d.ts.map +1 -0
  127. package/dist/esm/components/Dashboard/util.js +80 -0
  128. package/dist/esm/components/ReportBuilder/FilterModal.js +32 -32
  129. package/dist/esm/components/ReportBuilder/convert.d.ts +5 -31
  130. package/dist/esm/components/ReportBuilder/convert.d.ts.map +1 -1
  131. package/dist/esm/components/ReportBuilder/convert.js +1 -1
  132. package/dist/esm/components/UiComponents.d.ts +1 -23
  133. package/dist/esm/components/UiComponents.d.ts.map +1 -1
  134. package/dist/esm/components/UiComponents.js +65 -23
  135. package/dist/esm/hooks/useAskQuill.d.ts +27 -0
  136. package/dist/esm/hooks/useAskQuill.d.ts.map +1 -0
  137. package/dist/esm/hooks/useAskQuill.js +173 -0
  138. package/dist/esm/hooks/useDashboard.d.ts.map +1 -1
  139. package/dist/esm/hooks/useDashboard.js +7 -5
  140. package/dist/esm/index.d.ts +1 -0
  141. package/dist/esm/index.d.ts.map +1 -1
  142. package/dist/esm/index.js +1 -0
  143. package/dist/esm/internals/ReportBuilder/PivotForm.d.ts +3 -3
  144. package/dist/esm/internals/ReportBuilder/PivotForm.d.ts.map +1 -1
  145. package/dist/esm/internals/ReportBuilder/PivotForm.js +4 -2
  146. package/dist/esm/internals/ReportBuilder/PivotModal.d.ts +1 -15
  147. package/dist/esm/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
  148. package/dist/esm/internals/ReportBuilder/PivotModal.js +24 -24
  149. package/dist/esm/models/Filter.d.ts +25 -19
  150. package/dist/esm/models/Filter.d.ts.map +1 -1
  151. package/dist/esm/models/Filter.js +2 -2
  152. package/dist/esm/{components/ReportBuilder/pivot.d.ts → models/Pivot.d.ts} +13 -4
  153. package/dist/esm/models/Pivot.d.ts.map +1 -0
  154. package/dist/esm/models/Report.d.ts +5 -1
  155. package/dist/esm/models/Report.d.ts.map +1 -1
  156. package/dist/esm/models/Tables.d.ts +16 -0
  157. package/dist/esm/models/Tables.d.ts.map +1 -1
  158. package/dist/esm/utils/astFilterProcessing.js +27 -27
  159. package/dist/esm/utils/astProcessing.d.ts +42 -0
  160. package/dist/esm/utils/astProcessing.d.ts.map +1 -1
  161. package/dist/esm/utils/astProcessing.js +204 -0
  162. package/dist/esm/utils/constants.d.ts +1 -0
  163. package/dist/esm/utils/constants.d.ts.map +1 -1
  164. package/dist/esm/utils/constants.js +1 -0
  165. package/dist/esm/utils/dashboard.d.ts.map +1 -1
  166. package/dist/esm/utils/dashboard.js +2 -0
  167. package/dist/esm/utils/dataFetcher.d.ts +4 -0
  168. package/dist/esm/utils/dataFetcher.d.ts.map +1 -1
  169. package/dist/esm/utils/dataFetcher.js +22 -0
  170. package/dist/esm/utils/dates.d.ts +1 -1
  171. package/dist/esm/utils/filterProcessing.d.ts +2 -2
  172. package/dist/esm/utils/filterProcessing.d.ts.map +1 -1
  173. package/dist/esm/utils/filterProcessing.js +7 -7
  174. package/dist/esm/utils/pivotConstructor.d.ts +1 -1
  175. package/dist/esm/utils/pivotConstructor.d.ts.map +1 -1
  176. package/dist/esm/utils/pivotConstructor.js +7 -4
  177. package/dist/esm/utils/pivotProcessing.d.ts +4 -4
  178. package/dist/esm/utils/pivotProcessing.d.ts.map +1 -1
  179. package/dist/esm/utils/pivotProcessing.js +19 -1
  180. package/dist/esm/utils/queryConstructor.d.ts +1 -1
  181. package/dist/esm/utils/queryConstructor.d.ts.map +1 -1
  182. package/dist/esm/utils/queryConstructor.js +3 -3
  183. package/dist/esm/utils/report.d.ts +25 -0
  184. package/dist/esm/utils/report.d.ts.map +1 -1
  185. package/dist/esm/utils/report.js +114 -3
  186. package/dist/esm/utils/schema.d.ts.map +1 -1
  187. package/dist/esm/utils/schema.js +1 -1
  188. package/dist/esm/utils/tableProcessing.d.ts +18 -0
  189. package/dist/esm/utils/tableProcessing.d.ts.map +1 -1
  190. package/dist/esm/utils/tableProcessing.js +91 -1
  191. package/package.json +1 -1
  192. package/dist/cjs/components/ReportBuilder/pivot.d.ts.map +0 -1
  193. package/dist/cjs/models/Pivots.d.ts +0 -2
  194. package/dist/cjs/models/Pivots.d.ts.map +0 -1
  195. package/dist/cjs/models/Pivots.js +0 -2
  196. package/dist/esm/components/ReportBuilder/pivot.d.ts.map +0 -1
  197. package/dist/esm/models/Pivots.d.ts +0 -2
  198. package/dist/esm/models/Pivots.d.ts.map +0 -1
  199. package/dist/esm/models/Pivots.js +0 -1
  200. /package/dist/cjs/{components/ReportBuilder/pivot.js → models/Pivot.js} +0 -0
  201. /package/dist/esm/{components/ReportBuilder/pivot.js → models/Pivot.js} +0 -0
@@ -1,20 +1,17 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useContext, useEffect, useRef, useState, } from 'react';
3
- import { DEFAULT_TAB_OPTIONS, MemoizedButton, MemoizedCheckbox, MemoizedDeleteButton, MemoizedHeader, MemoizedLabel, MemoizedSecondaryButton, MemoizedText, MemoizedPopover, QuillTabs, MemoizedModal, QuillChartBuilderInputRowContainer, QuillChartBuilderInputColumnContainer, MemoizedSubHeader, QuillErrorMessageComponent, QuillPivotRowContainer, QuillPivotColumnContainer, QuillColumnSearchEmptyState, QuillChartBuilderFormContainer, QuillLoadingComponent, QuillTableSQLEditorComponent, } from './components/UiComponents';
3
+ import { DEFAULT_TAB_OPTIONS, MemoizedButton, MemoizedDeleteButton, MemoizedHeader, MemoizedLabel, MemoizedSecondaryButton, MemoizedText, MemoizedPopover, QuillTabs, MemoizedModal, QuillChartBuilderInputRowContainer, QuillChartBuilderInputColumnContainer, MemoizedSubHeader, QuillErrorMessageComponent, QuillPivotRowContainer, QuillPivotColumnContainer, QuillColumnSearchEmptyState, QuillChartBuilderFormContainer, QuillLoadingComponent, QuillTableSQLEditorComponent, } from './components/UiComponents';
4
4
  import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors, } from '@dnd-kit/core';
5
5
  import { arrayMove, SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy, useSortable, } from '@dnd-kit/sortable';
6
6
  import { CSS as DND_CSS } from '@dnd-kit/utilities';
7
- import { ClientContext, CustomFieldContext, SchemaContext, ThemeContext, } from './Context';
8
- import { extractColumnish, getTableAliases, getTableNames, isBoolColumnType, isDateishColumnType, isNumericColumnType, isTextColumnType, } from './components/ReportBuilder/ast';
9
- import { ChartBuilderWithModal, createInitialFormData } from './ChartBuilder';
7
+ import { ClientContext, CustomFieldContext, DashboardContext, SchemaContext, ThemeContext, } from './Context';
8
+ import { getTableNames, isNumericColumnType, isTextColumnType, } from './components/ReportBuilder/ast';
9
+ import { ChartBuilderWithModal } from './ChartBuilder';
10
10
  import { QuillTextInput } from './components/UiComponents';
11
11
  import { QuillSidebar, CustomContainer, QuillSelectColumn, QuillDraggableColumn, QuillSidebarHeading, QuillFilterPopover, QuillSortPopover, QuillLimitPopover, FilterPopoverWrapper, } from './components/ReportBuilder/ui';
12
- import { generateCurrentPeriodPostgres, generateEqualsPostgres, generateLastNPeriodsPostgres, generatePreviousPeriodPostgres, } from './components/ReportBuilder/postgres';
13
- import { convertBigQuery, convertGroupBy, convertRemoveSimpleParentheses, convertStringComparison, convertWildcardColumns, convertUnaryToBinary, } from './components/ReportBuilder/convert';
14
- import { deepCopy, formatDateComparisonNode, getDateFilterInfo, isColumnComparison, isDateTruncEquals, isInTheLastInterval, isNodeEmptyCollection, isTheCurrentInterval, isThePreviousInterval, showNodeAsRow, removeNonSelectedTableReferences, isEquals, } from './components/ReportBuilder/util';
15
- import { getDefaultOperatorSubtrees, OPERATOR_GROUPS, } from './components/ReportBuilder/operators';
12
+ import { deepCopy } from './components/ReportBuilder/util';
16
13
  import { hashCode } from './utils/crypto';
17
- import { defaultAST, defaultBoolComparison, defaultColumn, defaultEntry, defaultNumericComparison, defaultTable, defaultVariant, } from './components/ReportBuilder/constants';
14
+ import { defaultAST, defaultColumn, defaultEntry, defaultNumericComparison, defaultTable, defaultVariant, } from './components/ReportBuilder/constants';
18
15
  import AddColumnModal from './components/ReportBuilder/AddColumnModal';
19
16
  import { AddSortPopover, SortSentence, } from './components/ReportBuilder/AddSortPopover';
20
17
  import { PivotModal, generatePivotTable, } from './internals/ReportBuilder/PivotModal';
@@ -23,14 +20,11 @@ import { AddLimitPopover, LimitSentence, } from './components/ReportBuilder/AddL
23
20
  import { updateFirstChildWidth } from './utils/width';
24
21
  import { QuillSelectComponent } from './components/QuillSelect';
25
22
  import { QuillCard } from './components/QuillCard';
26
- import { getData } from './utils/dataFetcher';
27
23
  import { DATE_FORMAT_TYPES, quillFormat } from './utils/valueFormatter';
28
- import { getPossiblePivotFieldOptions, pivotToSql, } from './utils/pivotProcessing';
24
+ import { pivotToSql } from './utils/pivotProcessing';
29
25
  import { getUniqueValuesByColumns, getDateRangeByColumns, getCountsByColumns, fetchTableByQuery, } from './utils/tableProcessing';
30
- import { useQuill } from './hooks/useQuill';
31
- import { getDataFromCloud } from './utils/dataFetcher';
32
- import { convertColumnInfoToColumnInternal, convertPostgresColumn, } from './utils/columnProcessing';
33
- import { getSelectFromAST, processApostrophe, processStarColumn, } from './utils/astProcessing';
26
+ import { convertColumnInfoToColumnInternal } from './utils/columnProcessing';
27
+ import { fetchAndProcessASTFromPrompt, fetchASTFromQuillReport, getAllPossibleColumns, } from './utils/astProcessing';
34
28
  import PivotForm from './internals/ReportBuilder/PivotForm';
35
29
  import { getSchemaInfoWithCustomFields } from './utils/schema';
36
30
  import { getDateBucketFromRange } from './utils/dates';
@@ -40,8 +34,7 @@ import useAstToFilterTree from './hooks/useAstToFilterTree';
40
34
  import { filterSentence } from './utils/filterProcessing';
41
35
  import { QuillMultiSelectComponentWithCombo } from './components/QuillMultiSelectWithCombo';
42
36
  import { shouldFetchMore, DEFAULT_PAGINATION, shouldSortInMemory, } from './utils/paginationProcessing';
43
- import { EMPTY_REPORT, formatRowsFromReport } from './utils/report';
44
- import { parseValueFromBigQueryDates } from './utils/dataProcessing';
37
+ import { EMPTY_REPORT, fetchReportBuilderDataFromAST, formatRowsFromReport, } from './utils/report';
45
38
  export const QUILL_SERVER = (typeof process !== 'undefined' && process?.env?.QUILL_SERVER_HOST) ||
46
39
  'https://quill-344421.uc.r.appspot.com';
47
40
  /**
@@ -75,8 +68,12 @@ export const QUILL_SERVER = (typeof process !== 'undefined' && process?.env?.QUI
75
68
  * ### Report Builder API
76
69
  * @see https://docs.quillsql.com/components/report-builder
77
70
  */
78
- export default function ReportBuilder({ initialTableName = '', onSubmitEditReport = () => void null, onSubmitCreateReport = () => void null, destinationDashboard = undefined, organizationName = '', ButtonComponent = MemoizedButton, SecondaryButtonComponent = MemoizedSecondaryButton, DeleteButtonComponent = MemoizedDeleteButton, ModalComponent = MemoizedModal, TextInputComponent = QuillTextInput, SelectComponent = QuillSelectComponent, MultiSelectComponent = QuillMultiSelectComponentWithCombo, TableComponent = QuillTableSQLEditorComponent, PopoverComponent = MemoizedPopover, TabsComponent = QuillTabs, CheckboxComponent = MemoizedCheckbox, SidebarComponent = QuillSidebar, ContainerComponent = CustomContainer, SelectColumnComponent = QuillSelectColumn, DraggableColumnComponent = QuillDraggableColumn, SidebarHeadingComponent = QuillSidebarHeading, FilterPopoverComponent = QuillFilterPopover, SortPopoverComponent = QuillSortPopover, LimitPopoverComponent = QuillLimitPopover, CardComponent = QuillCard, LabelComponent = MemoizedLabel, HeaderComponent = MemoizedHeader, SubHeaderComponent = MemoizedSubHeader, TextComponent = MemoizedText, ErrorMessageComponent = QuillErrorMessageComponent, ChartBuilderInputRowContainer = QuillChartBuilderInputRowContainer, ChartBuilderInputColumnContainer = QuillChartBuilderInputColumnContainer, PivotRowContainer = QuillPivotRowContainer, PivotColumnContainer = QuillPivotColumnContainer, LoadingComponent = QuillLoadingComponent, ColumnSearchEmptyState = QuillColumnSearchEmptyState, ChartBuilderFormContainer = QuillChartBuilderFormContainer, ChartBuilderModalComponent = MemoizedModal, isAdminEnabled = false, isAIEnabled = true, showChartBuilderTableFormatOptions = true, containerStyle, className, pivotRecommendationsEnabled = true, reportId, hideCopySQL = true, isChartBuilderHorizontalView = true, onClickChartElement, }) {
79
- const { data: report } = useQuill(reportId || '');
71
+ export default function ReportBuilder({ initialTableName = '', onSubmitEditReport = () => void null, onSubmitCreateReport = () => void null, destinationDashboard = undefined, organizationName = '', ButtonComponent = MemoizedButton, SecondaryButtonComponent = MemoizedSecondaryButton, DeleteButtonComponent = MemoizedDeleteButton, ModalComponent = MemoizedModal, TextInputComponent = QuillTextInput, SelectComponent = QuillSelectComponent, MultiSelectComponent = QuillMultiSelectComponentWithCombo, TableComponent = QuillTableSQLEditorComponent, PopoverComponent = MemoizedPopover, TabsComponent = QuillTabs,
72
+ // CheckboxComponent = MemoizedCheckbox,
73
+ SidebarComponent = QuillSidebar, ContainerComponent = CustomContainer, SelectColumnComponent = QuillSelectColumn, DraggableColumnComponent = QuillDraggableColumn, SidebarHeadingComponent = QuillSidebarHeading, FilterPopoverComponent = QuillFilterPopover, SortPopoverComponent = QuillSortPopover, LimitPopoverComponent = QuillLimitPopover, CardComponent = QuillCard, LabelComponent = MemoizedLabel, HeaderComponent = MemoizedHeader, SubHeaderComponent = MemoizedSubHeader, TextComponent = MemoizedText, ErrorMessageComponent = QuillErrorMessageComponent, ChartBuilderInputRowContainer = QuillChartBuilderInputRowContainer, ChartBuilderInputColumnContainer = QuillChartBuilderInputColumnContainer, PivotRowContainer = QuillPivotRowContainer, PivotColumnContainer = QuillPivotColumnContainer, LoadingComponent = QuillLoadingComponent, ColumnSearchEmptyState = QuillColumnSearchEmptyState, ChartBuilderFormContainer = QuillChartBuilderFormContainer, ChartBuilderModalComponent = MemoizedModal, isAdminEnabled = false, isAIEnabled = true, showChartBuilderTableFormatOptions = true, containerStyle, className, pivotRecommendationsEnabled = true, reportId, hideCopySQL = true, isChartBuilderHorizontalView = true, onClickChartElement, }) {
74
+ const [dashboard] = useContext(DashboardContext);
75
+ const [schema, setSchema] = useContext(SchemaContext);
76
+ const [reportInfo, setReportInfo] = useState(null);
80
77
  const [aiPrompt, setAiPrompt] = useState('');
81
78
  const [errorMessage, setErrorMessage] = useState('');
82
79
  const [baseAst, setBaseAst] = useState(null);
@@ -84,22 +81,20 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
84
81
  const [orderedColumnNames, setOrderedColumnNames] = useState([]);
85
82
  const [selectedColumns, setSelectedColumns] = useState([]);
86
83
  const [selectedOrderedColumns, setSelectedOrderedColumns] = useState([]);
87
- const [schema, setSchema] = useContext(SchemaContext);
88
84
  const [activeQuery, setActiveQuery] = useState('');
89
- const [activeEditItem, setActiveEditItem] = useState(null);
85
+ const [, setActiveEditItem] = useState(null);
90
86
  const [activePath, setActivePath] = useState(null);
91
87
  const [openPopover, setOpenPopover] = useState(null);
92
88
  const [loading, setLoading] = useState(!!initialTableName);
93
89
  const [loadingSchema, setLoadingSchema] = useState(false);
94
90
  const [isChartBuilderOpen, setIsChartBuilderOpen] = useState(false);
95
- const [isPending, setIsPending] = useState(false);
91
+ const [, setIsPending] = useState(false);
96
92
  const [isCopying, setIsCopying] = useState(false);
97
93
  const [dataDisplayed, setDataDisplayed] = useState(false);
98
94
  const [rows, setRows] = useState([]);
99
95
  const [formattedRows, setFormattedRows] = useState([]);
100
96
  const [columns, setColumns] = useState([]);
101
97
  const [tempReport, setTempReport] = useState(EMPTY_REPORT);
102
- const [topLevelBinaryOperator, setTopLevelBinaryOperator] = useState('AND');
103
98
  const [uniqueValues, setUniqueValues] = useState({});
104
99
  const [pivot, setPivot] = useState(null);
105
100
  const [pivotData, setPivotData] = useState(null);
@@ -183,7 +178,7 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
183
178
  const column = columns.find((c) => c.field === changeField);
184
179
  if (column?.jsType === 'date') {
185
180
  newPivot.rowFieldType = 'date';
186
- newPivot.sort = 'true';
181
+ newPivot.sort = true;
187
182
  newPivot.sortField = changeField;
188
183
  newPivot.sortFieldType = column.format;
189
184
  newPivot.sortDirection = 'ASC';
@@ -194,7 +189,7 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
194
189
  }
195
190
  }
196
191
  let dateBucket = undefined;
197
- const tempDateRange = dateRanges && dateRanges[newPivot.rowField];
192
+ const tempDateRange = dateRanges && dateRanges[newPivot.rowField || ''];
198
193
  if (tempDateRange) {
199
194
  dateBucket = getDateBucketFromRange(tempDateRange.dateRange);
200
195
  }
@@ -247,7 +242,6 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
247
242
  setDataDisplayed(false);
248
243
  setRows([]);
249
244
  setColumns([]);
250
- setTopLevelBinaryOperator('AND');
251
245
  setErrorMessage('');
252
246
  setFormattedRows([]);
253
247
  // setUniqueValues({});
@@ -264,12 +258,6 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
264
258
  clearAllState();
265
259
  }
266
260
  }, [client]);
267
- useEffect(() => {
268
- if (activePath !== null) {
269
- // update the modal with the new subtree
270
- setActiveEditItem(getByKey(formData, activePath));
271
- }
272
- }, [formData]);
273
261
  const formatRows = (rows, columns, pivot, aggregationType) => {
274
262
  const copiedRows = deepCopy(rows);
275
263
  if (pivot) {
@@ -314,19 +302,6 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
314
302
  return formattedRows;
315
303
  }
316
304
  };
317
- const getByKey = (formData, path) => {
318
- if (!path)
319
- return deepCopy(formData);
320
- // Function to immutably update or delete nodes based on their path
321
- const paths = path.split('.');
322
- let current = deepCopy(formData);
323
- for (let i = 0; i < paths.length; i++) {
324
- if (current[paths[i]]) {
325
- current = current[paths[i]];
326
- }
327
- }
328
- return current;
329
- };
330
305
  const copySQLToClipboard = () => {
331
306
  let query = activeQuery;
332
307
  if (pivot) {
@@ -371,7 +346,7 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
371
346
  const data = await response.json();
372
347
  setActiveQuery(data.query);
373
348
  if (fetchData) {
374
- fetchUponChange(ast, formData);
349
+ fetchReportFromASTHelper(ast, formData);
375
350
  }
376
351
  return data.query;
377
352
  }
@@ -459,7 +434,7 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
459
434
  return -1;
460
435
  return 0;
461
436
  });
462
- await handleAsk(`get ${columnsForTable} from ${initialTableName}`);
437
+ await fetchAstFromPromptHelper(`get ${columnsForTable} from ${initialTableName}`);
463
438
  setInitialLoad(false);
464
439
  };
465
440
  const fetchSchema = async () => {
@@ -498,106 +473,27 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
498
473
  };
499
474
  useEffect(() => {
500
475
  const loadChart = async () => {
501
- setInitialChartLoad(true);
502
- // @ts-ignore THIS PROCESS SHOULD BE UPDATED TO NOT USE USEQUILL
503
- if (!report || report.referencedTables.length !== 1) {
504
- setInitialChartLoad(false);
505
- return;
506
- }
476
+ let report;
507
477
  try {
508
- // @ts-ignore THIS PROCESS SHOULD BE UPDATED TO NOT USE USEQUILL
509
- const tableName = report.referencedTables[0];
510
- if (!tableName) {
511
- return;
512
- }
513
- const resp = await getDataFromCloud(client, `astify`, {
514
- // @ts-ignore THIS PROCESS SHOULD BE UPDATED TO NOT USE USEQUILL
515
- query: report.queryString,
516
- useNewNodeSql: true,
517
- });
518
- if (resp.success === false) {
519
- setErrorMessage(resp.message);
520
- return;
521
- }
522
- const ast = getSelectFromAST(resp.ast);
523
- let convertedAst = processStarColumn(ast, report.columns);
524
- processApostrophe(convertedAst, ['type', 'value']);
525
- convertedAst = convertBigQuery(convertedAst);
526
- const schemaInfo = schema.length !== 0 ? schema : await fetchSchema();
527
- let newAst;
528
- let groupByPivot = {};
529
- ({ ast: newAst, pivot: groupByPivot } = convertGroupBy(convertedAst,
530
- // @ts-ignore
531
- report.pivot, schemaInfo));
532
- if (convertedAst.where) {
533
- setFormData(deepCopy(convertedAst.where));
534
- }
535
- // @ts-ignore THIS PROCESS SHOULD BE UPDATED TO NOT USE USEQUILL
536
- setActiveQuery(report.queryString);
537
- newAst = groupByPivot ? newAst : convertedAst;
538
- const initialRows = await fetchUponChange(newAst, undefined);
539
- if (initialRows.error) {
540
- setBaseAst(null);
541
- setErrorMessage(initialRows.message);
542
- setInitialChartLoad(false);
543
- return;
544
- }
545
- setBaseAst(newAst);
546
- const tableInfo = schemaInfo.find((table) => table.name === tableName);
547
- let newUniqueValues = undefined;
548
- let dateRangesTemp = undefined;
549
- if (tableName) {
550
- newUniqueValues = await getUniqueStringValues(tableInfo.columns, tableName);
551
- setUniqueValues(newUniqueValues);
552
- dateRangesTemp = await getDateRanges(tableInfo.columns, tableName);
553
- setDateRanges(dateRangesTemp);
554
- }
555
- if (groupByPivot) {
556
- // @ts-ignore
557
- setPivotRowField(groupByPivot.rowField);
558
- // @ts-ignore
559
- setPivotAggregation(groupByPivot.aggregationType);
560
- // @ts-ignore
561
- setPivotColumnField(groupByPivot.columnField);
562
- // @ts-ignore
563
- setPivotValueField(groupByPivot.valueField);
564
- setPivot(groupByPivot);
565
- let dateBucket = undefined;
566
- const tempDateRange = dateRangesTemp &&
567
- groupByPivot.rowField &&
568
- dateRangesTemp[groupByPivot.rowField];
569
- if (tempDateRange) {
570
- dateBucket = getDateBucketFromRange(tempDateRange.dateRange);
571
- }
572
- const pivotedData = await generatePivotTable(
573
- // @ts-ignore
574
- groupByPivot, initialRows, tempDateRange, false, -1, undefined, dateBucket, report, client, newUniqueValues[tableName]);
575
- setPivotData(pivotedData || []);
576
- const formattedRows = formatRows(pivotedData.rows, report.columns, true,
577
- // @ts-ignore
578
- groupByPivot.aggregationType);
579
- setFormattedRows(formattedRows);
580
- }
581
- else {
582
- const formattedRows = formatRows(report.rows, report.columns);
583
- setFormattedRows(formattedRows);
584
- }
585
- setCurrentTable(tableName);
586
- }
587
- catch (error) {
588
- console.error(error);
589
- setErrorMessage('Error loading report');
478
+ if (!reportId) {
479
+ throw new Error('Report ID is required');
480
+ }
481
+ report = dashboard[reportId];
482
+ if (!report || report.referencedTables?.length !== 1) {
483
+ throw new Error('Report not found');
484
+ }
485
+ const { ast: newAst, pivot: newPivot, schema: curSchema, } = await fetchASTFromQuillReport(report, client, schema);
486
+ setBaseAst({ ...newAst, where: null });
487
+ await fetchReportFromASTHelper({ ...newAst, where: null }, newAst.where, newPivot, curSchema, report);
488
+ await fetchSchema();
489
+ setReportInfo(report);
590
490
  }
591
- // This handles a flashing issue
592
- setTimeout(() => {
491
+ catch (err) {
593
492
  setInitialChartLoad(false);
594
- }, 500);
493
+ }
595
494
  };
596
- // @ts-ignore THIS PROCESS SHOULD BE UPDATED TO NOT USE USEQUILL
597
- if (report && report.referencedTables.length === 1) {
598
- loadChart();
599
- }
600
- }, [report]);
495
+ loadChart();
496
+ }, [dashboard[reportId || '']]);
601
497
  useEffect(() => {
602
498
  if (schema.length === 0) {
603
499
  fetchSchema();
@@ -620,7 +516,7 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
620
516
  ...defaultAST,
621
517
  ...baseAst,
622
518
  ...(!baseAst?.columns && {
623
- columns: getAllPossibleColumns().map((c) => {
519
+ columns: getAllPossibleColumns(baseAst, schema).map((c) => {
624
520
  const newColumn = deepCopy(defaultColumn);
625
521
  newColumn.expr.column = c.name;
626
522
  return newColumn;
@@ -640,7 +536,7 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
640
536
  ...defaultAST,
641
537
  ...baseAst,
642
538
  ...(!baseAst?.columns && {
643
- columns: getAllPossibleColumns().map((c) => {
539
+ columns: getAllPossibleColumns(baseAst, schema).map((c) => {
644
540
  const newColumn = deepCopy(defaultColumn);
645
541
  newColumn.expr.column = c.name;
646
542
  return newColumn;
@@ -741,7 +637,7 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
741
637
  ...defaultAST,
742
638
  ...baseAst,
743
639
  ...(!baseAst?.columns && {
744
- columns: getAllPossibleColumns().map((c) => {
640
+ columns: getAllPossibleColumns(baseAst, schema).map((c) => {
745
641
  const newColumn = deepCopy(defaultColumn);
746
642
  newColumn.expr.column = c.name;
747
643
  return newColumn;
@@ -756,169 +652,6 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
756
652
  fetchSqlQuery(newAst, newState);
757
653
  });
758
654
  };
759
- // TODO: Merge this function with the updateFormData function
760
- const updateActiveItem = (updates, { isDeletion = false, isInsertion = false, isReplaceSubtree = false, isAddVariant = false, isDeleteVariant = false, column = undefined, }) => {
761
- let newState = deepCopy(activeEditItem);
762
- updates.forEach(({ path, value }) => {
763
- let current = newState;
764
- const globalPath = path;
765
- const paths = globalPath.split('.').filter((p) => p);
766
- if (paths.length === 0 && !isInsertion && !isReplaceSubtree) {
767
- setActiveEditItem(null);
768
- return;
769
- }
770
- const isOperatorChange = paths[paths.length - 1] === 'operator';
771
- let parent = null;
772
- let parentKey = null;
773
- for (let i = 0; i < paths.length - 1; i++) {
774
- let currentPath = paths[i];
775
- let index;
776
- if (paths[i].includes('||')) {
777
- const splitPath = paths[i].split('||');
778
- currentPath = splitPath[0];
779
- index = splitPath[1];
780
- }
781
- if (current[currentPath]) {
782
- parent = current;
783
- parentKey = currentPath;
784
- current = current[currentPath];
785
- }
786
- if (index) {
787
- current = current[parseInt(index)];
788
- }
789
- }
790
- const lastKey = paths[paths.length - 1];
791
- if (isDeletion) {
792
- if (lastKey === 'left' || lastKey === 'right') {
793
- if (parent) {
794
- if (lastKey === 'right') {
795
- parent[parentKey] = parent[parentKey].left;
796
- }
797
- else {
798
- parent[parentKey] = parent[parentKey].right;
799
- }
800
- }
801
- else {
802
- delete current[lastKey];
803
- if (newState?.left && !newState?.right) {
804
- newState = newState.left;
805
- }
806
- else if (newState?.right && !newState?.left) {
807
- newState = newState.right;
808
- }
809
- }
810
- }
811
- }
812
- else if (isInsertion) {
813
- const columns = getAllPossibleColumns();
814
- const defaultColumn = columns[0].name;
815
- // TODO: I think this is a bug, take a closer look here
816
- newState = {
817
- type: 'binary_expr',
818
- operator: 'AND',
819
- left: newState,
820
- right: {
821
- ...defaultEntry,
822
- left: {
823
- ...defaultEntry.left,
824
- column: defaultColumn,
825
- },
826
- },
827
- };
828
- }
829
- else if (isAddVariant) {
830
- const newVariant = deepCopy(defaultVariant);
831
- if (value) {
832
- newVariant.args.value[0].value = value;
833
- // if there is already a single default value there,
834
- // let's remove it so when we push we replace.
835
- if (current[lastKey].length === 1 &&
836
- current[lastKey][0].args.value[0].value === '') {
837
- current[lastKey].pop();
838
- }
839
- }
840
- current[lastKey].push(newVariant);
841
- }
842
- else if (isDeleteVariant) {
843
- if (value) {
844
- const argList = current[lastKey];
845
- argList.splice(argList.findIndex((arg) => arg.args.value[0].value === value), 1);
846
- }
847
- else {
848
- current[lastKey].pop();
849
- }
850
- // add back in a phantom element to prevent app from crashing
851
- // when the user removes all variants and hits save.
852
- if (current[lastKey].length === 0) {
853
- const newVariant = deepCopy(defaultVariant);
854
- newVariant.args.value[0].value = '';
855
- current[lastKey].push(newVariant);
856
- }
857
- }
858
- else if (isReplaceSubtree) {
859
- if (lastKey) {
860
- current[lastKey] = value;
861
- }
862
- else {
863
- newState = value;
864
- }
865
- }
866
- else if (isOperatorChange) {
867
- const newOp = value;
868
- const oldOp = current[lastKey];
869
- if (OPERATOR_GROUPS[oldOp] === OPERATOR_GROUPS[newOp]) {
870
- current[lastKey] = value;
871
- }
872
- else {
873
- const group = OPERATOR_GROUPS[newOp];
874
- const subtree = getDefaultOperatorSubtrees(group, newOp, column, '', client.databaseType);
875
- if (parentKey) {
876
- parent[parentKey] = deepCopy(subtree);
877
- }
878
- else {
879
- newState = deepCopy(subtree);
880
- }
881
- }
882
- }
883
- else {
884
- if (typeof current[lastKey] === 'object' && current[lastKey] !== null) {
885
- current[lastKey].value = value;
886
- }
887
- else {
888
- current[lastKey] = value;
889
- }
890
- }
891
- });
892
- // Function to immutably update or delete nodes based on their path
893
- setActiveEditItem(newState);
894
- };
895
- const handleChange = (updates) => {
896
- const callback = isPending ? updateActiveItem : updateFormData;
897
- callback(updates, {});
898
- };
899
- const handleChangeText = (updates) => {
900
- const callback = isPending ? updateActiveItem : updateFormData;
901
- callback(updates, {});
902
- };
903
- // Function to handle operator changes
904
- const handleOperatorChange = (value, node, keyPrefix, column = null) => {
905
- if (!keyPrefix) {
906
- setTopLevelBinaryOperator(value);
907
- }
908
- if (isPending) {
909
- updateActiveItem([{ path: keyPrefix + 'operator', value }], { column });
910
- }
911
- else {
912
- updateFormData([{ path: keyPrefix + 'operator', value }], { column });
913
- }
914
- };
915
- // Function to replace an entire subtree with a given value.
916
- const handleReplaceSubtree = (keyPrefix, newValue, pending = isPending) => {
917
- const callback = pending ? updateActiveItem : updateFormData;
918
- callback([{ path: keyPrefix, value: newValue }], {
919
- isReplaceSubtree: true,
920
- });
921
- };
922
655
  // Function to handle the insertion of expressions
923
656
  const handleInsertion = (value, op = 'OR', isCondition = undefined) => {
924
657
  updateFormData([{ path: '', value }], {
@@ -927,23 +660,6 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
927
660
  isCondition,
928
661
  });
929
662
  };
930
- // Function to handle the insertion of expr_list variants
931
- const handleInsertVariant = (key, name = null) => {
932
- // note: if name, treat that as the name of the value to insert
933
- const callback = isPending ? updateActiveItem : updateFormData;
934
- callback([{ path: key, value: name }], { isAddVariant: true });
935
- };
936
- // Function to handle the insertion of expr_list variants
937
- const handleDeleteVariant = (key, name = null) => {
938
- // note: if name, treat that as the name of the valeu to delete
939
- const callback = isPending ? updateActiveItem : updateFormData;
940
- callback([{ path: key, value: name }], { isDeleteVariant: true });
941
- };
942
- const getColumnValueForColumnComparison = (node) => node.left.value ??
943
- node.left.column ??
944
- node.left.args?.value[0]?.value ??
945
- node.left.args?.value[0]?.column ??
946
- undefined;
947
663
  /**
948
664
  * Searches for the column by name and returns the field type.
949
665
  *
@@ -1040,676 +756,6 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
1040
756
  return;
1041
757
  }
1042
758
  };
1043
- /**
1044
- * Render form fields based on the type of the node
1045
- * @param node the AST or subtree to render recursively
1046
- * @param keyPrefix a stringified version of the path from the root
1047
- *
1048
- * Note: The keyPrefix should be separated by '.' characters and each item
1049
- * should be a valid index into the node (eg. 'left.right.value' is a valid
1050
- * keyPrefix but 'left.args[0].value' is not -- should be 'left.args.0.value')
1051
- */
1052
- const renderNode = (node, keyPrefix = '') => {
1053
- const dateComparisonPartialMatch = formatDateComparisonNode(node);
1054
- switch (node.type) {
1055
- case 'binary_expr':
1056
- if (dateComparisonPartialMatch ||
1057
- (isDateTruncEquals(node) && client.databaseType !== 'BigQuery')) {
1058
- const { dateColumn, dateFilterType, intervalCount, intervalType, intervalPaths, } = getDateFilterInfo(node);
1059
- const isPlural = intervalCount !== 1 && dateFilterType !== 'in the current'
1060
- ? 's'
1061
- : '';
1062
- // Pull off the string literal date for "equals" comparisons
1063
- const rawDateStringEquals = node.right?.value ??
1064
- node.right?.args?.value[1]?.column ??
1065
- node.right?.args?.value[1]?.value;
1066
- const rawDateStringEqualsPath = (node.right?.value && 'node.right.value') ??
1067
- (node.right?.args?.value[1]?.column &&
1068
- 'node.right.args.value.1.column') ??
1069
- (node.right?.args?.value[1]?.value &&
1070
- 'node.right.args.value.1.value');
1071
- return (_jsxs("div", { style: { display: 'flex', gap: 20 }, children: [_jsx(SelectComponent, { value: dateColumn, onChange: (event) => {
1072
- const columnType = getColumnTypeByName(event.target.value);
1073
- if (isDateishColumnType(columnType)) {
1074
- // handleChange(value, keyPrefix + dateColumnPath, "text");
1075
- handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
1076
- }
1077
- else if (isNumericColumnType(columnType)) {
1078
- const newSubtree = deepCopy(defaultNumericComparison);
1079
- newSubtree.left.column = event.target.value;
1080
- handleReplaceSubtree(keyPrefix, newSubtree);
1081
- }
1082
- else if (isBoolColumnType(columnType)) {
1083
- const newSubtree = deepCopy(defaultBoolComparison);
1084
- newSubtree.left.column = event.target.value;
1085
- handleReplaceSubtree(keyPrefix, newSubtree);
1086
- }
1087
- else {
1088
- const newSubtree = deepCopy(defaultEntry);
1089
- newSubtree.left.args.value[0].column = event.target.value;
1090
- handleReplaceSubtree(keyPrefix, newSubtree);
1091
- }
1092
- }, options: getAllPossibleColumns().map((column) => ({
1093
- label: snakeAndCamelCaseToTitleCase(column.displayName),
1094
- value: column.name,
1095
- })), width: 200 }), _jsx(SelectComponent, { value: dateFilterType, onChange: (event) => {
1096
- if (event.target.value === dateFilterType)
1097
- return null;
1098
- let newSubtree = {};
1099
- // TODO: implement one for each database type (eg. pg, snowflake, etc.)
1100
- if (event.target.value === 'in the last') {
1101
- newSubtree = generateLastNPeriodsPostgres({
1102
- dateField: dateColumn,
1103
- intervalPeriod: `${intervalCount ?? 1} ${intervalType}`,
1104
- });
1105
- }
1106
- else if (event.target.value === 'in the previous') {
1107
- newSubtree = generatePreviousPeriodPostgres({
1108
- dateField: dateColumn,
1109
- intervalPeriod: `${intervalCount ?? 1} ${intervalType}`,
1110
- currentPeriod: intervalType,
1111
- });
1112
- }
1113
- else if (event.target.value === 'in the current') {
1114
- newSubtree = generateCurrentPeriodPostgres({
1115
- dateField: dateColumn,
1116
- currentPeriod: intervalType,
1117
- });
1118
- }
1119
- else if (event.target.value === 'equals') {
1120
- newSubtree = generateEqualsPostgres({
1121
- dateField: dateColumn,
1122
- currentPeriod: intervalType,
1123
- timestamp: '2024-01-01',
1124
- });
1125
- }
1126
- // replace the entire subtree for this filter
1127
- handleReplaceSubtree(keyPrefix, newSubtree);
1128
- }, options: [
1129
- { label: 'in the last', value: 'in the last' },
1130
- { label: 'in the previous', value: 'in the previous' },
1131
- { label: 'in the current', value: 'in the current' },
1132
- { label: 'equals', value: 'equals' },
1133
- ], width: 200 }), !['in the current', 'equals'].includes(dateFilterType) && (_jsx(TextInputComponent, { id: "date_filter_interval_count", value: intervalCount?.toString() ?? '', width: 70, onChange: (e) => {
1134
- if (Number.isNaN(parseFloat(e.target.value || '0'))) {
1135
- alert('Please input a number.');
1136
- return;
1137
- }
1138
- const isPluralNow = parseFloat(e.target.value || '0') !== 1 ? 's' : '';
1139
- intervalPaths.forEach((intervalPath) => handleChangeText([
1140
- {
1141
- value: `${e.target.value || 0} ${intervalType}${isPluralNow}`,
1142
- path: keyPrefix + intervalPath,
1143
- },
1144
- ]));
1145
- } })), _jsx(SelectComponent, { value: intervalType, onChange: (event) => {
1146
- if (intervalPaths.length === 1 &&
1147
- dateFilterType !== 'in the previous') {
1148
- handleChangeText([
1149
- {
1150
- value: intervalCount !== null
1151
- ? `${intervalCount} ${event.target.value}${isPlural}`
1152
- : event.target.value,
1153
- path: keyPrefix + intervalPaths[0],
1154
- },
1155
- ]);
1156
- return;
1157
- }
1158
- let newSubtree;
1159
- if (dateFilterType === 'in the previous') {
1160
- newSubtree = generatePreviousPeriodPostgres({
1161
- dateField: dateColumn,
1162
- intervalPeriod: `${intervalCount ?? 1} ${event.target.value}`,
1163
- currentPeriod: event.target.value,
1164
- });
1165
- }
1166
- else if (dateFilterType === 'equals') {
1167
- newSubtree = generateEqualsPostgres({
1168
- dateField: dateColumn,
1169
- currentPeriod: event.target.value,
1170
- timestamp: rawDateStringEquals,
1171
- });
1172
- }
1173
- else {
1174
- newSubtree = generateCurrentPeriodPostgres({
1175
- dateField: dateColumn,
1176
- currentPeriod: event.target.value,
1177
- });
1178
- }
1179
- handleReplaceSubtree(keyPrefix, newSubtree);
1180
- }, options: dateFilterType === 'in the previous' ||
1181
- dateFilterType === 'in the last'
1182
- ? [
1183
- { label: `year${isPlural}`, value: 'year' },
1184
- { label: `month${isPlural}`, value: 'month' },
1185
- { label: `week${isPlural}`, value: 'week' },
1186
- { label: `day${isPlural}`, value: 'day' },
1187
- { label: `hour${isPlural}`, value: 'hour' },
1188
- ]
1189
- : [
1190
- { label: `year${isPlural}`, value: 'year' },
1191
- { label: `quarter${isPlural}`, value: 'quarter' },
1192
- { label: `month${isPlural}`, value: 'month' },
1193
- { label: `week${isPlural}`, value: 'week' },
1194
- { label: `day${isPlural}`, value: 'day' },
1195
- { label: `hour${isPlural}`, value: 'hour' },
1196
- ], width: 200 }), dateFilterType === 'equals' && (_jsx(TextInputComponent, { id: "date_filter_equals_raw_date", value: rawDateStringEquals, width: 120, onChange: (e) => {
1197
- handleChangeText([
1198
- {
1199
- value: e.target.value,
1200
- path: keyPrefix + rawDateStringEqualsPath,
1201
- },
1202
- ]);
1203
- } }))] }));
1204
- }
1205
- else if (isInTheLastInterval(node, client.databaseType)) {
1206
- const { dateColumn } = getDateFilterInfo(node);
1207
- const options = getAllPossibleColumns().map((column) => ({
1208
- label: snakeAndCamelCaseToTitleCase(column.displayName),
1209
- value: column.name,
1210
- }));
1211
- const plural = node.right.args.value[1].expr.value !== 1 ? 's' : '';
1212
- return (_jsxs("div", { style: {
1213
- display: 'flex',
1214
- flexDirection: 'row',
1215
- alignItems: 'center',
1216
- gap: 20,
1217
- }, children: [_jsx(SelectComponent, { value: node.left.column, onChange: (event) => {
1218
- const columnType = getColumnTypeByName(event.target.value);
1219
- if (isDateishColumnType(columnType)) {
1220
- // handleChange(value, keyPrefix + dateColumnPath, "text");
1221
- handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
1222
- }
1223
- else if (isNumericColumnType(columnType)) {
1224
- const newSubtree = deepCopy(defaultNumericComparison);
1225
- newSubtree.left.column = event.target.value;
1226
- handleReplaceSubtree(keyPrefix, newSubtree);
1227
- }
1228
- else if (isBoolColumnType(columnType)) {
1229
- const newSubtree = deepCopy(defaultBoolComparison);
1230
- newSubtree.left.column = event.target.value;
1231
- handleReplaceSubtree(keyPrefix, newSubtree);
1232
- }
1233
- else {
1234
- const newSubtree = deepCopy(defaultEntry);
1235
- newSubtree.left.args.value[0].column = event.target.value;
1236
- handleReplaceSubtree(keyPrefix, newSubtree);
1237
- }
1238
- }, options: options, width: 200 }), _jsx(SelectComponent, { value: 'IN_THE_LAST', onChange: (event) => {
1239
- handleOperatorChange(event.target.value, node, keyPrefix, dateColumn);
1240
- }, options: [
1241
- { label: 'in the last', value: 'IN_THE_LAST' },
1242
- { label: 'in the previous', value: 'IN_THE_PREVIOUS' },
1243
- { label: 'in the current', value: 'IN_THE_CURRENT' },
1244
- { label: 'equals', value: 'EQUALS' },
1245
- { label: 'is not null', value: 'IS NOT' },
1246
- { label: 'is null', value: 'IS' },
1247
- ], width: 200 }), _jsx(TextInputComponent, { id: 'date_window_interval_count', value: node.right.args.value[1].expr.value, width: 120, onChange: (e) => {
1248
- handleChange([
1249
- {
1250
- value: e.target.value,
1251
- path: keyPrefix + 'right.args.value||1.expr.value',
1252
- },
1253
- ]);
1254
- } }), _jsx("div", { children: _jsx(SelectComponent, { value: node.right.args.value[1].unit, onChange: (event) => handleChange([
1255
- {
1256
- value: event.target.value,
1257
- path: keyPrefix + 'right.args.value||1.unit',
1258
- },
1259
- ]), options: [
1260
- { label: `year${plural}`, value: '* 365 DAY' },
1261
- { label: `month${plural}`, value: '* 30 DAY' },
1262
- { label: `week${plural}`, value: '* 7 DAY' },
1263
- { label: `day${plural}`, value: 'DAY' },
1264
- ], width: 200 }) })] }));
1265
- }
1266
- else if (isTheCurrentInterval(node, client.databaseType)) {
1267
- const options = getAllPossibleColumns().map((column) => ({
1268
- label: snakeAndCamelCaseToTitleCase(column.displayName),
1269
- value: column.name,
1270
- }));
1271
- return (_jsxs("div", { style: {
1272
- display: 'flex',
1273
- flexDirection: 'row',
1274
- alignItems: 'center',
1275
- gap: 20,
1276
- }, children: [_jsx(SelectComponent, { value: node.left.column, onChange: (event) => {
1277
- const columnType = getColumnTypeByName(event.target.value);
1278
- if (isDateishColumnType(columnType)) {
1279
- // handleChange(value, keyPrefix + dateColumnPath, "text");
1280
- handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
1281
- }
1282
- else if (isNumericColumnType(columnType)) {
1283
- const newSubtree = deepCopy(defaultNumericComparison);
1284
- newSubtree.left.column = event.target.value;
1285
- handleReplaceSubtree(keyPrefix, newSubtree);
1286
- }
1287
- else if (isBoolColumnType(columnType)) {
1288
- const newSubtree = deepCopy(defaultBoolComparison);
1289
- newSubtree.left.column = event.target.value;
1290
- handleReplaceSubtree(keyPrefix, newSubtree);
1291
- }
1292
- else {
1293
- const newSubtree = deepCopy(defaultEntry);
1294
- newSubtree.left.args.value[0].column = event.target.value;
1295
- handleReplaceSubtree(keyPrefix, newSubtree);
1296
- }
1297
- }, options: options, width: 200 }), _jsx(SelectComponent, { value: 'IN_THE_CURRENT', onChange: (event) => {
1298
- handleOperatorChange(event.target.value, node, keyPrefix, node.left.column);
1299
- }, options: [
1300
- { label: 'in the last', value: 'IN_THE_LAST' },
1301
- { label: 'in the previous', value: 'IN_THE_PREVIOUS' },
1302
- { label: 'in the current', value: 'IN_THE_CURRENT' },
1303
- { label: 'equals', value: 'EQUALS' },
1304
- { label: 'is not null', value: 'IS NOT' },
1305
- { label: 'is null', value: 'IS' },
1306
- // { label: 'equals', value: 'equals' },
1307
- ], width: 200 }), _jsx(SelectComponent, { value: node.left.args.value[1].column, onChange: (event) => {
1308
- handleChange([
1309
- {
1310
- value: event.target.value,
1311
- path: 'right.args.value||1.column',
1312
- },
1313
- {
1314
- value: event.target.value,
1315
- path: 'left.args.value||1.column',
1316
- },
1317
- ]);
1318
- }, options: [
1319
- { label: `year`, value: 'YEAR' },
1320
- { label: `quarter`, value: 'QUARTER' },
1321
- { label: `month`, value: 'MONTH' },
1322
- { label: `week`, value: 'WEEK' },
1323
- ], width: 200 })] }));
1324
- }
1325
- else if (isThePreviousInterval(node)) {
1326
- const options = getAllPossibleColumns().map((column) => ({
1327
- label: snakeAndCamelCaseToTitleCase(column.displayName),
1328
- value: column.name,
1329
- }));
1330
- return (_jsxs("div", { style: {
1331
- display: 'flex',
1332
- flexDirection: 'row',
1333
- alignItems: 'center',
1334
- gap: 20,
1335
- }, children: [_jsx(SelectComponent, { value: node.left.column, onChange: (event) => {
1336
- const columnType = getColumnTypeByName(event.target.value);
1337
- if (isDateishColumnType(columnType)) {
1338
- // handleChange(value, keyPrefix + dateColumnPath, "text");
1339
- handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
1340
- }
1341
- else if (isNumericColumnType(columnType)) {
1342
- const newSubtree = deepCopy(defaultNumericComparison);
1343
- newSubtree.left.column = event.target.value;
1344
- handleReplaceSubtree(keyPrefix, newSubtree);
1345
- }
1346
- else if (isBoolColumnType(columnType)) {
1347
- const newSubtree = deepCopy(defaultBoolComparison);
1348
- newSubtree.left.column = event.target.value;
1349
- handleReplaceSubtree(keyPrefix, newSubtree);
1350
- }
1351
- else {
1352
- const newSubtree = deepCopy(defaultEntry);
1353
- newSubtree.left.args.value[0].column = event.target.value;
1354
- handleReplaceSubtree(keyPrefix, newSubtree);
1355
- }
1356
- }, options: options, width: 200 }), _jsx(SelectComponent, { value: 'IN_THE_PREVIOUS', onChange: (event) => {
1357
- handleOperatorChange(event.target.value, node, keyPrefix, node.left.column);
1358
- }, options: [
1359
- { label: 'in the last', value: 'IN_THE_LAST' },
1360
- { label: 'in the previous', value: 'IN_THE_PREVIOUS' },
1361
- { label: 'in the current', value: 'IN_THE_CURRENT' },
1362
- { label: 'equals', value: 'EQUALS' },
1363
- { label: 'is not null', value: 'IS NOT' },
1364
- { label: 'is null', value: 'IS' },
1365
- // { label: 'equals', value: 'equals' },
1366
- ], width: 200 }), _jsx(SelectComponent, { value: node.left.args.value[1].column, onChange: (event) => {
1367
- const dayConversion = {
1368
- YEAR: 365,
1369
- QUARTER: 90,
1370
- MONTH: 30,
1371
- WEEK: 7,
1372
- };
1373
- handleChange([
1374
- {
1375
- value: event.target.value,
1376
- path: 'left.args.value||1.column',
1377
- },
1378
- {
1379
- value: event.target.value,
1380
- path: 'right.args.value||1.column',
1381
- },
1382
- {
1383
- value: dayConversion[event.target.value] || 30,
1384
- path: 'right.args.value||0.args.value||1.expr.value',
1385
- },
1386
- ]);
1387
- }, options: [
1388
- { label: `year`, value: 'YEAR' },
1389
- { label: `quarter`, value: 'QUARTER' },
1390
- { label: `month`, value: 'MONTH' },
1391
- { label: `week`, value: 'WEEK' },
1392
- ], width: 200 })] }));
1393
- }
1394
- else if (isEquals(node, client.databaseType)) {
1395
- const options = getAllPossibleColumns().map((column) => ({
1396
- label: snakeAndCamelCaseToTitleCase(column.displayName),
1397
- value: column.name,
1398
- }));
1399
- return (_jsxs("div", { style: {
1400
- display: 'flex',
1401
- flexDirection: 'row',
1402
- alignItems: 'center',
1403
- gap: 20,
1404
- }, children: [_jsx(SelectComponent, { value: node.left.column, onChange: (event) => {
1405
- const columnType = getColumnTypeByName(event.target.value);
1406
- if (isDateishColumnType(columnType)) {
1407
- // handleChange(value, keyPrefix + dateColumnPath, "text");
1408
- handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
1409
- }
1410
- else if (isNumericColumnType(columnType)) {
1411
- const newSubtree = deepCopy(defaultNumericComparison);
1412
- newSubtree.left.column = event.target.value;
1413
- handleReplaceSubtree(keyPrefix, newSubtree);
1414
- }
1415
- else if (isBoolColumnType(columnType)) {
1416
- const newSubtree = deepCopy(defaultBoolComparison);
1417
- newSubtree.left.column = event.target.value;
1418
- handleReplaceSubtree(keyPrefix, newSubtree);
1419
- }
1420
- else {
1421
- const newSubtree = deepCopy(defaultEntry);
1422
- newSubtree.left.args.value[0].column = event.target.value;
1423
- handleReplaceSubtree(keyPrefix, newSubtree);
1424
- }
1425
- }, options: options, width: 200 }), _jsx(SelectComponent, { value: 'EQUALS', onChange: (event) => {
1426
- handleOperatorChange(event.target.value, node, keyPrefix, node.left.column);
1427
- }, options: [
1428
- { label: 'in the last', value: 'IN_THE_LAST' },
1429
- { label: 'in the previous', value: 'IN_THE_PREVIOUS' },
1430
- { label: 'in the current', value: 'IN_THE_CURRENT' },
1431
- { label: 'equals', value: 'EQUALS' },
1432
- { label: 'is not null', value: 'IS NOT' },
1433
- { label: 'is null', value: 'IS' },
1434
- // { label: 'equals', value: 'equals' },
1435
- ], width: 200 }), _jsx(SelectComponent, { value: node.right.args.value[1].column, onChange: (event) => {
1436
- handleChange([
1437
- {
1438
- value: event.target.value,
1439
- path: 'right.args.value||1.column',
1440
- },
1441
- {
1442
- value: event.target.value,
1443
- path: 'left.args.value||1.column',
1444
- },
1445
- ]);
1446
- }, options: [
1447
- { label: `year`, value: 'YEAR' },
1448
- { label: `quarter`, value: 'QUARTER' },
1449
- { label: `month`, value: 'MONTH' },
1450
- { label: `week`, value: 'WEEK' },
1451
- ], width: 200 }), _jsx(TextInputComponent, { id: 'quoted_string', value: node.right.args.value[0].value, width: 120, onChange: (e) => handleChange([
1452
- {
1453
- value: e.target.value,
1454
- path: 'right.args.value||0.value',
1455
- },
1456
- ]) })] }));
1457
- }
1458
- else if (isColumnComparison(node)) {
1459
- const options = getAllPossibleColumns().map((column) => ({
1460
- label: snakeAndCamelCaseToTitleCase(column.displayName),
1461
- value: column.name,
1462
- }));
1463
- // grab the value of the left child of the column comparison
1464
- // operator (ie. the column name)
1465
- const leftChildValue = getColumnValueForColumnComparison(node);
1466
- const tables = getTableNames(baseAst);
1467
- const table = tables.length === 1 ? tables[0] : initialTableName;
1468
- const column = schema
1469
- .find((tableInfo) => tableInfo.name === table)
1470
- ?.columns.find((col) => col.name === leftChildValue);
1471
- const columnType = column?.fieldType;
1472
- const operatorOptions = [
1473
- ...(isNumericColumnType(columnType)
1474
- ? [
1475
- { label: 'equal to', value: '=' },
1476
- { label: 'not equal to', value: '!=' },
1477
- { label: 'greater than', value: '>' },
1478
- { label: 'less than', value: '<' },
1479
- { label: 'greater than or equal to', value: '>=' },
1480
- { label: 'less than or equal to', value: '<=' },
1481
- { label: 'is not null', value: 'IS NOT' },
1482
- { label: 'is null', value: 'IS' },
1483
- ]
1484
- : []),
1485
- ...(isTextColumnType(columnType)
1486
- ? [
1487
- { label: 'is exactly', value: 'LIKE' },
1488
- { label: 'is not exactly', value: 'NOT LIKE' },
1489
- { label: 'is', value: 'IN' },
1490
- { label: 'is not', value: 'NOT IN' },
1491
- { label: 'is not null', value: 'IS NOT' },
1492
- { label: 'is null', value: 'IS' },
1493
- ]
1494
- : []),
1495
- ...(isDateishColumnType(columnType)
1496
- ? [
1497
- { label: 'in the last', value: 'IN_THE_LAST' },
1498
- {
1499
- label: 'in the previous',
1500
- value: 'IN_THE_PREVIOUS',
1501
- },
1502
- { label: 'in the current', value: 'IN_THE_CURRENT' },
1503
- { label: 'equals', value: 'equals' },
1504
- ]
1505
- : []),
1506
- ];
1507
- return (_jsxs("div", { style: {
1508
- display: 'flex',
1509
- gap: 12,
1510
- flexDirection: 'column',
1511
- width: '100%',
1512
- padding: '6px 0px',
1513
- }, children: [_jsxs("div", { style: {
1514
- display: 'flex',
1515
- gap: 20,
1516
- flexDirection: showNodeAsRow(node, formData)
1517
- ? 'row'
1518
- : 'column',
1519
- width: '100%',
1520
- }, children: [_jsx(SelectComponent, { value: leftChildValue, onChange: (event) => {
1521
- const columnType = getColumnTypeByName(event.target.value);
1522
- if (isDateishColumnType(columnType)) {
1523
- handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
1524
- }
1525
- else if (isNumericColumnType(columnType)) {
1526
- const newSubtree = deepCopy(defaultNumericComparison);
1527
- newSubtree.left.column = event.target.value;
1528
- handleReplaceSubtree(keyPrefix, newSubtree);
1529
- }
1530
- else if (isBoolColumnType(columnType)) {
1531
- const newSubtree = deepCopy(defaultBoolComparison);
1532
- newSubtree.left.column = event.target.value;
1533
- handleReplaceSubtree(keyPrefix, newSubtree);
1534
- }
1535
- else {
1536
- const newSubtree = deepCopy(defaultEntry);
1537
- newSubtree.left.args.value[0].column = event.target.value;
1538
- handleReplaceSubtree(keyPrefix, newSubtree);
1539
- }
1540
- }, options: options, width: 200 }), operatorOptions.length > 0 && (_jsx(SelectComponent, { value: node.operator, onChange: (event) => {
1541
- handleOperatorChange(event.target.value, node, keyPrefix, leftChildValue);
1542
- }, options: operatorOptions, width: 200 })), node.right &&
1543
- node.right.type !== 'expr_list' &&
1544
- renderNode(node.right, keyPrefix + 'right.')] }, keyPrefix), node.right && node.right.type === 'expr_list' && (_jsx("div", { style: {
1545
- display: 'grid',
1546
- gridTemplateColumns: 'repeat(2, 1fr)',
1547
- gap: 12,
1548
- }, children: uniqueValues[table] &&
1549
- Object.keys(uniqueValues[table][leftChildValue] ?? {}).map((key) => (_jsx(CheckboxComponent, { label: key, isChecked: uniqueValues[table][leftChildValue][key], onChange: (event) => {
1550
- const newValues = deepCopy(uniqueValues);
1551
- newValues[table][leftChildValue][key] =
1552
- event.target.checked;
1553
- setUniqueValues(newValues);
1554
- if (event.target.checked) {
1555
- handleInsertVariant(keyPrefix + 'right.' + 'value', key);
1556
- }
1557
- else {
1558
- handleDeleteVariant(keyPrefix + 'right.' + 'value', key);
1559
- }
1560
- } }))) }, keyPrefix + 'right.'))] }));
1561
- }
1562
- else {
1563
- const columnName = node.left.column;
1564
- const column = schema
1565
- .find((tableInfo) => tableInfo.name === currentTable)
1566
- ?.columns.find((col) => col.name === columnName);
1567
- const columnType = column?.fieldType;
1568
- return (_jsxs("div", { style: {
1569
- display: 'flex',
1570
- gap: 12,
1571
- justifyContent: 'space-between',
1572
- flexDirection: showNodeAsRow(node, formData) ? 'row' : 'column',
1573
- width: '100%',
1574
- }, children: [node.left && renderNode(node.left, keyPrefix + 'left.'), _jsx(SelectComponent, { value: node.operator, onChange: (event) => {
1575
- handleOperatorChange(event.target.value, node, keyPrefix);
1576
- }, options: [
1577
- // { label: `and`, value: "AND" },
1578
- // { label: `or`, value: "OR" },
1579
- ...(isNumericColumnType(columnType)
1580
- ? [
1581
- { label: 'equal to', value: '=' },
1582
- { label: 'not equal to', value: '!=' },
1583
- { label: 'greater than', value: '>' },
1584
- { label: 'less than', value: '<' },
1585
- { label: 'greater than or equal to', value: '>=' },
1586
- { label: 'less than or equal to', value: '<=' },
1587
- { label: 'is not null', value: 'IS NOT' },
1588
- { label: 'is null', value: 'IS' },
1589
- ]
1590
- : []),
1591
- ...(isTextColumnType(columnType)
1592
- ? [
1593
- { label: 'is exactly', value: 'LIKE' },
1594
- { label: 'is not exactly', value: 'NOT LIKE' },
1595
- { label: 'is', value: 'IN' },
1596
- { label: 'is not', value: 'NOT IN' },
1597
- { label: 'is not null', value: 'IS NOT' },
1598
- { label: 'is null', value: 'IS' },
1599
- ]
1600
- : []),
1601
- ...(isDateishColumnType(columnType)
1602
- ? [
1603
- { label: 'in the last', value: 'IN_THE_LAST' },
1604
- { label: 'in the previous', value: 'IN_THE_PREVIOUS' },
1605
- { label: 'in the current', value: 'IN_THE_CURRENT' },
1606
- { label: 'equals', value: 'EQUALS' },
1607
- { label: 'is not null', value: 'IS NOT' },
1608
- { label: 'is null', value: 'IS' },
1609
- ]
1610
- : []),
1611
- // { label: `minus`, value: "-" },
1612
- // { label: `plus`, value: "+" },
1613
- ], width: 200 }), node.right && renderNode(node.right, keyPrefix + 'right.')] }, keyPrefix));
1614
- }
1615
- case 'column_ref': {
1616
- const options = getAllPossibleColumns().map((column) => ({
1617
- label: snakeAndCamelCaseToTitleCase(column.displayName),
1618
- value: column.name,
1619
- }));
1620
- return (_jsx(SelectComponent, { value: node.column ?? options[0]?.value, onChange: (event) => {
1621
- handleChange([
1622
- { value: event.target.value, path: keyPrefix + 'column' },
1623
- ]);
1624
- }, options: options, width: 200 }));
1625
- }
1626
- case 'expr_list': {
1627
- const len = node.value.length;
1628
- return (_jsxs("div", { style: { display: 'flex', flexDirection: 'row', gap: 12 }, children: [node.value.map((elem, index) => {
1629
- if (elem.value) {
1630
- return (_jsx(TextInputComponent, { id: `expr_list_${index}`, width: 200, value: elem.value, onChange: (e) => handleChange([
1631
- {
1632
- value: e.target.value,
1633
- path: keyPrefix + `value.${index}.`,
1634
- },
1635
- ]) }, `input_${index}`));
1636
- }
1637
- return renderNode(elem, keyPrefix + `value.${index}.`);
1638
- }), len > 1 && (_jsx(SecondaryButtonComponent, { label: '-', onClick: () => handleDeleteVariant(keyPrefix + 'value') })), _jsx(SecondaryButtonComponent, { onClick: () => handleInsertVariant(keyPrefix + 'value'), label: '+' })] }, keyPrefix));
1639
- }
1640
- case 'double_quote_string':
1641
- case 'single_quote_string':
1642
- return (_jsx(TextInputComponent, { id: 'quoted_string', value: node.value.replaceAll('%', ''), width: 120, onChange: (e) => handleChange([
1643
- {
1644
- value: e.target.value,
1645
- path: keyPrefix + 'value',
1646
- },
1647
- ]) }));
1648
- case 'null':
1649
- return _jsx("div", {});
1650
- case 'number':
1651
- return (_jsx(TextInputComponent, { id: "quill_number_input", value: node.value, width: 120, onChange: (e) => {
1652
- handleChange([
1653
- {
1654
- value: e.target.value,
1655
- path: keyPrefix + 'value',
1656
- },
1657
- ]);
1658
- } }));
1659
- case 'bool':
1660
- return (_jsx(SelectComponent, { value: node.value.toString(), onChange: (event) => {
1661
- let formatted = true;
1662
- if (event.target.value === 'false') {
1663
- formatted = false;
1664
- }
1665
- handleChange([
1666
- {
1667
- value: formatted,
1668
- path: keyPrefix + 'value',
1669
- },
1670
- ]);
1671
- }, options: [
1672
- { label: 'is true', value: 'true' },
1673
- { label: 'is false', value: 'false' },
1674
- ], width: 200 }));
1675
- case 'function':
1676
- if (!node.args) {
1677
- return _jsx("label", {});
1678
- }
1679
- else if (node.args.type === 'expr_list' &&
1680
- node.args.value.length === 1) {
1681
- return (_jsx("div", { style: { display: 'flex', flexDirection: 'row' }, children: node.args.value[0] &&
1682
- renderNode(node.args.value[0], keyPrefix + 'args.value.0.') }));
1683
- }
1684
- else if (node.args.type === 'expr_list' &&
1685
- node.args.value.length === 2) {
1686
- return (_jsxs("div", { style: { display: 'flex', flexDirection: 'row', gap: 20 }, children: [node.args.value[0] &&
1687
- renderNode(node.args.value[0], keyPrefix + 'args.value.0.'), node.args.value[1] &&
1688
- renderNode(node.args.value[1], keyPrefix + 'args.value.1.')] }));
1689
- }
1690
- return node.name;
1691
- case 'interval':
1692
- return (_jsx("div", { style: { display: 'flex', flexDirection: 'row', gap: 20 }, children: renderNode(node.expr, keyPrefix + 'expr.') }));
1693
- default:
1694
- return null;
1695
- }
1696
- };
1697
- const isValidPivot = (fields) => {
1698
- let validPivot = true;
1699
- if (pivot.rowField &&
1700
- !fields.find((field) => field.name === pivot.rowField)) {
1701
- validPivot = false;
1702
- }
1703
- if (pivot.valueField &&
1704
- !fields.find((field) => field.name === pivot.valueField)) {
1705
- validPivot = false;
1706
- }
1707
- if (pivot.columnField &&
1708
- !fields.find((field) => field.name === pivot.columnField)) {
1709
- validPivot = false;
1710
- }
1711
- return validPivot;
1712
- };
1713
759
  /**
1714
760
  * @param filterTree
1715
761
  * Returns a list of filters to be displayed
@@ -1805,7 +851,7 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
1805
851
  ...defaultAST,
1806
852
  ...baseAst,
1807
853
  ...(!baseAst?.columns && {
1808
- columns: getAllPossibleColumns().map((c) => {
854
+ columns: getAllPossibleColumns(baseAst, schema).map((c) => {
1809
855
  const newColumn = deepCopy(defaultColumn);
1810
856
  newColumn.expr.column = c.name;
1811
857
  return newColumn;
@@ -1832,7 +878,7 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
1832
878
  ...defaultAST,
1833
879
  ...baseAst,
1834
880
  ...(!baseAst?.columns && {
1835
- columns: getAllPossibleColumns().map((c) => {
881
+ columns: getAllPossibleColumns(baseAst, schema).map((c) => {
1836
882
  const newColumn = deepCopy(defaultColumn);
1837
883
  newColumn.expr.column = c.name;
1838
884
  return newColumn;
@@ -1867,7 +913,7 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
1867
913
  ...defaultAST,
1868
914
  ...baseAst,
1869
915
  ...(!baseAst?.columns && {
1870
- columns: getAllPossibleColumns().map((c) => {
916
+ columns: getAllPossibleColumns(baseAst, schema).map((c) => {
1871
917
  const newColumn = deepCopy(defaultColumn);
1872
918
  newColumn.expr.column = c.name;
1873
919
  return newColumn;
@@ -1885,38 +931,6 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
1885
931
  }
1886
932
  }) }));
1887
933
  };
1888
- const getAllPossibleColumns = () => {
1889
- if (!baseAst || !baseAst.from) {
1890
- return schema.flatMap((table) => table.columns.map((c) => ({
1891
- ...c,
1892
- table: table.displayName,
1893
- })));
1894
- }
1895
- // TODO: support infinitely nested FROM table lookups.
1896
- // This currently only supports top-level table names in the FROM section
1897
- // of queries (eg. FROM "table_name", not "FROM (SELECT * FROM other) AS table_name")
1898
- const tableNamesInQuery = baseAst.from.map((tbl) => tbl.table);
1899
- return schema
1900
- .filter((t) => tableNamesInQuery.includes(t.displayName))
1901
- .flatMap((table) => table.columns
1902
- .map((c) => ({
1903
- ...c,
1904
- table: table.displayName,
1905
- }))
1906
- .sort((a, b) => {
1907
- const aIsId = a.name.toLowerCase() === 'id' ||
1908
- a.name.toLowerCase().endsWith('_id') ||
1909
- a.name.endsWith('Id');
1910
- const bIsId = b.name.toLowerCase() === 'id' ||
1911
- b.name.toLowerCase().endsWith('_id') ||
1912
- b.name.endsWith('Id');
1913
- if (aIsId && !bIsId)
1914
- return 1;
1915
- if (bIsId && !aIsId)
1916
- return -1;
1917
- return 0;
1918
- }));
1919
- };
1920
934
  /**
1921
935
  * Return whether all columns have been selected (used to hide select all
1922
936
  * and show clear button).
@@ -1940,497 +954,81 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
1940
954
  },
1941
955
  as: null,
1942
956
  });
1943
- const AddConditionPopover = ({ onSave }) => {
1944
- return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx("h1", { style: {
1945
- fontWeight: '600',
1946
- fontSize: 18,
1947
- margin: 0,
1948
- textAlign: 'left',
1949
- }, children: "Add condition" }), _jsx(TabsComponent, { value: topLevelBinaryOperator, options: DEFAULT_TAB_OPTIONS, onChange: (event) => setTopLevelBinaryOperator(event.target.value) }), activeEditItem && renderNode(activeEditItem), _jsx("div", { style: {
1950
- display: 'flex',
1951
- flexDirection: 'row',
1952
- gap: 8,
1953
- justifyContent: 'end',
1954
- }, children: _jsx(ButtonComponent, { onClick: onSave, label: 'Add condition' }) })] }));
1955
- };
1956
- const fetchUponChange = async (baseAst, newFormData) => {
1957
- // if newFormData is null still use it
957
+ const fetchReportFromASTHelper = async (baseAst, newFormData, curPivot, curSchema, previousReport) => {
1958
958
  const curFormData = newFormData !== undefined ? newFormData : formData;
1959
- let rows;
1960
- if ((curFormData || baseAst) && !loading) {
1961
- try {
1962
- setLoading(true);
1963
- const hostedBody = {
1964
- metadata: {
1965
- clientId: client.publicKey,
1966
- ast: { ...baseAst, where: curFormData },
1967
- publicKey: client.publicKey,
1968
- orgId: client.customerId,
1969
- task: 'patterns',
1970
- getCustomFields: false,
1971
- customFields,
1972
- additionalProcessing: { page: { currentPage: 0, rowsPerPage: 20 } },
1973
- useUpdatedDataGathering: true,
1974
- useNewNodeSql: true, // new flag
1975
- },
1976
- };
1977
- const tables = getTableNames(baseAst);
1978
- const table = tables.length >= 1 ? tables[0] : initialTableName;
1979
- let newUniqueValues = uniqueValues;
1980
- let dateRangesTemp = dateRanges;
1981
- let curReport = tempReport;
1982
- if ((newUniqueValues && Object.keys(newUniqueValues).length === 0) ||
1983
- table !== currentTable) {
1984
- const tableInfo = schema.find((tableInfo) => tableInfo.name === table);
1985
- if (tableInfo) {
1986
- newUniqueValues = await getUniqueStringValues(tableInfo.columns, table);
1987
- if (hashCode(uniqueValues) !== hashCode(newUniqueValues)) {
1988
- setUniqueValues(newUniqueValues);
1989
- }
1990
- dateRangesTemp = await getDateRanges(tableInfo.columns, table);
1991
- setDateRanges(dateRangesTemp || {});
1992
- }
1993
- setCurrentTable(table);
1994
- }
1995
- const cloudBody = {};
1996
- const data2 = await getData(client, 'dashquery', 'same-origin', hostedBody, cloudBody);
1997
- if (data2.success === false) {
1998
- throw new Error(data2.errorMessage);
1999
- }
2000
- if (client.databaseType &&
2001
- client.databaseType.toLowerCase() === 'bigquery') {
2002
- parseValueFromBigQueryDates(data2.rows, columns);
2003
- }
2004
- rows = data2.rows;
2005
- if (data2.rowCount) {
2006
- setNumberOfRows(data2.rowCount);
2007
- }
2008
- if (data2.rows && data2.rows.length) {
2009
- if (pivot) {
2010
- // check if any of the pivot fields aren't in the data2.fields array
2011
- if (!isValidPivot(data2.fields)) {
2012
- const processedFields = data2.fields.map((elem) => convertPostgresColumn(elem));
2013
- setPivot(null);
2014
- setPivotData(null);
2015
- setRows(data2.rows);
2016
- setColumns(processedFields);
2017
- if (data2.rowCount) {
2018
- const processedFormData = report
2019
- ? report
2020
- : createInitialFormData(processedFields);
2021
- setNumberOfRows(data2.rowCount);
2022
- curReport = {
2023
- ...formData,
2024
- ...processedFormData,
2025
- itemQuery: data2.itemQuery,
2026
- rowCount: data2.rowCount,
2027
- filtersApplied: [],
2028
- rows: data2.rows,
2029
- columns: processedFields,
2030
- };
2031
- setTempReport(curReport);
2032
- }
2033
- const formattedRows = formatRows(data2.rows, processedFields, false);
2034
- setFormattedRows(formattedRows);
2035
- return;
2036
- }
2037
- curReport = {
2038
- ...formData,
2039
- itemQuery: data2.itemQuery,
2040
- rowCount: data2.rowCount,
2041
- filtersApplied: [],
2042
- rows: data2.rows,
2043
- };
2044
- // Do all of this to make sure we have the right unique columns when applying a pivot
2045
- let dateBucket = undefined;
2046
- const tempDateRange = dateRangesTemp &&
2047
- pivot.rowField &&
2048
- dateRangesTemp[pivot.rowField];
2049
- if (tempDateRange) {
2050
- dateBucket = getDateBucketFromRange(tempDateRange.dateRange);
2051
- }
2052
- let distinctValuesForQuery = {};
2053
- if (pivot.columnField) {
2054
- const sqlQuery = await fetchSqlQuery({ ...baseAst, where: curFormData }, null, false);
2055
- distinctValuesForQuery = await getUniqueValuesByColumns([
2056
- {
2057
- field: pivot.columnField,
2058
- label: pivot.columnField,
2059
- format: 'string',
2060
- },
2061
- ], sqlQuery, [], client, customFields);
2062
- }
2063
- const pivotedData = await generatePivotTable(
2064
- // @ts-ignore
2065
- pivot, data2.rows, undefined, false, -1, undefined, dateBucket, curReport, client, distinctValuesForQuery ? distinctValuesForQuery : undefined);
2066
- console.info(`%c[Pivot]: ${JSON.stringify(pivot)}`, 'color: dimgray');
2067
- const processedFields = data2.fields.map((elem) => convertPostgresColumn(elem));
2068
- setPivotData(pivotedData);
2069
- setRows(data2.rows);
2070
- setColumns(processedFields);
2071
- if (data2.rowCount) {
2072
- const processedFormData = report
2073
- ? report
2074
- : createInitialFormData(processedFields);
2075
- setNumberOfRows(data2.rowCount);
2076
- setTempReport({
2077
- ...formData,
2078
- ...processedFormData,
2079
- itemQuery: data2.itemQuery,
2080
- rowCount: data2.rowCount,
2081
- filtersApplied: [],
2082
- rows: data2.rows,
2083
- columns: processedFields,
2084
- });
2085
- }
2086
- const formattedRows = formatRows(pivotedData.rows, processedFields, true, pivot.aggregationType);
2087
- setSelectedColumns(processedFields.map((column) => {
2088
- return `${table}.${column.field}`;
2089
- }));
2090
- setFormattedRows(formattedRows);
2091
- }
2092
- else {
2093
- const processedFields = data2.fields.map((elem) => convertPostgresColumn(elem));
2094
- setRows(data2.rows);
2095
- setColumns(processedFields);
2096
- if (data2.rowCount) {
2097
- const processedFormData = report
2098
- ? report
2099
- : createInitialFormData(processedFields);
2100
- setNumberOfRows(data2.rowCount);
2101
- setTempReport({
2102
- ...formData,
2103
- ...processedFormData,
2104
- itemQuery: data2.itemQuery,
2105
- rowCount: data2.rowCount,
2106
- filtersApplied: [],
2107
- rows: data2.rows,
2108
- columns: processedFields,
2109
- });
2110
- }
2111
- setSelectedColumns(processedFields.map((column) => {
2112
- return `${table}.${column.field}`;
2113
- }));
2114
- const formattedRows = formatRows(data2.rows, processedFields, false);
2115
- setFormattedRows(formattedRows);
2116
- if (data2.errorMessage) {
2117
- setErrorMessage(`Error: ${data2.errorMessage}`);
2118
- }
2119
- }
2120
- }
2121
- else {
2122
- setRows([]);
2123
- setColumns([]);
2124
- setFormattedRows([]);
2125
- setPivotData(null);
2126
- }
2127
- setLoading(false);
2128
- setDataDisplayed(true);
2129
- return rows;
959
+ let reportBuilderInfo = undefined;
960
+ try {
961
+ setLoading(true);
962
+ reportBuilderInfo = await fetchReportBuilderDataFromAST(baseAst, curFormData, curSchema ?? schema, client, curPivot ?? pivot, formData, currentTable, { uniqueStrings: uniqueValues, dateRanges: dateRanges ?? {} }, previousReport ?? reportInfo ?? undefined, customFields);
963
+ if (reportBuilderInfo.error) {
964
+ throw new Error(reportBuilderInfo.error);
2130
965
  }
2131
- catch (e) {
2132
- setErrorMessage(e.message);
966
+ }
967
+ catch (err) {
968
+ if (err instanceof Error) {
969
+ setErrorMessage(err.message);
2133
970
  setLoading(false);
2134
- setDataDisplayed(true);
2135
- setRows([]);
2136
- setColumns([]);
2137
- setFormattedRows([]);
2138
- setPivotData(null);
2139
- return { error: true, message: e.message };
971
+ return { error: true, message: err.message, rows: [] };
2140
972
  }
973
+ setLoading(false);
974
+ setErrorMessage('Failed to fetch');
975
+ return { error: true, message: 'Failed to fetch', rows: [] };
2141
976
  }
2142
- };
2143
- // Returns whether a where-clause contains a nested subquery.
2144
- const isSubquery = (node) => {
2145
- if (!node)
2146
- return false;
2147
- if (node.ast)
2148
- return true;
2149
- if (node.left && isSubquery(node.left))
2150
- return true;
2151
- if (node.right && isSubquery(node.right))
2152
- return true;
2153
- if (node.value && Array.isArray(node.value)) {
2154
- for (const value of node.value) {
2155
- if (isSubquery(value))
2156
- return true;
2157
- }
977
+ if (!reportBuilderInfo) {
978
+ setErrorMessage('Failed to fetch');
979
+ return;
2158
980
  }
2159
- return false;
981
+ const reportTable = reportBuilderInfo.table;
982
+ const reportBuilderInfoColumns = reportBuilderInfo.columns.map((column) => {
983
+ return `${reportTable}.${column.field}`;
984
+ });
985
+ setRows(reportBuilderInfo.rows);
986
+ setColumns(reportBuilderInfo.columns);
987
+ setNumberOfRows(reportBuilderInfo.rowCount);
988
+ setPivot(reportBuilderInfo.pivot);
989
+ setPivotData(reportBuilderInfo.pivotData);
990
+ setFormattedRows(reportBuilderInfo.formattedRows);
991
+ setTempReport(reportBuilderInfo.report);
992
+ setSelectedColumns(reportBuilderInfoColumns);
993
+ setActiveQuery(reportBuilderInfo.query);
994
+ setUniqueValues(reportBuilderInfo.uniqueValues);
995
+ setDateRanges(reportBuilderInfo.dateRanges);
996
+ setLoading(false);
997
+ setDataDisplayed(true);
998
+ setCurrentTable(reportBuilderInfo.table);
999
+ setFormData(curFormData);
1000
+ if (reportBuilderInfo.pivot) {
1001
+ setPivotRowField(reportBuilderInfo.pivot.rowField);
1002
+ setPivotAggregation(reportBuilderInfo.pivot.aggregationType);
1003
+ setPivotColumnField(reportBuilderInfo.pivot.columnField);
1004
+ setPivotValueField(reportBuilderInfo.pivot.valueField);
1005
+ }
1006
+ setReportInfo(reportBuilderInfo.report);
2160
1007
  };
2161
- const handleAsk = async (overridePrompt = '') => {
2162
- if (!aiPrompt && !overridePrompt) {
1008
+ const fetchAstFromPromptHelper = async (overridePrompt) => {
1009
+ let astInfo = {};
1010
+ const prompt = overridePrompt || aiPrompt;
1011
+ if (!prompt) {
1012
+ setErrorMessage('Please supply a prompt.');
2163
1013
  return;
2164
1014
  }
2165
1015
  try {
2166
1016
  setLoading(true);
2167
- setAskedAQuestion(true);
2168
- setErrorMessage('');
2169
- let res, data, ast;
2170
- let numRetries = 0;
2171
- const MAX_RETRIES = 3;
2172
- // refetch the request if it comes back and we know it's invalid.
2173
- // TODO: remove this to allow joins later down the road
2174
- let isTableJoin = !ast || !ast.from || ast.from.length !== 1;
2175
- while (isTableJoin || isSubquery(ast?.where)) {
2176
- if (numRetries === MAX_RETRIES)
2177
- break;
2178
- if (!activeQuery || (ast && (isTableJoin || isSubquery(ast?.where)))) {
2179
- res = await fetch(`${QUILL_SERVER}/magic`, {
2180
- method: 'POST',
2181
- headers: { 'Content-Type': 'application/json' },
2182
- body: JSON.stringify({
2183
- initialQuestion: aiPrompt || overridePrompt,
2184
- publicKey: client.publicKey,
2185
- useNewNodeSql: true, // new flag
2186
- }),
2187
- });
2188
- }
2189
- else {
2190
- res = await fetch(`${QUILL_SERVER}/magic/edit`, {
2191
- method: 'POST',
2192
- headers: { 'Content-Type': 'application/json' },
2193
- body: JSON.stringify({
2194
- sqlQuery: activeQuery,
2195
- initialQuestion: aiPrompt,
2196
- publicKey: client.publicKey,
2197
- useNewNodeSql: true, // new flag
2198
- }),
2199
- });
2200
- }
2201
- data = await res.json();
2202
- ast = data?.ast?.length ? data?.ast[0] : data?.ast;
2203
- // TODO: Debug invalid table joins in handleAsk
2204
- isTableJoin =
2205
- ast?.type !== 'bigquery' &&
2206
- (!ast || !ast.from || ast.from.length !== 1);
2207
- numRetries += 1;
2208
- }
2209
- if (numRetries === MAX_RETRIES) {
2210
- console.error('[Error]: Max retries exceeded.');
2211
- console.info(`%c[Prompt]: ${aiPrompt}`, 'color: dimgray');
2212
- setErrorMessage("Error: Couldn't process your request, please re-word your prompt.");
2213
- return;
2214
- }
2215
- let currentSchema = schema;
2216
- if (currentSchema && currentSchema.length === 0) {
2217
- currentSchema = await fetchSchema();
2218
- }
2219
- let newAst, groupByPivot;
2220
- if (ast) {
2221
- // Unwrap the ast object, supporting many possible types
2222
- ast = ast.length ? ast[0] : ast;
2223
- newAst = convertBigQuery(ast);
2224
- newAst = convertWildcardColumns(newAst, currentSchema); // must go before groupby
2225
- ({ ast: newAst, pivot: groupByPivot } = convertGroupBy(newAst, pivot, currentSchema));
2226
- newAst = convertStringComparison(newAst, client.databaseType);
2227
- newAst = convertRemoveSimpleParentheses(newAst);
2228
- const table = getTableNames(newAst)[0] ?? initialTableName;
2229
- const tableAlias = getTableAliases(newAst)[0] ?? initialTableName;
2230
- newAst = convertUnaryToBinary(newAst);
2231
- newAst = removeNonSelectedTableReferences(newAst, tableAlias ?? table, getAllPossibleColumns().map((col) => col.name));
2232
- const procesedColumns = deepCopy(newAst).columns?.map((column) => {
2233
- if (column.expr.type === 'column_ref') {
2234
- const columnName = extractColumnish(column.expr);
2235
- return `${table}.${columnName}`;
2236
- }
2237
- else if (column.as) {
2238
- return `${table}.${column.as}`;
2239
- }
2240
- return `${table}.${column.expr.value}`;
2241
- });
2242
- setSelectedColumns(procesedColumns);
2243
- if (groupByPivot) {
2244
- setBaseAst(deepCopy({ ...newAst, orderby: null, limit: null }));
2245
- newAst = deepCopy({ ...newAst, orderby: null, limit: null });
2246
- }
2247
- else {
2248
- setBaseAst(deepCopy({ ...newAst }));
2249
- }
2250
- setFormData(deepCopy(newAst.where));
2251
- setTopLevelBinaryOperator(
2252
- // @ts-ignore
2253
- newAst?.where ? newAst?.where?.operator : 'AND');
2254
- }
2255
- ast = newAst; // so we fetch data for newAst later.
2256
- fetchSqlQuery(ast, undefined, false);
2257
- const table = getTableNames(newAst)[0] ?? initialTableName;
2258
- const hostedBody = {
2259
- metadata: {
2260
- clientId: client.publicKey,
2261
- ast,
2262
- publicKey: client.publicKey,
2263
- orgId: client.customerId,
2264
- task: 'patterns',
2265
- additionalProcessing: { page: { currentPage: 0, rowsPerPage: 20 } },
2266
- useUpdatedDataGathering: true,
2267
- pivot: groupByPivot,
2268
- useNewNodeSql: true, // new flag
2269
- },
2270
- };
2271
- let currentUniqueValues = uniqueValues;
2272
- let dateRangesTemp = dateRanges;
2273
- if ((currentUniqueValues &&
2274
- currentUniqueValues[table] &&
2275
- Object.keys(currentUniqueValues[table]).length === 0) ||
2276
- table !== currentTable) {
2277
- const tableInfo = currentSchema.find((tableInfo) => tableInfo.name === table);
2278
- if (tableInfo) {
2279
- const newUniqueValues = await getUniqueStringValues(tableInfo.columns, table);
2280
- currentUniqueValues = newUniqueValues;
2281
- if (hashCode(uniqueValues) !== hashCode(newUniqueValues)) {
2282
- setUniqueValues(newUniqueValues);
2283
- }
2284
- dateRangesTemp = await getDateRanges(tableInfo.columns, table);
2285
- setDateRanges(dateRangesTemp);
2286
- }
2287
- setCurrentTable(table);
2288
- }
2289
- const cloudBody = {};
2290
- const data2 = await getData(client, 'patterns', 'same-origin', hostedBody, cloudBody);
2291
- if (!data2 || data2.status === 'error') {
2292
- throw new Error('Error querying data from patterns');
2293
- }
2294
- if (data2.rows && data2.rows.length) {
2295
- const processedFields = data2.fields
2296
- .map((elem) => convertPostgresColumn(elem))
2297
- .map((elem) => {
2298
- const tableInfo = currentSchema.find((t) => t.name === table);
2299
- const columnInfo = tableInfo?.columns.find((column) => column.name === elem.field);
2300
- return columnInfo
2301
- ? convertColumnInfoToColumnInternal(columnInfo)
2302
- : null;
2303
- })
2304
- .filter((elem) => elem);
2305
- let possiblePivot = true;
2306
- const possibleColumns = getPossiblePivotFieldOptions(processedFields, currentUniqueValues[table]);
2307
- if (groupByPivot &&
2308
- ((groupByPivot.columnField &&
2309
- !possibleColumns.columnFields.includes(groupByPivot?.columnField)) ||
2310
- (groupByPivot.rowField &&
2311
- !possibleColumns.rowFields.includes(groupByPivot?.rowField)) ||
2312
- (groupByPivot.valueField &&
2313
- !possibleColumns.valueFields.includes(groupByPivot?.valueField || '')))) {
2314
- possiblePivot = false;
2315
- let errorMessageEnding = '';
2316
- if (groupByPivot.columnField &&
2317
- !possibleColumns.columnFields.includes(groupByPivot?.columnField || '')) {
2318
- if (currentUniqueValues[table]?.[groupByPivot?.columnField || '']) {
2319
- errorMessageEnding = `The column ${groupByPivot?.columnField} has more than 24 unique values to pivot on.`;
2320
- }
2321
- else {
2322
- errorMessageEnding = `The column ${groupByPivot?.columnField} is not a proper column field.`;
2323
- }
2324
- }
2325
- else if (groupByPivot.rowField &&
2326
- !possibleColumns.rowFields.includes(groupByPivot?.rowField || '')) {
2327
- if (currentUniqueValues[table]?.[groupByPivot?.rowField || '']) {
2328
- errorMessageEnding = `The column ${groupByPivot?.rowField} has more than 36 unique values to pivot on.`;
2329
- }
2330
- else {
2331
- errorMessageEnding = `The column ${groupByPivot?.rowField} is not a proper row field.`;
2332
- }
2333
- }
2334
- else if (groupByPivot.valueField &&
2335
- !possibleColumns.valueFields.includes(groupByPivot?.valueField || '')) {
2336
- errorMessageEnding = `The column ${groupByPivot?.valueField} is not a proper value field.`;
2337
- }
2338
- setErrorMessage(`The requested pivot is not supported. ${errorMessageEnding}`);
2339
- }
2340
- if (groupByPivot && possiblePivot) {
2341
- let curReport = report ? report : undefined;
2342
- if (data2.rowCount) {
2343
- const processedFormData = report
2344
- ? report
2345
- : createInitialFormData(processedFields);
2346
- setNumberOfRows(data2.rowCount);
2347
- curReport = {
2348
- ...formData,
2349
- ...processedFormData,
2350
- itemQuery: data2.itemQuery,
2351
- rowCount: data2.rowCount,
2352
- filtersApplied: [],
2353
- rows: data2.rows,
2354
- columns: processedFields,
2355
- };
2356
- setTempReport(curReport || null);
2357
- }
2358
- let dateBucket = undefined;
2359
- const tempDateRange = dateRangesTemp &&
2360
- groupByPivot.rowField &&
2361
- dateRangesTemp[groupByPivot.rowField];
2362
- if (tempDateRange) {
2363
- dateBucket = getDateBucketFromRange(tempDateRange.dateRange);
2364
- }
2365
- const pivotedData = await generatePivotTable(
2366
- // @ts-ignore
2367
- groupByPivot, data2.rows, undefined, false, -1, undefined, dateBucket, curReport, client, groupByPivot.columnField
2368
- ? currentUniqueValues[groupByPivot.columnField]
2369
- : undefined);
2370
- console.info(`%c[Pivot]: ${JSON.stringify(groupByPivot)}`, 'color: dimgray');
2371
- setPivotData(pivotedData);
2372
- setPivot(groupByPivot);
2373
- if (client.databaseType &&
2374
- client.databaseType.toLowerCase() === 'bigquery') {
2375
- parseValueFromBigQueryDates(data2.rows, processedFields);
2376
- }
2377
- setRows(data2.rows);
2378
- setPivotRowField(groupByPivot?.rowField);
2379
- setPivotColumnField(groupByPivot?.columnField);
2380
- setPivotValueField(groupByPivot?.valueField);
2381
- setPivotAggregation(groupByPivot?.aggregationType);
2382
- setColumns(processedFields);
2383
- const formattedRows = formatRows(pivotedData.rows, processedFields, true, groupByPivot.aggregationType);
2384
- setFormattedRows(formattedRows);
2385
- }
2386
- else {
2387
- const processedFields = data2.fields.map((elem) => convertPostgresColumn(elem));
2388
- if (client.databaseType &&
2389
- client.databaseType.toLowerCase() === 'bigquery') {
2390
- parseValueFromBigQueryDates(data2.rows, processedFields);
2391
- }
2392
- setRows(data2.rows);
2393
- setColumns(processedFields);
2394
- if (data2.rowCount) {
2395
- setNumberOfRows(data2.rowCount);
2396
- setTempReport({
2397
- ...formData,
2398
- itemQuery: data2.itemQuery,
2399
- rowCount: data2.rowCount,
2400
- filtersApplied: [],
2401
- rows: data2.rows,
2402
- columns: processedFields,
2403
- });
2404
- }
2405
- const formattedRows = formatRows(data2.rows, processedFields, false);
2406
- setFormattedRows(formattedRows);
2407
- }
2408
- return data2.rows;
1017
+ astInfo = await fetchAndProcessASTFromPrompt(prompt, schema, client, pivot, activeQuery);
1018
+ if (astInfo.error) {
1019
+ throw new Error(astInfo.error);
2409
1020
  }
2410
- else {
2411
- setPivotData([]);
2412
- setRows([]);
2413
- setColumns([]);
2414
- setFormattedRows([]);
2415
- }
2416
- if (data2.query) {
2417
- setActiveQuery(data2.query);
2418
- }
2419
- else {
2420
- setActiveQuery('');
2421
- }
2422
- if (data2.errorMessage) {
2423
- setErrorMessage(`Error: Couldn't process your request, please re-word your prompt.`);
2424
- }
2425
- }
2426
- catch (e) {
2427
- console.error(e);
2428
- setErrorMessage(`Error: Couldn't process your request, please re-word your prompt.`);
2429
1021
  }
2430
- finally {
2431
- setLoading(false);
2432
- setDataDisplayed(true);
1022
+ catch (err) {
1023
+ if (err instanceof Error) {
1024
+ setErrorMessage(err.message);
1025
+ setLoading(false);
1026
+ }
1027
+ return;
2433
1028
  }
1029
+ setBaseAst(astInfo.ast);
1030
+ setFormData(astInfo.whereAst);
1031
+ await fetchReportFromASTHelper(astInfo.ast, astInfo.whereAST, astInfo.pivot);
2434
1032
  };
2435
1033
  const handleDeleteColumn = (name) => {
2436
1034
  if (!baseAst || !baseAst.columns.length || selectedColumns.length === 1) {
@@ -2622,46 +1220,7 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
2622
1220
  setIsPending(false);
2623
1221
  const item = filterToAst(filter, client.databaseType.toLowerCase());
2624
1222
  handleInsertion(item, 'AND', false);
2625
- }, onDeleteFilter: () => { }, ButtonComponent: ButtonComponent, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, SecondaryButtonComponent: SecondaryButtonComponent, MultiSelectComponent: MultiSelectComponent }) }) }), baseAst?.where &&
2626
- false && ( // temp removed the AddConditionPopover
2627
- _jsxs(_Fragment, { children: [_jsx(SecondaryButtonComponent, { onClick: () => {
2628
- if (!openPopover) {
2629
- setActiveEditItem(deepCopy(defaultEntry));
2630
- setOpenPopover('AddConditionPopover');
2631
- setActivePath('');
2632
- setIsPending(true);
2633
- }
2634
- }, label: "Add condition" }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddConditionPopover', setIsOpen: (isOpen) => {
2635
- if (!isOpen) {
2636
- setIsPending(false);
2637
- setTimeout(() => {
2638
- clearCheckboxes();
2639
- setActiveEditItem(null);
2640
- }, 300);
2641
- setActivePath(null);
2642
- setOpenPopover(null);
2643
- }
2644
- }, popoverTitle: "Add condition", popoverChildren: _jsx(AddConditionPopover, { onSave: () => {
2645
- if (isNodeEmptyCollection(activeEditItem)) {
2646
- setIsPending(false);
2647
- setTimeout(() => {
2648
- setActiveEditItem(null);
2649
- clearCheckboxes();
2650
- }, 300);
2651
- setActivePath(null);
2652
- setOpenPopover(null);
2653
- }
2654
- else {
2655
- setIsPending(false);
2656
- handleInsertion(activeEditItem, topLevelBinaryOperator, true);
2657
- setTimeout(() => {
2658
- setActiveEditItem(null);
2659
- clearCheckboxes();
2660
- }, 300);
2661
- setActivePath(null);
2662
- setOpenPopover(null);
2663
- }
2664
- } }) })] }))] })] }), _jsxs("div", { style: { width: '100%' }, children: [_jsx(SidebarHeadingComponent, { label: "Pivot" }), _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, CardComponent: CardComponent, SelectComponent: SelectComponent, ButtonComponent: ButtonComponent, PopoverComponent: PopoverComponent, TextComponent: TextComponent, ErrorMessageComponent: ErrorMessageComponent, PivotRowContainer: PivotRowContainer, PivotColumnContainer: PivotColumnContainer, LoadingComponent: LoadingComponent, isOpen: showPivotPopover, setIsOpen: setShowPivotPopover, showUpdatePivot: isEditingPivot, setShowUpdatePivot: setIsEditingPivot, parentRef: parentRef, data: rows, columns: columns, triggerButtonText: 'Add pivot', selectedPivotIndex: selectedPivotIndex, setSelectedPivotIndex: setSelectedPivotIndex, removePivot: () => {
1223
+ }, onDeleteFilter: () => { }, ButtonComponent: ButtonComponent, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, SecondaryButtonComponent: SecondaryButtonComponent, MultiSelectComponent: MultiSelectComponent }) }) })] })] }), _jsxs("div", { style: { width: '100%' }, children: [_jsx(SidebarHeadingComponent, { label: "Pivot" }), _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, CardComponent: CardComponent, SelectComponent: SelectComponent, ButtonComponent: ButtonComponent, PopoverComponent: PopoverComponent, TextComponent: TextComponent, ErrorMessageComponent: ErrorMessageComponent, PivotRowContainer: PivotRowContainer, PivotColumnContainer: PivotColumnContainer, LoadingComponent: LoadingComponent, isOpen: showPivotPopover, setIsOpen: setShowPivotPopover, showUpdatePivot: isEditingPivot, setShowUpdatePivot: setIsEditingPivot, parentRef: parentRef, data: rows, columns: columns, triggerButtonText: 'Add pivot', selectedPivotIndex: selectedPivotIndex, setSelectedPivotIndex: setSelectedPivotIndex, removePivot: () => {
2665
1224
  setPivot(null);
2666
1225
  setPivotData(null);
2667
1226
  const formattedRows = formatRows(rows, columns, false);
@@ -2670,7 +1229,7 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
2670
1229
  // TODOs
2671
1230
  selectPivot: () => {
2672
1231
  return;
2673
- }, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent: LabelComponent, HeaderComponent: HeaderComponent, dateRange: undefined, pivotCountRequest: 4, SecondaryButtonComponent: SecondaryButtonComponent, query: activeQuery, initialUniqueValues: uniqueValues[currentTable], disabled: !loading && (!baseAst || !dataDisplayed), pivotRecommendationsEnabled: pivotRecommendationsEnabled && overrideRecommendations, report: tempReport ?? report }), pivot && (_jsx(PivotForm, { columns: columns, uniqueValues: uniqueValues[currentTable], setPivotRowField: (value) => {
1232
+ }, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent: LabelComponent, HeaderComponent: HeaderComponent, dateRange: undefined, pivotCountRequest: 4, SecondaryButtonComponent: SecondaryButtonComponent, query: activeQuery, initialUniqueValues: uniqueValues[currentTable], disabled: !loading && (!baseAst || !dataDisplayed), pivotRecommendationsEnabled: pivotRecommendationsEnabled && overrideRecommendations, report: tempReport ?? reportInfo }), pivot && (_jsx(PivotForm, { columns: columns, uniqueValues: uniqueValues[currentTable], setPivotRowField: (value) => {
2674
1233
  setPivotRowField(value);
2675
1234
  }, setPivotColumnField: setPivotColumnField, setPivotValueField: setPivotValueField, setPivotAggregation: setPivotAggregation, pivotRowField: pivotRowField, pivotColumnField: pivotColumnField, pivotValueField: pivotValueField, pivotAggregation: pivotAggregation, onDelete: () => {
2676
1235
  setPivot(null);
@@ -2816,7 +1375,7 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
2816
1375
  display: 'flex',
2817
1376
  flexDirection: 'row',
2818
1377
  gap: '12px',
2819
- }, children: [_jsx("div", { style: { width: '100%' } }), !hideCopySQL && (_jsx(SecondaryButtonComponent, { onClick: () => copySQLToClipboard(), label: isCopying ? '✅ Copied' : 'Copy SQL' })), _jsx(ButtonComponent, { label: report ? 'Save changes' : 'Add to dashboard', onClick: () => { } })] }))] })] }), _jsx("style", { children: `body{margin:0;}` })] }));
1378
+ }, children: [_jsx("div", { style: { width: '100%' } }), !hideCopySQL && (_jsx(SecondaryButtonComponent, { onClick: () => copySQLToClipboard(), label: isCopying ? '✅ Copied' : 'Copy SQL' })), _jsx(ButtonComponent, { label: reportInfo ? 'Save changes' : 'Add to dashboard', onClick: () => { } })] }))] })] }), _jsx("style", { children: `body{margin:0;}` })] }));
2820
1379
  }
2821
1380
  return (_jsxs("div", { style: { backgroundColor: theme.backgroundColor, ...containerStyle }, className: className, children: [(!isChartBuilderHorizontalView ||
2822
1381
  (isChartBuilderHorizontalView && !isChartBuilderOpen)) && (_jsxs("div", { ref: parentRef, style: {
@@ -2903,47 +1462,7 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
2903
1462
  setIsPending(false);
2904
1463
  const item = filterToAst(filter, client.databaseType.toLowerCase());
2905
1464
  handleInsertion(item, 'AND', false);
2906
- }, onDeleteFilter: () => { }, ButtonComponent: ButtonComponent, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, MultiSelectComponent: MultiSelectComponent }) }) }), baseAst?.where &&
2907
- false && ( // temp removed the AddConditionPopover
2908
- _jsxs(_Fragment, { children: [_jsx(SecondaryButtonComponent, { onClick: () => {
2909
- if (!openPopover) {
2910
- setActiveEditItem(deepCopy(defaultEntry));
2911
- setOpenPopover('AddConditionPopover');
2912
- setActivePath('');
2913
- setIsPending(true);
2914
- }
2915
- }, label: 'Add condition' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddConditionPopover', setIsOpen: (isOpen) => {
2916
- if (!isOpen) {
2917
- // delay onClose callback so onClick no-ops
2918
- setTimeout(() => {
2919
- setIsPending(false);
2920
- setActiveEditItem(null);
2921
- setActivePath(null);
2922
- setOpenPopover(null);
2923
- clearCheckboxes();
2924
- }, 200);
2925
- }
2926
- }, popoverChildren: _jsx(AddConditionPopover, { onSave: () => {
2927
- if (isNodeEmptyCollection(activeEditItem)) {
2928
- setIsPending(false);
2929
- setTimeout(() => {
2930
- setActiveEditItem(null);
2931
- }, 300);
2932
- setActivePath(null);
2933
- setOpenPopover(null);
2934
- clearCheckboxes();
2935
- }
2936
- else {
2937
- setIsPending(false);
2938
- handleInsertion(activeEditItem, topLevelBinaryOperator, true);
2939
- setTimeout(() => {
2940
- setActiveEditItem(null);
2941
- }, 300);
2942
- setActivePath(null);
2943
- setOpenPopover(null);
2944
- clearCheckboxes();
2945
- }
2946
- } }) })] }))] })] }), _jsxs("div", { style: { width: '100%' }, children: [_jsx(SidebarHeadingComponent, { label: "Pivot" }), _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: SelectComponent, ButtonComponent: ButtonComponent, CardComponent: CardComponent, SecondaryButtonComponent: SecondaryButtonComponent, PopoverComponent: PopoverComponent, TextComponent: TextComponent, ErrorMessageComponent: ErrorMessageComponent, PivotRowContainer: PivotRowContainer, PivotColumnContainer: PivotColumnContainer, LoadingComponent: LoadingComponent, isOpen: showPivotPopover, setIsOpen: setShowPivotPopover, showUpdatePivot: isEditingPivot, setShowUpdatePivot: setIsEditingPivot, parentRef: parentRef, data: rows, columns: columns, triggerButtonText: 'Add pivot', selectedPivotIndex: selectedPivotIndex, setSelectedPivotIndex: setSelectedPivotIndex, removePivot: () => {
1465
+ }, onDeleteFilter: () => { }, ButtonComponent: ButtonComponent, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, MultiSelectComponent: MultiSelectComponent }) }) })] })] }), _jsxs("div", { style: { width: '100%' }, children: [_jsx(SidebarHeadingComponent, { label: "Pivot" }), _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: SelectComponent, ButtonComponent: ButtonComponent, CardComponent: CardComponent, SecondaryButtonComponent: SecondaryButtonComponent, PopoverComponent: PopoverComponent, TextComponent: TextComponent, ErrorMessageComponent: ErrorMessageComponent, PivotRowContainer: PivotRowContainer, PivotColumnContainer: PivotColumnContainer, LoadingComponent: LoadingComponent, isOpen: showPivotPopover, setIsOpen: setShowPivotPopover, showUpdatePivot: isEditingPivot, setShowUpdatePivot: setIsEditingPivot, parentRef: parentRef, data: rows, columns: columns, triggerButtonText: 'Add pivot', selectedPivotIndex: selectedPivotIndex, setSelectedPivotIndex: setSelectedPivotIndex, removePivot: () => {
2947
1466
  setPivot(null);
2948
1467
  setPivotData(null);
2949
1468
  const formattedRows = formatRows(rows, columns, false);
@@ -3238,7 +1757,9 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
3238
1757
  ? askAIInputWidth
3239
1758
  : askAILoadingContainerWidth, onChange: (e) => setAiPrompt(e.target.value), placeholder: askedAQuestion
3240
1759
  ? 'Ask a follow-up question...'
3241
- : 'Ask a question...' }), _jsx(ButtonComponent, { onClick: handleAsk, label: 'Ask AI' }), ((baseAst && dataDisplayed) || initialLoad) && (_jsx(SecondaryButtonComponent, { label: 'New report', onClick: clearAllState }))] }) })), baseAst && (_jsx(TableComponent, { isLoading: tableLoading ||
1760
+ : 'Ask a question...' }), _jsx(ButtonComponent, { onClick: () => {
1761
+ fetchAstFromPromptHelper();
1762
+ }, label: 'Ask AI' }), ((baseAst && dataDisplayed) || initialLoad) && (_jsx(SecondaryButtonComponent, { label: 'New report', onClick: clearAllState }))] }) })), baseAst && (_jsx(TableComponent, { isLoading: tableLoading ||
3242
1763
  (loading && errorMessage.length === 0) ||
3243
1764
  initialChartLoad, rows: formattedRows, rowCount: pivot ? undefined : numberOfRows, columns: pivot
3244
1765
  ? pivotData?.columns || emptyPivotColumns()
@@ -3259,15 +1780,17 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
3259
1780
  width: '100%',
3260
1781
  gap: 12,
3261
1782
  alignItems: 'center',
3262
- }, children: [_jsx(ErrorMessageComponent, { errorMessage: errorMessage }), _jsx(SecondaryButtonComponent, { onClick: handleAsk, label: 'Retry' })] })) : (_jsx("div", { style: { width: '100%' } })), baseAst && dataDisplayed && !initialChartLoad && (_jsxs(_Fragment, { children: [!hideCopySQL && (_jsx(SecondaryButtonComponent, { label: isCopying ? '✅ Copied' : 'Copy SQL', onClick: () => copySQLToClipboard() })), _jsx(ButtonComponent, { onClick: () => {
1783
+ }, children: [_jsx(ErrorMessageComponent, { errorMessage: errorMessage }), _jsx(SecondaryButtonComponent, { onClick: () => {
1784
+ fetchAstFromPromptHelper();
1785
+ }, label: 'Retry' })] })) : (_jsx("div", { style: { width: '100%' } })), baseAst && dataDisplayed && !initialChartLoad && (_jsxs(_Fragment, { children: [!hideCopySQL && (_jsx(SecondaryButtonComponent, { label: isCopying ? '✅ Copied' : 'Copy SQL', onClick: () => copySQLToClipboard() })), _jsx(ButtonComponent, { onClick: () => {
3263
1786
  setIsChartBuilderOpen(true);
3264
- }, disabled: !!errorMessage, label: report ? 'Save changes' : 'Add to dashboard' })] }))] })] }), _jsx("style", { children: `body{margin:0;}` })] })), (!isChartBuilderHorizontalView || isChartBuilderOpen) && (_jsx(ChartBuilderWithModal, { report: report
1787
+ }, disabled: !!errorMessage, label: reportInfo ? 'Save changes' : 'Add to dashboard' })] }))] })] }), _jsx("style", { children: `body{margin:0;}` })] })), (!isChartBuilderHorizontalView || isChartBuilderOpen) && (_jsx(ChartBuilderWithModal, { hideDeleteButton: true, report: reportInfo
3265
1788
  ? {
3266
- ...report,
1789
+ ...reportInfo,
3267
1790
  ...tempReport,
3268
1791
  pivot: pivot,
3269
- yAxisFields: report.pivot && !pivot ? [] : report.yAxisFields,
3270
- columns: report.columns.filter((col) => {
1792
+ yAxisFields: reportInfo.pivot && !pivot ? [] : reportInfo.yAxisFields,
1793
+ columns: reportInfo.columns.filter((col) => {
3271
1794
  return columns.find((c) => {
3272
1795
  return col.field === c.field;
3273
1796
  });
@@ -3275,5 +1798,5 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
3275
1798
  queryString: activeQuery,
3276
1799
  rows: rows,
3277
1800
  }
3278
- : tempReport, rows: rows, columns: columns, pivot: pivot, query: activeQuery, showTableFormatOptions: showChartBuilderTableFormatOptions, showDateFieldOptions: isAdminEnabled, showAccessControlOptions: isAdminEnabled, title: report ? 'Save changes' : 'Add to dashboard', isHorizontalView: true, isOpen: isChartBuilderOpen, setIsOpen: setIsChartBuilderOpen, onAddToDashboardComplete: report ? onSubmitEditReport : onSubmitCreateReport, destinationDashboard: destinationDashboard, organizationName: organizationName, pivotData: pivotData, initialUniqueValues: uniqueValues[currentTable], pivotRecommendationsEnabled: pivotRecommendationsEnabled && overrideRecommendations, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, HeaderComponent: HeaderComponent, SubHeaderComponent: SubHeaderComponent, LabelComponent: LabelComponent, TextComponent: TextComponent, CardComponent: CardComponent, ModalComponent: ChartBuilderModalComponent, PopoverComponent: PopoverComponent, TableComponent: TableComponent, DeleteButtonComponent: DeleteButtonComponent, LoadingComponent: LoadingComponent, ChartBuilderInputRowContainer: ChartBuilderInputRowContainer, ChartBuilderInputColumnContainer: ChartBuilderInputColumnContainer, FormContainer: ChartBuilderFormContainer, hideDateRangeFilter: true, buttonLabel: report ? 'Save changes' : 'Add to dashboard', onClickChartElement: onClickChartElement, rowCount: numberOfRows, onPageChange: onPageChange, onSortChange: onSortChange, isLoading: tableLoading }))] }));
1801
+ : tempReport, rows: rows, columns: columns, pivot: pivot, query: activeQuery, showTableFormatOptions: showChartBuilderTableFormatOptions, showDateFieldOptions: isAdminEnabled, showAccessControlOptions: isAdminEnabled, title: reportInfo ? 'Save changes' : 'Add to dashboard', isHorizontalView: true, isOpen: isChartBuilderOpen, setIsOpen: setIsChartBuilderOpen, onAddToDashboardComplete: reportInfo ? onSubmitEditReport : onSubmitCreateReport, destinationDashboard: destinationDashboard, organizationName: organizationName, pivotData: pivotData, initialUniqueValues: uniqueValues[currentTable], pivotRecommendationsEnabled: pivotRecommendationsEnabled && overrideRecommendations, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, HeaderComponent: HeaderComponent, SubHeaderComponent: SubHeaderComponent, LabelComponent: LabelComponent, TextComponent: TextComponent, CardComponent: CardComponent, ModalComponent: ChartBuilderModalComponent, PopoverComponent: PopoverComponent, TableComponent: TableComponent, DeleteButtonComponent: DeleteButtonComponent, LoadingComponent: LoadingComponent, ChartBuilderInputRowContainer: ChartBuilderInputRowContainer, ChartBuilderInputColumnContainer: ChartBuilderInputColumnContainer, FormContainer: ChartBuilderFormContainer, hideDateRangeFilter: true, buttonLabel: reportInfo ? 'Save changes' : 'Add to dashboard', onClickChartElement: onClickChartElement, rowCount: numberOfRows, onPageChange: onPageChange, onSortChange: onSortChange, isLoading: tableLoading }))] }));
3279
1802
  }