@quillsql/react 2.13.43 → 2.13.44

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 (249) hide show
  1. package/dist/cjs/Chart.d.ts.map +1 -1
  2. package/dist/cjs/Chart.js +2 -2
  3. package/dist/cjs/ChartBuilder.d.ts +1 -0
  4. package/dist/cjs/ChartBuilder.d.ts.map +1 -1
  5. package/dist/cjs/ChartBuilder.js +48 -14
  6. package/dist/cjs/ChartEditor.d.ts +1 -1
  7. package/dist/cjs/ChartEditor.d.ts.map +1 -1
  8. package/dist/cjs/ChartEditor.js +2 -2
  9. package/dist/cjs/Context.d.ts.map +1 -1
  10. package/dist/cjs/Context.js +37 -26
  11. package/dist/cjs/Dashboard.d.ts +2 -2
  12. package/dist/cjs/Dashboard.d.ts.map +1 -1
  13. package/dist/cjs/Dashboard.js +115 -99
  14. package/dist/cjs/ReportBuilder.d.ts.map +1 -1
  15. package/dist/cjs/ReportBuilder.js +871 -1574
  16. package/dist/cjs/SQLEditor.d.ts.map +1 -1
  17. package/dist/cjs/SQLEditor.js +23 -4
  18. package/dist/cjs/Table.d.ts.map +1 -1
  19. package/dist/cjs/components/Chart/CustomReferenceLine.js +1 -1
  20. package/dist/cjs/components/Chart/GaugeChart.js +0 -6
  21. package/dist/cjs/components/Dashboard/DashboardFilter.d.ts.map +1 -1
  22. package/dist/cjs/components/Dashboard/DashboardFilter.js +3 -3
  23. package/dist/cjs/components/Dashboard/DashboardSection.d.ts +1 -1
  24. package/dist/cjs/components/Dashboard/DashboardSection.d.ts.map +1 -1
  25. package/dist/cjs/components/Dashboard/DashboardSection.js +20 -19
  26. package/dist/cjs/components/Dashboard/MetricComponent.d.ts.map +1 -1
  27. package/dist/cjs/components/Dashboard/MetricComponent.js +1 -0
  28. package/dist/cjs/components/Dashboard/TableComponent.d.ts.map +1 -1
  29. package/dist/cjs/components/Dashboard/TableComponent.js +5 -1
  30. package/dist/cjs/components/QuillMultiSelectWithCombo.d.ts.map +1 -1
  31. package/dist/cjs/components/QuillMultiSelectWithCombo.js +58 -8
  32. package/dist/cjs/components/QuillSelect.d.ts.map +1 -1
  33. package/dist/cjs/components/QuillSelect.js +91 -14
  34. package/dist/cjs/components/QuillSelectWithCombo.js +6 -6
  35. package/dist/cjs/components/ReportBuilder/AddColumnModal.d.ts +6 -16
  36. package/dist/cjs/components/ReportBuilder/AddColumnModal.d.ts.map +1 -1
  37. package/dist/cjs/components/ReportBuilder/AddColumnModal.js +172 -75
  38. package/dist/cjs/components/ReportBuilder/AddSortPopover.d.ts +1 -5
  39. package/dist/cjs/components/ReportBuilder/AddSortPopover.d.ts.map +1 -1
  40. package/dist/cjs/components/ReportBuilder/AddSortPopover.js +2 -9
  41. package/dist/cjs/components/ReportBuilder/DraggableColumns.d.ts +17 -0
  42. package/dist/cjs/components/ReportBuilder/DraggableColumns.d.ts.map +1 -0
  43. package/dist/cjs/components/ReportBuilder/DraggableColumns.js +52 -0
  44. package/dist/cjs/components/ReportBuilder/DraggableItem.d.ts +17 -0
  45. package/dist/cjs/components/ReportBuilder/DraggableItem.d.ts.map +1 -0
  46. package/dist/cjs/components/ReportBuilder/DraggableItem.js +17 -0
  47. package/dist/cjs/components/ReportBuilder/FilterModal.d.ts +6 -12
  48. package/dist/cjs/components/ReportBuilder/FilterModal.d.ts.map +1 -1
  49. package/dist/cjs/components/ReportBuilder/FilterModal.js +29 -20
  50. package/dist/cjs/components/ReportBuilder/FilterStack.d.ts +8 -17
  51. package/dist/cjs/components/ReportBuilder/FilterStack.d.ts.map +1 -1
  52. package/dist/cjs/components/ReportBuilder/FilterStack.js +20 -86
  53. package/dist/cjs/components/ReportBuilder/convert.js +6 -6
  54. package/dist/cjs/components/ReportBuilder/ui.d.ts +8 -9
  55. package/dist/cjs/components/ReportBuilder/ui.d.ts.map +1 -1
  56. package/dist/cjs/components/ReportBuilder/ui.js +30 -8
  57. package/dist/cjs/components/ReportBuilder/util.d.ts +2 -5
  58. package/dist/cjs/components/ReportBuilder/util.d.ts.map +1 -1
  59. package/dist/cjs/components/ReportBuilder/util.js +1 -1
  60. package/dist/cjs/components/UiComponents.d.ts +3 -2
  61. package/dist/cjs/components/UiComponents.d.ts.map +1 -1
  62. package/dist/cjs/components/UiComponents.js +13 -13
  63. package/dist/cjs/hooks/useAskQuill.d.ts +1 -1
  64. package/dist/cjs/hooks/useAskQuill.d.ts.map +1 -1
  65. package/dist/cjs/hooks/useAskQuill.js +14 -12
  66. package/dist/cjs/hooks/useDashboard.d.ts +5 -3
  67. package/dist/cjs/hooks/useDashboard.d.ts.map +1 -1
  68. package/dist/cjs/hooks/useDashboard.js +8 -6
  69. package/dist/cjs/hooks/useOnClickOutside.d.ts +1 -0
  70. package/dist/cjs/hooks/useOnClickOutside.d.ts.map +1 -1
  71. package/dist/cjs/hooks/useOnClickOutside.js +33 -0
  72. package/dist/cjs/internals/ReportBuilder/PivotForm.d.ts +2 -1
  73. package/dist/cjs/internals/ReportBuilder/PivotForm.d.ts.map +1 -1
  74. package/dist/cjs/internals/ReportBuilder/PivotForm.js +22 -15
  75. package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts +7 -5
  76. package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
  77. package/dist/cjs/internals/ReportBuilder/PivotModal.js +100 -48
  78. package/dist/cjs/models/Client.d.ts +4 -0
  79. package/dist/cjs/models/Client.d.ts.map +1 -1
  80. package/dist/cjs/models/Dashboard.d.ts +1 -0
  81. package/dist/cjs/models/Dashboard.d.ts.map +1 -1
  82. package/dist/cjs/models/Report.d.ts +2 -0
  83. package/dist/cjs/models/Report.d.ts.map +1 -1
  84. package/dist/cjs/models/ReportBuilder.d.ts +46 -0
  85. package/dist/cjs/models/ReportBuilder.d.ts.map +1 -0
  86. package/dist/cjs/models/ReportBuilder.js +19 -0
  87. package/dist/cjs/models/Tables.d.ts +5 -5
  88. package/dist/cjs/models/Tables.d.ts.map +1 -1
  89. package/dist/cjs/utils/astFilterProcessing.d.ts +4 -0
  90. package/dist/cjs/utils/astFilterProcessing.d.ts.map +1 -1
  91. package/dist/cjs/utils/astFilterProcessing.js +301 -97
  92. package/dist/cjs/utils/astProcessing.d.ts +14 -4
  93. package/dist/cjs/utils/astProcessing.d.ts.map +1 -1
  94. package/dist/cjs/utils/astProcessing.js +38 -4
  95. package/dist/cjs/utils/dashboard.d.ts.map +1 -1
  96. package/dist/cjs/utils/dashboard.js +18 -3
  97. package/dist/cjs/utils/dataFetcher.d.ts.map +1 -1
  98. package/dist/cjs/utils/dataFetcher.js +4 -3
  99. package/dist/cjs/utils/filterProcessing.d.ts +2 -11
  100. package/dist/cjs/utils/filterProcessing.d.ts.map +1 -1
  101. package/dist/cjs/utils/filterProcessing.js +4 -16
  102. package/dist/cjs/utils/pivotConstructor.d.ts +2 -1
  103. package/dist/cjs/utils/pivotConstructor.d.ts.map +1 -1
  104. package/dist/cjs/utils/pivotConstructor.js +4 -2
  105. package/dist/cjs/utils/pivotProcessing.d.ts +17 -7
  106. package/dist/cjs/utils/pivotProcessing.d.ts.map +1 -1
  107. package/dist/cjs/utils/pivotProcessing.js +60 -51
  108. package/dist/cjs/utils/queryConstructor.d.ts.map +1 -1
  109. package/dist/cjs/utils/queryConstructor.js +15 -2
  110. package/dist/cjs/utils/report.d.ts +12 -9
  111. package/dist/cjs/utils/report.d.ts.map +1 -1
  112. package/dist/cjs/utils/report.js +114 -47
  113. package/dist/cjs/utils/reportBuilder.d.ts +88 -0
  114. package/dist/cjs/utils/reportBuilder.d.ts.map +1 -0
  115. package/dist/cjs/utils/reportBuilder.js +395 -0
  116. package/dist/cjs/utils/schema.d.ts +7 -0
  117. package/dist/cjs/utils/schema.d.ts.map +1 -1
  118. package/dist/cjs/utils/schema.js +36 -2
  119. package/dist/cjs/utils/tableProcessing.d.ts +59 -29
  120. package/dist/cjs/utils/tableProcessing.d.ts.map +1 -1
  121. package/dist/cjs/utils/tableProcessing.js +75 -90
  122. package/dist/cjs/utils/ui.d.ts +2 -0
  123. package/dist/cjs/utils/ui.d.ts.map +1 -0
  124. package/dist/cjs/utils/ui.js +18 -0
  125. package/dist/esm/Chart.d.ts.map +1 -1
  126. package/dist/esm/Chart.js +2 -2
  127. package/dist/esm/ChartBuilder.d.ts +1 -0
  128. package/dist/esm/ChartBuilder.d.ts.map +1 -1
  129. package/dist/esm/ChartBuilder.js +49 -15
  130. package/dist/esm/ChartEditor.d.ts +1 -1
  131. package/dist/esm/ChartEditor.d.ts.map +1 -1
  132. package/dist/esm/ChartEditor.js +2 -2
  133. package/dist/esm/Context.d.ts.map +1 -1
  134. package/dist/esm/Context.js +37 -26
  135. package/dist/esm/Dashboard.d.ts +2 -2
  136. package/dist/esm/Dashboard.d.ts.map +1 -1
  137. package/dist/esm/Dashboard.js +119 -103
  138. package/dist/esm/ReportBuilder.d.ts.map +1 -1
  139. package/dist/esm/ReportBuilder.js +878 -1581
  140. package/dist/esm/SQLEditor.d.ts.map +1 -1
  141. package/dist/esm/SQLEditor.js +23 -4
  142. package/dist/esm/Table.d.ts.map +1 -1
  143. package/dist/esm/components/Chart/CustomReferenceLine.js +1 -1
  144. package/dist/esm/components/Chart/GaugeChart.js +0 -6
  145. package/dist/esm/components/Dashboard/DashboardFilter.d.ts.map +1 -1
  146. package/dist/esm/components/Dashboard/DashboardFilter.js +3 -3
  147. package/dist/esm/components/Dashboard/DashboardSection.d.ts +1 -1
  148. package/dist/esm/components/Dashboard/DashboardSection.d.ts.map +1 -1
  149. package/dist/esm/components/Dashboard/DashboardSection.js +21 -20
  150. package/dist/esm/components/Dashboard/MetricComponent.d.ts.map +1 -1
  151. package/dist/esm/components/Dashboard/MetricComponent.js +1 -0
  152. package/dist/esm/components/Dashboard/TableComponent.d.ts.map +1 -1
  153. package/dist/esm/components/Dashboard/TableComponent.js +5 -1
  154. package/dist/esm/components/QuillMultiSelectWithCombo.d.ts.map +1 -1
  155. package/dist/esm/components/QuillMultiSelectWithCombo.js +57 -7
  156. package/dist/esm/components/QuillSelect.d.ts.map +1 -1
  157. package/dist/esm/components/QuillSelect.js +58 -14
  158. package/dist/esm/components/QuillSelectWithCombo.js +6 -6
  159. package/dist/esm/components/ReportBuilder/AddColumnModal.d.ts +6 -16
  160. package/dist/esm/components/ReportBuilder/AddColumnModal.d.ts.map +1 -1
  161. package/dist/esm/components/ReportBuilder/AddColumnModal.js +173 -76
  162. package/dist/esm/components/ReportBuilder/AddSortPopover.d.ts +1 -5
  163. package/dist/esm/components/ReportBuilder/AddSortPopover.d.ts.map +1 -1
  164. package/dist/esm/components/ReportBuilder/AddSortPopover.js +2 -9
  165. package/dist/esm/components/ReportBuilder/DraggableColumns.d.ts +17 -0
  166. package/dist/esm/components/ReportBuilder/DraggableColumns.d.ts.map +1 -0
  167. package/dist/esm/components/ReportBuilder/DraggableColumns.js +46 -0
  168. package/dist/esm/components/ReportBuilder/DraggableItem.d.ts +17 -0
  169. package/dist/esm/components/ReportBuilder/DraggableItem.d.ts.map +1 -0
  170. package/dist/esm/components/ReportBuilder/DraggableItem.js +14 -0
  171. package/dist/esm/components/ReportBuilder/FilterModal.d.ts +6 -12
  172. package/dist/esm/components/ReportBuilder/FilterModal.d.ts.map +1 -1
  173. package/dist/esm/components/ReportBuilder/FilterModal.js +29 -20
  174. package/dist/esm/components/ReportBuilder/FilterStack.d.ts +8 -17
  175. package/dist/esm/components/ReportBuilder/FilterStack.d.ts.map +1 -1
  176. package/dist/esm/components/ReportBuilder/FilterStack.js +21 -87
  177. package/dist/esm/components/ReportBuilder/convert.js +6 -6
  178. package/dist/esm/components/ReportBuilder/ui.d.ts +8 -9
  179. package/dist/esm/components/ReportBuilder/ui.d.ts.map +1 -1
  180. package/dist/esm/components/ReportBuilder/ui.js +33 -11
  181. package/dist/esm/components/ReportBuilder/util.d.ts +2 -5
  182. package/dist/esm/components/ReportBuilder/util.d.ts.map +1 -1
  183. package/dist/esm/components/ReportBuilder/util.js +1 -1
  184. package/dist/esm/components/UiComponents.d.ts +3 -2
  185. package/dist/esm/components/UiComponents.d.ts.map +1 -1
  186. package/dist/esm/components/UiComponents.js +13 -13
  187. package/dist/esm/hooks/useAskQuill.d.ts +1 -1
  188. package/dist/esm/hooks/useAskQuill.d.ts.map +1 -1
  189. package/dist/esm/hooks/useAskQuill.js +14 -12
  190. package/dist/esm/hooks/useDashboard.d.ts +5 -3
  191. package/dist/esm/hooks/useDashboard.d.ts.map +1 -1
  192. package/dist/esm/hooks/useDashboard.js +8 -6
  193. package/dist/esm/hooks/useOnClickOutside.d.ts +1 -0
  194. package/dist/esm/hooks/useOnClickOutside.d.ts.map +1 -1
  195. package/dist/esm/hooks/useOnClickOutside.js +31 -0
  196. package/dist/esm/internals/ReportBuilder/PivotForm.d.ts +2 -1
  197. package/dist/esm/internals/ReportBuilder/PivotForm.d.ts.map +1 -1
  198. package/dist/esm/internals/ReportBuilder/PivotForm.js +23 -16
  199. package/dist/esm/internals/ReportBuilder/PivotModal.d.ts +7 -5
  200. package/dist/esm/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
  201. package/dist/esm/internals/ReportBuilder/PivotModal.js +101 -49
  202. package/dist/esm/models/Client.d.ts +4 -0
  203. package/dist/esm/models/Client.d.ts.map +1 -1
  204. package/dist/esm/models/Dashboard.d.ts +1 -0
  205. package/dist/esm/models/Dashboard.d.ts.map +1 -1
  206. package/dist/esm/models/Report.d.ts +2 -0
  207. package/dist/esm/models/Report.d.ts.map +1 -1
  208. package/dist/esm/models/ReportBuilder.d.ts +46 -0
  209. package/dist/esm/models/ReportBuilder.d.ts.map +1 -0
  210. package/dist/esm/models/ReportBuilder.js +16 -0
  211. package/dist/esm/models/Tables.d.ts +5 -5
  212. package/dist/esm/models/Tables.d.ts.map +1 -1
  213. package/dist/esm/utils/astFilterProcessing.d.ts +4 -0
  214. package/dist/esm/utils/astFilterProcessing.d.ts.map +1 -1
  215. package/dist/esm/utils/astFilterProcessing.js +300 -97
  216. package/dist/esm/utils/astProcessing.d.ts +14 -4
  217. package/dist/esm/utils/astProcessing.d.ts.map +1 -1
  218. package/dist/esm/utils/astProcessing.js +38 -5
  219. package/dist/esm/utils/dashboard.d.ts.map +1 -1
  220. package/dist/esm/utils/dashboard.js +18 -3
  221. package/dist/esm/utils/dataFetcher.d.ts.map +1 -1
  222. package/dist/esm/utils/dataFetcher.js +4 -3
  223. package/dist/esm/utils/filterProcessing.d.ts +2 -11
  224. package/dist/esm/utils/filterProcessing.d.ts.map +1 -1
  225. package/dist/esm/utils/filterProcessing.js +4 -15
  226. package/dist/esm/utils/pivotConstructor.d.ts +2 -1
  227. package/dist/esm/utils/pivotConstructor.d.ts.map +1 -1
  228. package/dist/esm/utils/pivotConstructor.js +4 -2
  229. package/dist/esm/utils/pivotProcessing.d.ts +17 -7
  230. package/dist/esm/utils/pivotProcessing.d.ts.map +1 -1
  231. package/dist/esm/utils/pivotProcessing.js +58 -49
  232. package/dist/esm/utils/queryConstructor.d.ts.map +1 -1
  233. package/dist/esm/utils/queryConstructor.js +15 -2
  234. package/dist/esm/utils/report.d.ts +12 -9
  235. package/dist/esm/utils/report.d.ts.map +1 -1
  236. package/dist/esm/utils/report.js +116 -46
  237. package/dist/esm/utils/reportBuilder.d.ts +88 -0
  238. package/dist/esm/utils/reportBuilder.d.ts.map +1 -0
  239. package/dist/esm/utils/reportBuilder.js +386 -0
  240. package/dist/esm/utils/schema.d.ts +7 -0
  241. package/dist/esm/utils/schema.d.ts.map +1 -1
  242. package/dist/esm/utils/schema.js +34 -1
  243. package/dist/esm/utils/tableProcessing.d.ts +59 -29
  244. package/dist/esm/utils/tableProcessing.d.ts.map +1 -1
  245. package/dist/esm/utils/tableProcessing.js +71 -86
  246. package/dist/esm/utils/ui.d.ts +2 -0
  247. package/dist/esm/utils/ui.d.ts.map +1 -0
  248. package/dist/esm/utils/ui.js +14 -0
  249. package/package.json +1 -1
@@ -7,18 +7,10 @@ exports.default = ReportBuilder;
7
7
  const jsx_runtime_1 = require("react/jsx-runtime");
8
8
  const react_1 = require("react");
9
9
  const UiComponents_1 = require("./components/UiComponents");
10
- const core_1 = require("@dnd-kit/core");
11
- const sortable_1 = require("@dnd-kit/sortable");
12
- const utilities_1 = require("@dnd-kit/utilities");
13
10
  const Context_1 = require("./Context");
14
- const ast_1 = require("./components/ReportBuilder/ast");
15
11
  const ChartBuilder_1 = require("./ChartBuilder");
16
12
  const UiComponents_2 = require("./components/UiComponents");
17
13
  const ui_1 = require("./components/ReportBuilder/ui");
18
- const util_1 = require("./components/ReportBuilder/util");
19
- const crypto_1 = require("./utils/crypto");
20
- const constants_1 = require("./components/ReportBuilder/constants");
21
- const AddColumnModal_1 = __importDefault(require("./components/ReportBuilder/AddColumnModal"));
22
14
  const AddSortPopover_1 = require("./components/ReportBuilder/AddSortPopover");
23
15
  const PivotModal_1 = require("./internals/ReportBuilder/PivotModal");
24
16
  const textProcessing_1 = require("./utils/textProcessing");
@@ -26,27 +18,25 @@ const AddLimitPopover_1 = require("./components/ReportBuilder/AddLimitPopover");
26
18
  const width_1 = require("./utils/width");
27
19
  const QuillSelect_1 = require("./components/QuillSelect");
28
20
  const QuillCard_1 = require("./components/QuillCard");
29
- const valueFormatter_1 = require("./utils/valueFormatter");
30
21
  const pivotProcessing_1 = require("./utils/pivotProcessing");
31
22
  const tableProcessing_1 = require("./utils/tableProcessing");
32
23
  const astProcessing_1 = require("./utils/astProcessing");
33
24
  const PivotForm_1 = __importDefault(require("./internals/ReportBuilder/PivotForm"));
34
- const dates_1 = require("./utils/dates");
35
25
  const FilterModal_1 = __importDefault(require("./components/ReportBuilder/FilterModal"));
36
- const astFilterProcessing_1 = require("./utils/astFilterProcessing");
37
- const useAstToFilterTree_1 = __importDefault(require("./hooks/useAstToFilterTree"));
38
- const filterProcessing_1 = require("./utils/filterProcessing");
39
26
  const QuillMultiSelectWithCombo_1 = require("./components/QuillMultiSelectWithCombo");
40
27
  const paginationProcessing_1 = require("./utils/paginationProcessing");
41
28
  const report_1 = require("./utils/report");
42
29
  const Report_1 = require("./models/Report");
43
- const fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
44
30
  const FilterStack_1 = __importDefault(require("./components/ReportBuilder/FilterStack"));
45
- const constants_2 = require("./utils/constants");
31
+ const constants_1 = require("./utils/constants");
46
32
  const convert_1 = require("./components/ReportBuilder/convert");
47
- const pivotConstructor_1 = require("./utils/pivotConstructor");
48
- const columnProcessing_1 = require("./utils/columnProcessing");
49
33
  const dashboard_1 = require("./utils/dashboard");
34
+ const useDashboard_1 = require("./hooks/useDashboard");
35
+ const ReportBuilder_1 = require("./models/ReportBuilder");
36
+ const DraggableColumns_1 = __importDefault(require("./components/ReportBuilder/DraggableColumns"));
37
+ const AddColumnModal_1 = __importDefault(require("./components/ReportBuilder/AddColumnModal"));
38
+ const reportBuilder_1 = require("./utils/reportBuilder");
39
+ const dataFetcher_1 = require("./utils/dataFetcher");
50
40
  /**
51
41
  * Quill Report Builder
52
42
  *
@@ -79,173 +69,369 @@ const dashboard_1 = require("./utils/dashboard");
79
69
  * @see https://docs.quillsql.com/components/report-builder
80
70
  */
81
71
  function ReportBuilder({ initialTableName = '', onSubmitEditReport = () => void null, onSubmitCreateReport = () => void null, onSubmitSaveQuery = () => void null, onDiscardChanges = undefined, onSaveChanges = undefined, onCloseChartBuilder = undefined, destinationDashboard, chartBuilderTitle = undefined, organizationName = '', ButtonComponent = UiComponents_1.MemoizedButton, SecondaryButtonComponent = UiComponents_1.MemoizedSecondaryButton, DeleteButtonComponent = UiComponents_1.MemoizedDeleteButton, ModalComponent = UiComponents_1.MemoizedModal, TextInputComponent = UiComponents_2.QuillTextInput, SelectComponent = QuillSelect_1.QuillSelectComponent, MultiSelectComponent = QuillMultiSelectWithCombo_1.QuillMultiSelectComponentWithCombo, TableComponent = UiComponents_1.QuillTableReportBuilderComponent, PopoverComponent = UiComponents_1.MemoizedPopover, TabsComponent = UiComponents_1.QuillTabs, CheckboxComponent = UiComponents_1.QuillChartBuilderCheckboxComponent, SidebarComponent = ui_1.QuillSidebar, ContainerComponent = ui_1.CustomContainer, SelectColumnComponent = ui_1.QuillSelectColumn, DraggableColumnComponent = ui_1.QuillDraggableColumn, SidebarHeadingComponent = ui_1.QuillSidebarHeading, FilterPopoverComponent = ui_1.QuillFilterPopover, SortPopoverComponent = ui_1.QuillSortPopover, LimitPopoverComponent = ui_1.QuillLimitPopover, CardComponent = QuillCard_1.QuillCard, LabelComponent = UiComponents_1.MemoizedLabel, HeaderComponent = UiComponents_1.MemoizedHeader, SubHeaderComponent = UiComponents_1.MemoizedSubHeader, TextComponent = UiComponents_1.MemoizedText, ErrorMessageComponent = UiComponents_1.QuillErrorMessageComponent, ChartBuilderInputRowContainer = UiComponents_1.QuillChartBuilderInputRowContainer, ChartBuilderInputColumnContainer = UiComponents_1.QuillChartBuilderInputColumnContainer, PivotRowContainer = UiComponents_1.QuillPivotRowContainer, PivotColumnContainer = UiComponents_1.QuillPivotColumnContainer, LoadingComponent = UiComponents_1.QuillLoadingComponent, ColumnSearchEmptyState = UiComponents_1.QuillColumnSearchEmptyState, ChartBuilderFormContainer = UiComponents_1.QuillChartBuilderFormContainer, ChartBuilderModalComponent = UiComponents_1.MemoizedModal, isAdminEnabled = false, isAIEnabled = true, containerStyle, className, pivotRecommendationsEnabled = true, reportId, hideCopySQL = true, isChartBuilderHorizontalView = true, onClickChartElement, }) {
72
+ /**
73
+ * The state of the ReportBuilder is based off of an AST, which is a representation of a sql query
74
+ * ASTs for the same query can vary between database types, so we create a layer of abstraction on top of it
75
+ * An AST consists of these main parts:
76
+ * - from: the table(s) that the query is pulling data from
77
+ * - columns: the columns that the query is selecting
78
+ * - where: the conditions that the query is filtering by (filters)
79
+ * - groupby: the columns that the query is grouping by (these are represented by pivots)
80
+ * - orderby: the columns that the query is ordering by (sort)
81
+ * - limit: the number of rows that the query is limiting to (limit)
82
+ *
83
+ * The ReportBuilder maintains the state of these parts of the AST and assembles the AST when required
84
+ *
85
+ * User Interactions
86
+ * - Add Tables
87
+ * - Add Columns
88
+ * - Add Filters
89
+ * - Add Pivot
90
+ * - Add Sort
91
+ * - Add Limit
92
+ *
93
+ * - Two modes
94
+ * - Automatic: Run Query after every change
95
+ * - Manual: Run Query after user clicks "Run Query"
96
+ * */
97
+ // Notable ReportBuilder props
98
+ // intitialTableName: the table that the ReportBuilder will start with
99
+ // isAdminEnabled: whether the ReportBuilder is in admin mode
100
+ // isAIEnabled: whether the ReportBuilder's AI features are enabled
101
+ // pivotRecommendationsEnabled: whether the PivotModal's AI features are enabled
102
+ // reportId: a report id that the Report Builder will query from and modify
103
+ // onSubmitCreateReport: a callback function that will trigger when a new chart is saved
104
+ // onSubmitEditReport: a callback function that will trigger when a chart is edited
105
+ // onDiscardChanges: a callback function that will trigger when changes are discarded
106
+ // onCloseChartBuilder: a callback function that will trigger when the chart builder is closed
107
+ // hideCopySQL: hide the copy SQL button
108
+ // isChartBuilderHorizontalView: whether the chart builder is in horizontal view mode
109
+ // onClickChartElement: a callback function triggered when a chart element is clicked
110
+ // Contexts
82
111
  const [dashboard] = (0, react_1.useContext)(Context_1.DashboardContext);
83
112
  const [schemaData] = (0, react_1.useContext)(Context_1.SchemaDataContext);
84
- const { dashboardFilters } = (0, react_1.useContext)(Context_1.DashboardFiltersContext);
113
+ const { dashboards } = (0, useDashboard_1.useDashboards)();
114
+ const destinationDashboardConfig = (0, react_1.useMemo)(() => {
115
+ return dashboards?.find((d) => d.name === destinationDashboard);
116
+ }, [dashboards, destinationDashboard]);
117
+ const filteredSchema = (0, react_1.useMemo)(() => {
118
+ return schemaData.schemaWithCustomFields?.filter((table) => {
119
+ return (destinationDashboardConfig?.tenantKeys?.[0] === constants_1.SINGLE_TENANT ||
120
+ table.ownerTenantFields?.length === 0 ||
121
+ table.ownerTenantFields?.includes(destinationDashboardConfig?.tenantKeys?.[0] ?? ''));
122
+ });
123
+ }, [schemaData.schemaWithCustomFields, destinationDashboardConfig?.tenantKeys]);
85
124
  const { tenants } = (0, react_1.useContext)(Context_1.TenantContext);
86
- const specificDashboardFilters = (0, react_1.useMemo)(() => {
87
- if (!reportId)
88
- return [];
89
- const dashboardName = dashboard[reportId]?.dashboardName;
90
- if (!dashboardName)
91
- return [];
92
- return Object.values(dashboardFilters[dashboardName] ?? {}).map((f) => f.filter);
93
- }, [dashboardFilters, reportId, dashboard]);
125
+ const [theme] = (0, react_1.useContext)(Context_1.ThemeContext);
94
126
  const [client] = (0, react_1.useContext)(Context_1.ClientContext);
95
- const [reportInfo, setReportInfo] = (0, react_1.useState)(null);
96
- const [aiPrompt, setAiPrompt] = (0, react_1.useState)('');
97
- const [errorMessage, setErrorMessage] = (0, react_1.useState)('');
98
- const [baseAst, setBaseAst] = (0, react_1.useState)(null);
99
- const [formData, setFormData] = (0, react_1.useState)(null);
100
- const [orderedColumnNames, setOrderedColumnNames] = (0, react_1.useState)([]);
101
- const [selectedColumns, setSelectedColumns] = (0, react_1.useState)([]);
102
- const [selectedOrderedColumns, setSelectedOrderedColumns] = (0, react_1.useState)([]);
103
- const [isSaveQueryModalOpen, setIsSaveQueryModalOpen] = (0, react_1.useState)(false);
104
- const [activeQuery, setActiveQuery] = (0, react_1.useState)('');
105
- const [, setActiveEditItem] = (0, react_1.useState)(null);
106
- const [openPopover, setOpenPopover] = (0, react_1.useState)(null);
107
- const [loading, setLoading] = (0, react_1.useState)(!!initialTableName);
108
- const [isChartBuilderOpen, setIsChartBuilderOpen] = (0, react_1.useState)(false);
109
- const [isCopying, setIsCopying] = (0, react_1.useState)(false);
110
- const [dataDisplayed, setDataDisplayed] = (0, react_1.useState)(false);
111
- const [rows, setRows] = (0, react_1.useState)([]);
112
- const [formattedRows, setFormattedRows] = (0, react_1.useState)([]);
113
- const [columns, setColumns] = (0, react_1.useState)([]);
127
+ // Refs
128
+ const parentRef = (0, react_1.useRef)(null);
129
+ // Consts
114
130
  const REPORT_BUILDER_PAGINATION = {
115
131
  page: 0,
116
132
  rowsPerPage: 20,
117
133
  rowsPerRequest: 100,
118
134
  };
135
+ // ReportBuilder UI States
136
+ const [isChartBuilderOpen, setIsChartBuilderOpen] = (0, react_1.useState)(false);
137
+ const [filtersEnabled, setFiltersEnabled] = (0, react_1.useState)(!!reportId);
138
+ const [isSaveQueryModalOpen, setIsSaveQueryModalOpen] = (0, react_1.useState)(false);
139
+ const [openPopover, setOpenPopover] = (0, react_1.useState)(null);
140
+ const [aiPrompt, setAiPrompt] = (0, react_1.useState)('');
141
+ const [reportBuilderLoading, setReportBuilderLoading] = (0, react_1.useState)(false);
142
+ const [tableLoading, setTableLoading] = (0, react_1.useState)(false);
143
+ const [errorMessage, setErrorMessage] = (0, react_1.useState)('');
144
+ const [unresolvedReportMessage, setUnresolvedReportMessage] = (0, react_1.useState)('');
145
+ // Core Report states
146
+ const [tables, setTables] = (0, react_1.useState)([]);
147
+ const [columns, setColumns] = (0, react_1.useState)([]);
148
+ const [filterStack, setFilterStack] = (0, react_1.useState)([]);
149
+ const [pivot, setPivot] = (0, react_1.useState)(null);
150
+ const [sort, setSort] = (0, react_1.useState)([]);
151
+ const [limit, setLimit] = (0, react_1.useState)(null);
152
+ const reportBuilderState = (0, react_1.useMemo)(() => {
153
+ return {
154
+ tables,
155
+ columns,
156
+ filterStack,
157
+ pivot,
158
+ sort,
159
+ limit,
160
+ };
161
+ }, [columns, filterStack, limit, pivot, sort, tables]);
162
+ const undoButtonEnabled = false; // TODO: enable
163
+ const [stateStack, setStateStack] = (0, react_1.useState)([]);
164
+ // Other Report states
165
+ const [activeQuery, setActiveQuery] = (0, react_1.useState)('');
166
+ const [unfilteredUniqueValues, setUnfilteredUniqueValues] = (0, react_1.useState)({}); // unique values before filtering
167
+ const [unfilteredUniqueValuesIsLoading, setUnfilteredUniqueValuesIsLoading] = (0, react_1.useState)(false);
168
+ const [filteredUniqueValues, setFilteredUniqueValues] = (0, react_1.useState)(null); // unique values after filtering
169
+ const [filteredUniqueValuesIsLoading, setFilteredUniqueValuesIsLoading] = (0, react_1.useState)(false);
170
+ const [columnUniqueValues, setColumnUniqueValues] = (0, react_1.useState)({});
171
+ const [dateRanges, setDateRanges] = (0, react_1.useState)(null);
119
172
  const [tempReport, setTempReport] = (0, react_1.useState)({
120
173
  ...report_1.EMPTY_INTERNAL_REPORT,
121
174
  pagination: REPORT_BUILDER_PAGINATION,
122
175
  });
123
- const [uniqueValues, setUniqueValues] = (0, react_1.useState)({});
124
- const [uniqueValuesIsLoading, setUniqueValuesIsLoading] = (0, react_1.useState)(false);
125
- const [pivot, setPivot] = (0, react_1.useState)(null);
176
+ const [currentProcessing, setCurrentProcessing] = (0, react_1.useState)({
177
+ page: REPORT_BUILDER_PAGINATION,
178
+ });
179
+ const [previousPage, setPreviousPage] = (0, react_1.useState)(0);
180
+ const [isCopying, setIsCopying] = (0, react_1.useState)(false);
181
+ const [sortOrLimitWasReset, setSortOrLimitWasReset] = (0, react_1.useState)(false);
182
+ // Table display states
183
+ const [reportColumns, setReportColumns] = (0, react_1.useState)([]);
184
+ const [reportRows, setReportRows] = (0, react_1.useState)([]);
185
+ const [formattedRows, setFormattedRows] = (0, react_1.useState)([]);
126
186
  const [pivotData, setPivotData] = (0, react_1.useState)(null);
187
+ const [numberOfRows, setNumberOfRows] = (0, react_1.useState)(0);
188
+ const [rowCountIsLoading, setRowCountIsLoading] = (0, react_1.useState)(false);
189
+ const reportColumnsToStateColumns = (() => {
190
+ const positionMap = {};
191
+ columns.forEach((column, index) => {
192
+ positionMap[column.field] = index;
193
+ if (column.alias) {
194
+ positionMap[column.alias] = index;
195
+ }
196
+ });
197
+ // Sort reportColumns based on the position in columns
198
+ return [...reportColumns]
199
+ .filter((reportColumn) => positionMap[reportColumn.field] !== undefined)
200
+ .sort((a, b) => {
201
+ const posA = positionMap[a.field];
202
+ const posB = positionMap[b.field];
203
+ return posA && posB ? posA - posB : 0;
204
+ });
205
+ })();
206
+ // Pivot form states
207
+ const [pivotRowField, setPivotRowField] = (0, react_1.useState)(undefined);
208
+ const [pivotColumnField, setPivotColumnField] = (0, react_1.useState)(undefined);
209
+ const [pivotAggregations, setPivotAggregations] = (0, react_1.useState)([]);
210
+ const [pivotHint, setPivotHint] = (0, react_1.useState)('');
211
+ const [pivotError, setPivotError] = (0, react_1.useState)('');
127
212
  const [createdPivots, setCreatedPivots] = (0, react_1.useState)([]);
128
213
  const [recommendedPivots, setRecommendedPivots] = (0, react_1.useState)([]);
129
214
  const [pivotPopUpTitle, setPivotPopUpTitle] = (0, react_1.useState)('Add pivot');
130
215
  const [showPivotPopover, setShowPivotPopover] = (0, react_1.useState)(false);
131
216
  const [isEditingPivot, setIsEditingPivot] = (0, react_1.useState)(false);
132
- const [askedAQuestion, setAskedAQuestion] = (0, react_1.useState)(false);
133
- const [askAILoading, setAskAILoading] = (0, react_1.useState)(false);
134
217
  const [selectedPivotIndex, setSelectedPivotIndex] = (0, react_1.useState)(-1);
135
- const [initialLoad, setInitialLoad] = (0, react_1.useState)(!!initialTableName || !!reportId);
136
- const [currentTable, setCurrentTable] = (0, react_1.useState)(initialTableName || '');
137
- const parentRef = (0, react_1.useRef)(null);
218
+ const [pivotRecommendationsEnabledState, setPivotRecommendationsEnabledState,] = (0, react_1.useState)(pivotRecommendationsEnabled);
219
+ // Ask AI
220
+ const [askAILoading, setAskAILoading] = (0, react_1.useState)(false);
138
221
  const askAIContainerRef = (0, react_1.useRef)(null);
139
- const askAILoadingContainerRef = (0, react_1.useRef)(null);
140
222
  const [askAIInputWidth, setAskAIInputWidth] = (0, react_1.useState)(-1);
141
- const [askAILoadingContainerWidth, setAskAILoadingContainerWidth] = (0, react_1.useState)(-1);
142
- const [theme] = (0, react_1.useContext)(Context_1.ThemeContext);
143
- const [pivotRowField, setPivotRowField] = (0, react_1.useState)(undefined);
144
- const [pivotColumnField, setPivotColumnField] = (0, react_1.useState)(undefined);
145
- const [pivotAggregations, setPivotAggregations] = (0, react_1.useState)(reportInfo?.pivot?.aggregations ?? [
146
- {
147
- valueField: reportInfo?.pivot?.valueField,
148
- valueField2: reportInfo?.pivot?.valueField2,
149
- aggregationType: reportInfo?.pivot?.aggregationType,
150
- },
151
- ]);
152
- const [pivotHint, setPivotHint] = (0, react_1.useState)('');
153
- /* eslint-disable-next-line */
154
- const [pivotError, setPivotError] = (0, react_1.useState)(undefined);
155
- const [dateRanges, setDateRanges] = (0, react_1.useState)(null);
156
- const [fieldValuesMap, setFieldValuesMap] = (0, react_1.useState)({}); // Mapping of unique values per field, used in string filter 'in' and 'not in'
157
- const [globalUniqueValues, setGlobalUniqueValues] = (0, react_1.useState)({});
158
- const [globalUniqueValuesIsLoading, setGlobalUniqueValuesIsLoading] = (0, react_1.useState)(false);
159
- const { filterTree, filterStack } = (0, useAstToFilterTree_1.default)(formData, client, columns); // Stores the state of filters
160
- const [removingFilter, setRemovingFilter] = (0, react_1.useState)(false);
161
- const [pivotRecommendationsEnabledState, setPivotRecommendationsEnabledState,] = (0, react_1.useState)(pivotRecommendationsEnabled);
162
- const [unresolvedReportMessage, setUnresolvedReportMessage] = (0, react_1.useState)('');
163
- const dashboardName = (0, react_1.useMemo)(() => {
164
- if (destinationDashboard) {
165
- return destinationDashboard;
223
+ const loading = reportBuilderLoading || tableLoading;
224
+ const isSelectStar = (0, react_1.useMemo)(() => {
225
+ if (tables.length === 1) {
226
+ // Check if all columns are selected
227
+ const totalColumnLength = tables.reduce((acc, table) => {
228
+ const tableColumns = filteredSchema.find((t) => t.name === table.name)
229
+ ?.columns.length ?? 0;
230
+ return acc + tableColumns;
231
+ }, 0);
232
+ return totalColumnLength === columns.length;
166
233
  }
167
- if (!reportId) {
168
- return undefined;
234
+ else {
235
+ // TODO: Implement this to work with joins
236
+ // SELECT * won't work if joined table has shared column name
237
+ return false;
169
238
  }
170
- return dashboard[reportId]?.dashboardName;
171
- }, [reportId, dashboard, destinationDashboard]);
172
- const [filtersEnabled, setFiltersEnabled] = (0, react_1.useState)(!!reportId);
239
+ }, [tables, columns, filteredSchema]);
173
240
  const mssqlSortWarning = (0, react_1.useMemo)(() => {
174
241
  if (!client || client?.databaseType !== 'mssql') {
175
242
  return undefined;
176
243
  }
177
- else if (!pivot && !baseAst?.top) {
244
+ else if (!pivot && !limit) {
178
245
  return 'Please add a limit.';
179
246
  }
180
- }, [client, baseAst, pivot]);
181
- (0, react_1.useEffect)(() => {
182
- if (!client) {
183
- return;
247
+ }, [client, limit, pivot]);
248
+ // State changing functions
249
+ const clearAllState = () => {
250
+ setActiveQuery('');
251
+ handleMultiStateChange(ReportBuilder_1.EMPTY_REPORT_BUILDER_STATE);
252
+ setStateStack([]);
253
+ setFilteredUniqueValues(null);
254
+ setUnfilteredUniqueValues({});
255
+ setColumnUniqueValues({});
256
+ setDateRanges(null);
257
+ setTempReport({
258
+ ...report_1.EMPTY_INTERNAL_REPORT,
259
+ pagination: REPORT_BUILDER_PAGINATION,
260
+ });
261
+ resetProcessing();
262
+ setReportColumns([]);
263
+ setReportRows([]);
264
+ setFormattedRows([]);
265
+ setPivotData(null);
266
+ setNumberOfRows(0);
267
+ setRowCountIsLoading(false);
268
+ setPivotRowField(undefined);
269
+ setPivotColumnField(undefined);
270
+ setPivotAggregations([]);
271
+ setCreatedPivots([]);
272
+ setRecommendedPivots([]);
273
+ setSelectedPivotIndex(-1);
274
+ setAskAILoading(false);
275
+ setReportBuilderLoading(false);
276
+ setTableLoading(false);
277
+ setPivotError('');
278
+ setErrorMessage('');
279
+ setUnresolvedReportMessage('');
280
+ setPivotHint('');
281
+ };
282
+ const copySQLToClipboard = () => {
283
+ const query = pivot && pivotData ? pivotData.pivotQuery : activeQuery;
284
+ setIsCopying(true);
285
+ navigator.clipboard.writeText(query);
286
+ setTimeout(() => setIsCopying(false), 800);
287
+ };
288
+ const handleTablesChange = (newTables, updateStateStack = true) => {
289
+ setTables(newTables);
290
+ if (updateStateStack) {
291
+ setStateStack((prevStack) => [
292
+ ...prevStack,
293
+ { ...reportBuilderState, tables: newTables },
294
+ ]);
184
295
  }
185
- if (client.featureFlags?.['recommendedPivotsDisabled'] !== undefined) {
186
- setPivotRecommendationsEnabledState(!client.featureFlags?.['recommendedPivotsDisabled']);
296
+ };
297
+ const handleColumnsChange = (newColumns, fetchData, updateStateStack = true) => {
298
+ // If pivot is using removed columns, remove pivot
299
+ let removePivot = false;
300
+ if (pivot) {
301
+ const referencedColumns = [];
302
+ if (pivot.rowField) {
303
+ referencedColumns.push(pivot.rowField);
304
+ }
305
+ if (pivot.columnField) {
306
+ referencedColumns.push(pivot.columnField);
307
+ }
308
+ if (pivot.aggregations) {
309
+ pivot.aggregations.forEach((agg) => {
310
+ if (agg.valueField) {
311
+ referencedColumns.push(agg.valueField);
312
+ }
313
+ if (agg.valueField2) {
314
+ referencedColumns.push(agg.valueField2);
315
+ }
316
+ });
317
+ }
318
+ const columnMapping = referencedColumns
319
+ .map((col) => {
320
+ const column = columns.find((c) => (c.alias || c.field) === col);
321
+ return column;
322
+ })
323
+ .filter((c) => c !== undefined);
324
+ removePivot = !columnMapping.every((col) => newColumns.some((c) => (c.alias || c.field) === (col.alias || col.field) &&
325
+ c.table === col.table));
326
+ if (removePivot) {
327
+ handlePivotChange(null);
328
+ }
187
329
  }
188
- if (!initialLoad && client.publicKey) {
189
- clearAllState();
330
+ setColumns(newColumns);
331
+ if (updateStateStack) {
332
+ setStateStack((prevStack) => [
333
+ ...prevStack,
334
+ { ...reportBuilderState, columns: newColumns },
335
+ ]);
190
336
  }
191
- }, [client]);
192
- (0, react_1.useEffect)(() => {
193
- (0, width_1.updateFirstChildWidth)(askAIContainerRef, setAskAIInputWidth, { gap: 12 });
194
- (0, width_1.updateFirstChildWidth)(askAILoadingContainerRef, setAskAILoadingContainerWidth, { gap: 12 });
195
- }, [dataDisplayed]);
196
- (0, react_1.useEffect)(() => {
197
- if (isChartBuilderOpen === false) {
198
- onCloseChartBuilder && onCloseChartBuilder();
337
+ if (fetchData) {
338
+ fetchDataFromReportBuilderState({
339
+ ...reportBuilderState,
340
+ columns: newColumns,
341
+ pivot: removePivot ? null : pivot,
342
+ });
199
343
  }
200
- }, [isChartBuilderOpen]);
201
- // Whenever unique values changes, update the fieldValuesMap, used in FilterModals
202
- const updateFieldValuesMap = (curUniqueValues, tableName) => {
203
- const newFieldValues = {};
204
- if (curUniqueValues[tableName]) {
205
- for (const field of Object.keys(curUniqueValues[tableName])) {
206
- newFieldValues[field] = [];
207
- for (const value of Object.keys(curUniqueValues[tableName][field])) {
208
- newFieldValues[field]?.push(value);
209
- }
344
+ };
345
+ const handleFilterInsertion = (newFilter) => {
346
+ const newFilterStack = [...filterStack];
347
+ if (newFilterStack.length > 0) {
348
+ const tabNode = {
349
+ leaf: false,
350
+ operator: 'and',
351
+ leftNode: null,
352
+ rightNode: null,
353
+ };
354
+ newFilterStack.push(tabNode);
355
+ }
356
+ const newItem = {
357
+ leaf: true,
358
+ operator: null,
359
+ leftNode: null,
360
+ rightNode: null,
361
+ value: newFilter,
362
+ };
363
+ newFilterStack.push(newItem);
364
+ handleFilterStackChange(newFilterStack, true);
365
+ };
366
+ const handleFilterStackChange = (newFilterStack, fetchData, updateStateStack = true) => {
367
+ setFilterStack(newFilterStack);
368
+ if (newFilterStack.length === 0) {
369
+ setFilteredUniqueValues(null);
370
+ }
371
+ if (updateStateStack) {
372
+ setStateStack((prevStack) => [
373
+ ...prevStack,
374
+ { ...reportBuilderState, filterStack: newFilterStack },
375
+ ]);
376
+ }
377
+ if (fetchData) {
378
+ fetchDataFromReportBuilderState({
379
+ ...reportBuilderState,
380
+ filterStack: newFilterStack,
381
+ }, true);
382
+ }
383
+ };
384
+ const handlePivotChange = (newPivot, fetchData, updateStateStack = true) => {
385
+ setPivot(newPivot ? (0, reportBuilder_1.setTypesOnPivot)(newPivot, reportColumns) : null);
386
+ setPivotHint('');
387
+ setPivotError('');
388
+ if (!newPivot) {
389
+ setPivotData(null);
390
+ if (!fetchData) {
391
+ const formattedRows = (0, reportBuilder_1.formatRows)(reportRows, reportColumns, false);
392
+ setFormattedRows(formattedRows);
210
393
  }
211
394
  }
212
- setFieldValuesMap(newFieldValues);
395
+ let resetSortAndLimit = false;
396
+ if (!pivot && newPivot && (sort.length > 0 || limit)) {
397
+ setSort([]);
398
+ setLimit(null);
399
+ resetSortAndLimit = true;
400
+ }
401
+ setSortOrLimitWasReset(resetSortAndLimit);
402
+ if (updateStateStack) {
403
+ setStateStack((prevStack) => [
404
+ ...prevStack,
405
+ {
406
+ ...reportBuilderState,
407
+ pivot: newPivot,
408
+ sort: resetSortAndLimit ? [] : sort,
409
+ limit: resetSortAndLimit ? null : limit,
410
+ },
411
+ ]);
412
+ }
413
+ if (fetchData) {
414
+ fetchDataFromReportBuilderState({
415
+ ...reportBuilderState,
416
+ pivot: newPivot,
417
+ sort: resetSortAndLimit ? [] : sort,
418
+ limit: resetSortAndLimit ? null : limit,
419
+ });
420
+ }
213
421
  };
214
- (0, react_1.useEffect)(() => {
215
- // Since the TextInput component takes a required numeric width parameter,
216
- // we dynamically calculate the width of this component here.
217
- function handleResize() {
218
- (0, width_1.updateFirstChildWidth)(askAIContainerRef, setAskAIInputWidth, { gap: 12 });
219
- (0, width_1.updateFirstChildWidth)(askAILoadingContainerRef, setAskAILoadingContainerWidth, { gap: 12 });
422
+ const updatePivot = async (changeField, fieldKey) => {
423
+ if (!client || !pivot) {
424
+ return;
220
425
  }
221
- handleResize();
222
- window.addEventListener('resize', handleResize);
223
- return () => {
224
- window.removeEventListener('resize', handleResize);
225
- };
226
- }, []);
227
- const setTypesOnPivot = (newPivot, searchColumns) => ({
228
- ...newPivot,
229
- aggregations: newPivot.aggregations?.map((agg) => ({
230
- ...agg,
231
- valueFieldType: searchColumns.find((c) => c.field === agg.valueField)
232
- ?.jsType,
233
- valueField2Type: searchColumns.find((c) => c.field === agg.valueField2)
234
- ?.jsType,
235
- })),
236
- valueField: newPivot.aggregations?.[0]?.valueField,
237
- valueField2: newPivot.aggregations?.[0]?.valueField2,
238
- aggregationType: newPivot.aggregations?.[0]?.aggregationType,
239
- valueFieldType: searchColumns.find((c) => c.field === newPivot.aggregations?.[0]?.valueField)?.jsType,
240
- valueField2Type: searchColumns.find((c) => c.field === newPivot.aggregations?.[0]?.valueField2)?.jsType,
241
- });
242
- const updatePivot = async (changeField, fieldKey, prevValue) => {
243
- let newPivot = (0, util_1.deepCopy)(pivot);
244
- setPivotError(undefined);
426
+ let newPivot = { ...pivot };
427
+ setPivotError('');
245
428
  // @ts-ignore
246
429
  newPivot[fieldKey] = changeField;
247
430
  newPivot.rowLimit = undefined;
248
431
  newPivot.sort = undefined;
432
+ newPivot.sortDirection = undefined;
433
+ newPivot.sortField = undefined;
434
+ newPivot.sortFieldType = undefined;
249
435
  if (fieldKey === 'rowField') {
250
436
  if (changeField === '' || changeField === undefined) {
251
437
  setPivotColumnField(undefined);
@@ -257,22 +443,8 @@ function ReportBuilder({ initialTableName = '', onSubmitEditReport = () => void
257
443
  : agg.aggregationType,
258
444
  })));
259
445
  }
260
- // check to see if the new rowField value is a date field
261
- const column = columns.find((c) => c.field === changeField);
262
- if (column?.jsType === 'date') {
263
- newPivot.rowFieldType = 'date';
264
- newPivot.sort = true;
265
- newPivot.sortField = changeField;
266
- newPivot.sortFieldType = column.format;
267
- newPivot.sortDirection = 'ASC';
268
- }
269
- else {
270
- newPivot.rowFieldType = 'string';
271
- newPivot.sort = undefined;
272
- }
273
446
  }
274
- newPivot = setTypesOnPivot(newPivot, columns);
275
- setPivot(setTypesOnPivot(newPivot, columns));
447
+ newPivot = (0, reportBuilder_1.setTypesOnPivot)(newPivot, reportColumns);
276
448
  if (newPivot.aggregations?.length === 0 ||
277
449
  newPivot.aggregations?.some((agg) => !agg.aggregationType) ||
278
450
  newPivot.aggregations?.some((agg) => !agg.valueField && agg.aggregationType !== 'count')) {
@@ -283,793 +455,116 @@ function ReportBuilder({ initialTableName = '', onSubmitEditReport = () => void
283
455
  setPivotError(reason);
284
456
  return;
285
457
  }
286
- resetLimit();
287
- resetSort();
288
- setPreviousPage(0);
289
- setTableLoading(true);
290
- let dateBucket = undefined;
291
- const tempDateRange = dateRanges && dateRanges[newPivot.rowField || ''];
292
- if (tempDateRange) {
293
- dateBucket = (0, dates_1.getDateBucketFromRange)(tempDateRange.dateRange);
294
- }
295
- let distinctValuesForQuery = {};
296
- const prevPivot = pivot;
297
- const prevPivotData = pivotData;
298
- setPivotHint('');
299
- if (newPivot.columnField) {
300
- if (uniqueValues?.[newPivot.columnField]) {
301
- distinctValuesForQuery = uniqueValues;
302
- }
303
- else {
304
- distinctValuesForQuery = await (0, tableProcessing_1.getUniqueValuesByColumns)([
305
- {
306
- field: newPivot.columnField,
307
- label: newPivot.columnField,
308
- format: 'string',
309
- },
310
- ], activeQuery, [], client, tenants, schemaData.customFields ?? {}, undefined, dashboardName);
311
- }
312
- }
313
- try {
314
- const pivotedData = await (0, PivotModal_1.generatePivotTable)({
315
- pivot: newPivot,
316
- dateBucket,
317
- report: tempReport,
318
- client,
319
- uniqueValues: distinctValuesForQuery,
320
- dashboardName,
321
- tenants,
322
- additionalProcessing: { page: REPORT_BUILDER_PAGINATION },
323
- });
324
- resetProcessing();
325
- setPivotData(pivotedData || []);
326
- const formattedRows = formatRows(pivotedData.rows, columns, true, newPivot.aggregationType);
327
- setFormattedRows(formattedRows);
328
- }
329
- catch (e) {
330
- switch (fieldKey) {
331
- case 'rowField':
332
- setPivotRowField(prevValue);
333
- break;
334
- case 'columnField':
335
- setPivotColumnField(prevValue);
336
- break;
337
- case 'aggregations':
338
- setPivotAggregations(prevValue);
339
- break;
340
- }
341
- setPivot(prevPivot);
342
- setPivotData(prevPivotData);
343
- if (e instanceof Error)
344
- setPivotError(e.message);
345
- }
346
- finally {
347
- setTableLoading(false);
348
- }
349
- };
350
- const resetLimit = (fetchData) => {
351
- const newAst = {
352
- ...baseAst,
353
- limit: null,
354
- top: null,
355
- orderby: client?.databaseType === 'mssql' ? null : baseAst.orderby,
356
- };
357
- setBaseAst((prevAst) => ({
358
- ...prevAst,
359
- limit: null,
360
- top: null,
361
- orderby: client?.databaseType === 'mssql' ? null : prevAst.orderby,
362
- }));
363
- setPivot((oldPivot) => {
364
- if (!oldPivot)
365
- return null;
366
- return {
367
- ...oldPivot,
368
- rowLimit: undefined,
369
- };
370
- });
371
- if (fetchData) {
372
- fetchReportFromASTHelper({
373
- baseAst: newAst,
374
- curPivot: pivot ? { ...pivot, rowLimit: undefined } : undefined,
375
- });
376
- }
458
+ handlePivotChange(newPivot, true);
377
459
  };
378
- const resetSort = (fetchData) => {
379
- if (pivot) {
380
- setPivot((oldPivot) => {
381
- if (!oldPivot)
382
- return null;
383
- return {
384
- ...oldPivot,
385
- sort: undefined,
386
- sortField: undefined,
387
- sortDirection: undefined,
388
- sortFieldType: undefined,
389
- };
390
- });
460
+ const handleSortChange = (newSort, fetchData, updateStateStack = true) => {
461
+ setSort(newSort);
462
+ if (updateStateStack) {
463
+ setStateStack((prevStack) => [
464
+ ...prevStack,
465
+ { ...reportBuilderState, sort: newSort },
466
+ ]);
391
467
  }
392
- const newAst = { ...baseAst, orderby: null };
393
- setBaseAst((prevAst) => ({ ...prevAst, orderby: null }));
394
468
  if (fetchData) {
395
- fetchReportFromASTHelper({
396
- baseAst: newAst,
397
- curPivot: pivot
398
- ? {
399
- ...pivot,
400
- sort: undefined,
401
- sortField: undefined,
402
- sortDirection: undefined,
403
- sortFieldType: undefined,
404
- }
405
- : undefined,
469
+ fetchDataFromReportBuilderState({
470
+ ...reportBuilderState,
471
+ sort: newSort,
406
472
  });
407
473
  }
408
474
  };
409
- const enforceOrderOnColumns = (columnNames) => {
410
- if (pivot) {
411
- const rowName = pivot.rowField;
412
- const sortFn = (a, b) => a === rowName ? -1 : b === rowName ? 1 : 0;
413
- const columnsInPivot = getColumnsInPivotExpanded();
414
- return columnNames
415
- .sort(sortFn)
416
- .filter((c) => columnsInPivot.includes(c));
417
- }
418
- // make the columnNames match the order of the selectedOrderedColumns
419
- return columnNames.sort((a, b) => selectedOrderedColumns.indexOf(a) - selectedOrderedColumns.indexOf(b));
420
- // return columnNames;
421
- };
422
- const clearAllState = () => {
423
- // We're trying to not block the main thread while resetting all the state.
424
- // This shouldn't be an issue since the dispatches shouldn't block, but
425
- // this seems to work for now. ¯\_(ツ)_/¯
426
- setTimeout(() => {
427
- setAskedAQuestion(false);
428
- setAiPrompt('');
429
- setBaseAst(null);
430
- setFormData(null);
431
- setSelectedColumns([]);
432
- setActiveQuery('');
433
- setActiveEditItem(null);
434
- setOpenPopover(null);
435
- setLoading(false);
436
- setDataDisplayed(false);
437
- setRows([]);
438
- setColumns([]);
439
- setSelectedOrderedColumns([]);
440
- setErrorMessage('');
441
- setPivotError(undefined);
442
- setFormattedRows([]);
443
- setCurrentTable('');
444
- setUniqueValues({});
445
- setPivot(null);
446
- setPivotHint('');
447
- setPivotData(null);
448
- setRecommendedPivots([]);
449
- }, 0);
450
- };
451
- const fetchGlobalUniqueValues = async (columns, currentTable, client) => {
452
- setGlobalUniqueValuesIsLoading(true);
453
- const global = await (0, tableProcessing_1.getUniqueStringValues)(columns, currentTable, client, tenants, schemaData.customFields, undefined, true, undefined, dashboardName);
454
- setGlobalUniqueValues((0, filterProcessing_1.uniqueValuesToStringMap)(global));
455
- setGlobalUniqueValuesIsLoading(false);
456
- };
457
- const uniqueValuesDependenciesRef = (0, react_1.useRef)({ client, columns, currentTable });
458
- const memoizedFetchGlobalUniqueValues = (0, react_1.useCallback)(fetchGlobalUniqueValues, []);
459
- (0, react_1.useEffect)(() => {
460
- const hasChanged = !(0, fast_deep_equal_1.default)({ client, columns, currentTable }, uniqueValuesDependenciesRef.current);
461
- if (hasChanged && client && columns && currentTable) {
462
- memoizedFetchGlobalUniqueValues(columns, currentTable, client);
463
- uniqueValuesDependenciesRef.current = { client, columns, currentTable };
464
- }
465
- }, [client, columns, currentTable, memoizedFetchGlobalUniqueValues]);
466
- const formatRows = (rows, columns, pivot, aggregationType, dateBucket) => {
467
- const copiedRows = (0, util_1.deepCopy)(rows);
468
- if (pivot) {
469
- const formattedRows = copiedRows.map((row) => {
470
- const formattedRow = row;
471
- Object.keys(row).forEach((key) => {
472
- const column = columns.find((c) => c.field === key);
473
- let format = 'string';
474
- if (!column) {
475
- format =
476
- aggregationType === 'count'
477
- ? 'whole_number'
478
- : 'two_decimal_places';
479
- }
480
- else {
481
- format = valueFormatter_1.DATE_FORMAT_TYPES.includes(column.format)
482
- ? dateBucket
483
- ? (0, dates_1.getDateFormatFromBucket)(dateBucket)
484
- : 'MMM_yyyy'
485
- : 'string';
486
- }
487
- const formattedValue = (0, valueFormatter_1.quillFormat)({
488
- value: row[key],
489
- format,
490
- });
491
- formattedRow[key] = formattedValue;
492
- });
493
- return formattedRow;
494
- });
495
- return formattedRows;
496
- }
497
- else {
498
- const formattedRows = copiedRows.map((row) => {
499
- return columns.reduce((formattedRow, column) => {
500
- // Apply the format function to each field in the row
501
- const formattedValue = (0, valueFormatter_1.quillFormat)({
502
- value: row[column.field],
503
- format: column.format,
504
- });
505
- formattedRow[column.field] = formattedValue;
506
- return formattedRow;
507
- }, {});
508
- });
509
- return formattedRows;
510
- }
511
- };
512
- const copySQLToClipboard = () => {
513
- let query = activeQuery;
514
- if (pivot) {
515
- query = (0, pivotProcessing_1.pivotToSql)(pivot, activeQuery, columns);
516
- }
517
- setIsCopying(true);
518
- navigator.clipboard.writeText(query);
519
- setTimeout(() => setIsCopying(false), 800);
520
- };
521
- const clearCheckboxes = () => {
522
- const checkboxes = uniqueValues;
523
- const newValues = {};
524
- for (const table of Object.keys(checkboxes)) {
525
- newValues[table] = {};
526
- for (const column of Object.keys(checkboxes[table])) {
527
- newValues[table][column] = {};
528
- for (const variant of Object.keys(checkboxes[table][column])) {
529
- newValues[table][column][variant] = false;
530
- }
531
- }
475
+ const handleLimitChange = (newLimit, fetchData, updateStateStack = true) => {
476
+ setLimit(newLimit);
477
+ if (updateStateStack) {
478
+ setStateStack((prevStack) => [
479
+ ...prevStack,
480
+ { ...reportBuilderState, limit: newLimit },
481
+ ]);
532
482
  }
533
- setUniqueValues(newValues);
534
- updateFieldValuesMap(newValues, currentTable);
535
- };
536
- const fetchSqlQuery = async (ast, formData, fetchData = true) => {
537
483
  if (fetchData) {
538
- setLoading(true);
539
- }
540
- setErrorMessage('');
541
- try {
542
- const where = formData ? formData : ast?.where || null;
543
- const response = await fetch(`${constants_2.QUILL_SERVER}/sqlify`, {
544
- method: 'POST',
545
- headers: {
546
- 'Content-Type': 'application/json',
547
- },
548
- body: JSON.stringify({
549
- ast: { ...ast, where },
550
- publicKey: client.publicKey,
551
- useNewNodeSql: true, // new flag
552
- }),
484
+ fetchDataFromReportBuilderState({
485
+ ...reportBuilderState,
486
+ limit: newLimit,
553
487
  });
554
- const data = await response.json();
555
- setActiveQuery(data.query);
556
- if (fetchData) {
557
- fetchReportFromASTHelper({
558
- baseAst: ast,
559
- newFormData: formData,
560
- });
561
- }
562
- return data.query;
563
- }
564
- catch (error) {
565
- setLoading(false);
566
- console.error(error);
567
- }
568
- };
569
- const getDateRanges = async (columns, tableName) => {
570
- const dateColumns = columns.filter((column) => {
571
- return column.fieldType === 'date';
572
- });
573
- if (dateColumns.length === 0) {
574
- return {};
575
488
  }
576
- const dateColumnNames = dateColumns.map((column) => {
577
- return column.field;
578
- });
579
- const dateRanges = await (0, tableProcessing_1.getQueryDateRangeByColumns)(dateColumns, `Select ${dateColumnNames.join(', ')} from ${tableName}`, client, tenants, schemaData.customFields ?? {}, dashboardName);
580
- return dateRanges;
581
- };
582
- // It's just like getColumnsInPivot but we expand the columnField
583
- // if there is one to include all the variants just like it would
584
- // show up in the table. (eg. category -> ...[Fuel, Food, Other])
585
- const getColumnsInPivotExpanded = () => {
586
- if (!pivot)
587
- return [];
588
- const tables = (0, ast_1.getTableNames)(baseAst);
589
- if (tables.length !== 1)
590
- return [];
591
- const result = [];
592
- const table = tables[0];
593
- const { valueField, rowField, columnField } = pivot;
594
- if (columnField &&
595
- uniqueValues[table] &&
596
- uniqueValues[table][columnField]) {
597
- result.push(...Object.keys(uniqueValues[table][columnField]));
598
- }
599
- result.push(valueField, rowField);
600
- return result.filter(Boolean);
601
- };
602
- const loadTable = async (tables) => {
603
- if (!tables?.length || !schemaData.schema?.length)
604
- return;
605
- setLoading(true);
606
- const tableInfo = tables.find((tableInfo) => tableInfo.name === initialTableName);
607
- if (tableInfo) {
608
- setUniqueValuesIsLoading(true);
609
- const newUniqueValues = await (0, tableProcessing_1.getUniqueStringValues)(tableInfo.columns, initialTableName, client, tenants, schemaData.customFields, uniqueValues, true, undefined, dashboardName);
610
- if ((0, crypto_1.hashCode)(uniqueValues) !== (0, crypto_1.hashCode)(newUniqueValues)) {
611
- setUniqueValues(newUniqueValues);
612
- updateFieldValuesMap(newUniqueValues, initialTableName);
613
- }
614
- setUniqueValuesIsLoading(false);
615
- const dateRangesTemp = await getDateRanges(tableInfo.columns, initialTableName);
616
- setDateRanges(dateRangesTemp);
617
- }
618
- const columnsForTable = tables
619
- .find((t) => t.name === initialTableName)
620
- ?.columns.map((c) => c.field)
621
- .sort((a, b) => {
622
- const aIsId = a.endsWith('.id') ||
623
- a.endsWith('_id') ||
624
- a.endsWith('Id') ||
625
- a === 'id';
626
- const bIsId = b.endsWith('.id') ||
627
- b.endsWith('_id') ||
628
- b.endsWith('Id') ||
629
- b === 'id';
630
- if (aIsId && !bIsId)
631
- return 1;
632
- if (bIsId && !aIsId)
633
- return -1;
634
- return 0;
635
- });
636
- await fetchAstFromPromptHelper(`get ${columnsForTable} from ${initialTableName}`);
637
- setInitialLoad(false);
638
489
  };
639
- const onSchemaChange = async () => {
640
- try {
641
- setOrderedColumnNames((schemaData.schemaWithCustomFields ?? []).flatMap((table) => table.columns
642
- .map((c) => `${table.name}.${c.field}`)
643
- .sort((a, b) => {
644
- const aIsId = a.endsWith('.id') ||
645
- a.endsWith('_id') ||
646
- a.endsWith('Id') ||
647
- a === 'id';
648
- const bIsId = b.endsWith('.id') ||
649
- b.endsWith('_id') ||
650
- b.endsWith('Id') ||
651
- b === 'id';
652
- if (aIsId && !bIsId)
653
- return 1;
654
- if (bIsId && !aIsId)
655
- return -1;
656
- return 0;
657
- })));
658
- if (initialTableName) {
659
- await loadTable(schemaData.schemaWithCustomFields);
660
- }
661
- setInitialLoad(false);
490
+ const handleMultiStateChange = (state, fetchData, updateStateStack = true) => {
491
+ if (state.tables !== undefined) {
492
+ handleTablesChange(state.tables, false);
662
493
  }
663
- catch (error) {
664
- console.error(error);
494
+ if (state.columns !== undefined) {
495
+ handleColumnsChange(state.columns, false, false);
665
496
  }
666
- };
667
- (0, react_1.useEffect)(() => {
668
- const loadChart = async () => {
669
- let report;
670
- try {
671
- if (!reportId) {
672
- throw new Error('Report ID is required');
673
- }
674
- report = dashboard[reportId];
675
- if (!report || report.referencedTables?.length !== 1) {
676
- throw new Error('Report not found');
677
- }
678
- const { ast: newAst, pivot: newPivot, schema: curSchema, } = await (0, astProcessing_1.fetchASTFromQuillReport)(report, client, schemaData.schemaWithCustomFields);
679
- setBaseAst({ ...newAst, where: null });
680
- await fetchReportFromASTHelper({
681
- baseAst: { ...newAst, where: null },
682
- newFormData: newAst.where,
683
- curPivot: newPivot,
684
- curSchema,
685
- previousReport: report,
686
- });
687
- await onSchemaChange();
688
- setReportInfo(report);
689
- const query = await fetchSqlQuery(newAst, null, false);
690
- setActiveQuery(query);
691
- }
692
- catch (err) {
693
- console.error(err);
694
- setErrorMessage('Error when loading chart');
695
- }
696
- };
697
- if (reportId) {
698
- loadChart();
497
+ if (state.filterStack !== undefined) {
498
+ handleFilterStackChange(state.filterStack, false, false);
699
499
  }
700
- }, [dashboard[reportId || '']]);
701
- (0, react_1.useEffect)(() => {
702
- onSchemaChange();
703
- }, [schemaData.schemaWithCustomFields, initialTableName, reportId]);
704
- // Function to handle the insertion of expressions
705
- const handleInsertion = (value) => {
706
- const newFilterStack = [...filterStack];
707
- if (newFilterStack.length > 0) {
708
- const tabNode = {
709
- leaf: false,
710
- operator: 'and',
711
- leftNode: null,
712
- rightNode: null,
713
- };
714
- newFilterStack.push(tabNode);
500
+ if (state.pivot !== undefined) {
501
+ handlePivotChange(state.pivot, false, false);
715
502
  }
716
- const newItem = {
717
- leaf: true,
718
- operator: null,
719
- leftNode: null,
720
- rightNode: null,
721
- value: value,
722
- };
723
- newFilterStack.push(newItem);
724
- const tree = (0, filterProcessing_1.filterStackToFilterTree)(newFilterStack);
725
- if (tree) {
726
- const newFormData = (0, astFilterProcessing_1.filterTreeToAst)(tree, client.databaseType.toLowerCase());
727
- setFormData(newFormData);
728
- const newAst = { ...baseAst };
729
- newAst.where = newFormData;
730
- setBaseAst(newAst);
731
- fetchSqlQuery(newAst, newFormData);
503
+ if (state.sort !== undefined) {
504
+ handleSortChange(state.sort, false, false);
732
505
  }
733
- };
734
- /**
735
- * Searches for the column by name and returns the field type.
736
- *
737
- * Searches the known schema and returns the fieldType of the first column
738
- * it can find with the given name. Will first search through the current
739
- * list of fields in the current query if any, then will default to searching
740
- * through the whole schema.
741
- *
742
- * If more than one column exist with the given name, it will return the first
743
- * one that it finds. This might not be the one that you intended.
744
- *
745
- * TODO: pass an optional table param to limit the search to a given table.
746
- *
747
- * @param columnName the name to search for.
748
- * @returns the fieldType string or undefined if not found.
749
- */
750
- const getColumnTypeByName = (columnName) => {
751
- const column = columns.find((col) => col.field === columnName);
752
- return column?.fieldType;
753
- };
754
- const emptyPivotColumns = () => {
755
- if (pivot && pivot.rowField && pivot.columnField) {
756
- return [
757
- { label: (0, textProcessing_1.snakeAndCamelCaseToTitleCase)(pivot.rowField) },
758
- { label: (0, textProcessing_1.snakeAndCamelCaseToTitleCase)(pivot.columnField) },
759
- ];
760
- }
761
- else if (pivot && pivot.rowField) {
762
- return [
763
- { label: (0, textProcessing_1.snakeAndCamelCaseToTitleCase)(pivot.rowField) },
764
- ...(pivot.aggregations ?? [])
765
- .filter((a) => !!a.valueField)
766
- .map((agg) => ({
767
- label: (0, textProcessing_1.snakeAndCamelCaseToTitleCase)(agg.valueField),
768
- })),
769
- ];
770
- }
771
- else {
772
- return (pivot?.aggregations ?? [])
773
- .filter((a) => !!a.valueField)
774
- .map((agg) => ({
775
- label: (0, textProcessing_1.snakeAndCamelCaseToTitleCase)(agg.valueField),
776
- }));
777
- }
778
- };
779
- const [previousPage, setPreviousPage] = (0, react_1.useState)(0);
780
- const [currentProcessing, setCurrentProcessing] = (0, react_1.useState)({
781
- page: REPORT_BUILDER_PAGINATION,
782
- });
783
- const [numberOfRows, setNumberOfRows] = (0, react_1.useState)(0);
784
- const [rowCountIsLoading, setRowCountIsLoading] = (0, react_1.useState)(false);
785
- const [tableLoading, setTableLoading] = (0, react_1.useState)(false);
786
- const resetProcessing = () => {
787
- setCurrentProcessing({ page: REPORT_BUILDER_PAGINATION });
788
- };
789
- const onPageChange = (page, initiator = 'ReportBuilder') => {
790
- const pagination = initiator === 'ReportBuilder'
791
- ? REPORT_BUILDER_PAGINATION
792
- : paginationProcessing_1.DEFAULT_PAGINATION;
793
- if (currentProcessing.page &&
794
- (0, paginationProcessing_1.shouldFetchMore)(pagination, page, previousPage, pivotData ? pivotData.rows.length : rows.length)) {
795
- const newPagination = { ...currentProcessing.page, page };
796
- const updatedProcessing = { ...currentProcessing, page: newPagination };
797
- setCurrentProcessing(updatedProcessing);
798
- handleRunQuery(updatedProcessing);
799
- }
800
- if (page > previousPage) {
801
- setPreviousPage(page);
802
- }
803
- };
804
- const onSortChange = (sort, isDelete) => {
805
- if (pivot) {
806
- let newPivot = null;
807
- if (isDelete) {
808
- setPivot((oldPivot) => {
809
- if (!oldPivot)
810
- return null;
811
- newPivot = {
812
- ...oldPivot,
813
- sort: undefined,
814
- sortField: undefined,
815
- sortDirection: undefined,
816
- sortFieldType: undefined,
817
- };
818
- return newPivot;
819
- });
820
- }
821
- else {
822
- setPivot((oldPivot) => {
823
- if (!oldPivot)
824
- return null;
825
- newPivot = {
826
- ...oldPivot,
827
- sort: true,
828
- sortField: sort.field,
829
- sortDirection: sort.direction,
830
- sortFieldType: getColumnTypeByName(sort.field),
831
- };
832
- return newPivot;
833
- });
834
- }
835
- fetchReportFromASTHelper({
836
- baseAst: baseAst,
837
- curPivot: newPivot,
838
- });
839
- }
840
- else {
841
- const newAst = { ...baseAst };
842
- if (!newAst.orderby) {
843
- newAst.orderby = [];
844
- }
845
- const existingSortIndex = newAst.orderby.findIndex((item) => (0, astFilterProcessing_1.getFieldFromExpression)(item.expr) === sort.field);
846
- if (isDelete) {
847
- if (existingSortIndex !== -1) {
848
- newAst.orderby.splice(existingSortIndex, 1);
849
- }
850
- }
851
- else if (existingSortIndex !== -1) {
852
- newAst.orderby[existingSortIndex] = {
853
- expr: { type: 'column_ref', column: sort.field },
854
- type: sort.direction.toUpperCase(),
855
- };
856
- }
857
- else {
858
- newAst.orderby.push({
859
- expr: { type: 'column_ref', column: sort.field },
860
- type: sort.direction.toUpperCase(),
861
- });
862
- }
863
- setBaseAst((0, util_1.deepCopy)(newAst));
864
- fetchReportFromASTHelper({
865
- baseAst: newAst,
866
- });
867
- setPreviousPage(0);
506
+ if (state.limit !== undefined) {
507
+ handleLimitChange(state.limit, false, false);
868
508
  }
869
- };
870
- const onLimitChange = (limit) => {
871
- if (limit) {
872
- if (pivot) {
873
- setPivot((oldPivot) => {
874
- if (!oldPivot)
875
- return null;
876
- const newPivot = { ...oldPivot, rowLimit: limit };
877
- fetchReportFromASTHelper({ baseAst, curPivot: newPivot });
878
- return newPivot;
879
- });
880
- }
881
- else {
882
- const newAst = { ...baseAst };
883
- if (client.databaseType.toLowerCase() === 'mssql') {
884
- newAst.top = {
885
- value: limit,
886
- };
887
- }
888
- else {
889
- newAst.limit = {
890
- seperator: '',
891
- value: [
892
- {
893
- type: 'number',
894
- value: limit,
895
- },
896
- ],
897
- };
898
- }
899
- setBaseAst((0, util_1.deepCopy)(newAst));
900
- fetchSqlQuery((0, util_1.deepCopy)(newAst), undefined, true);
901
- }
509
+ if (updateStateStack) {
510
+ setStateStack((prevStack) => [
511
+ ...prevStack,
512
+ { ...reportBuilderState, ...state },
513
+ ]);
902
514
  }
903
- else {
904
- resetLimit(true);
515
+ if (fetchData) {
516
+ fetchDataFromReportBuilderState({ ...reportBuilderState, ...state }, !!state.filterStack, !!state.tables);
905
517
  }
906
- setOpenPopover(null);
907
518
  };
908
- const fetchRowCount = async (processing, includeFilters) => {
909
- if (!client || !activeQuery) {
519
+ const handleUndo = () => {
520
+ if (stateStack.length <= 1) {
910
521
  return;
911
522
  }
912
- setRowCountIsLoading(true);
913
- const tableInfo = await (0, tableProcessing_1.fetchResultsByQuery)({
914
- query: activeQuery,
915
- client,
916
- tenants,
917
- processing,
918
- customFields: schemaData.customFields,
919
- filters: includeFilters ? specificDashboardFilters : undefined,
920
- dateField: includeFilters
921
- ? (tempReport.dateField ?? reportInfo?.dateField)
922
- : undefined,
923
- rowsOnly: false,
924
- rowCountOnly: true,
925
- filterMap: undefined,
926
- dashboardName,
927
- });
928
- if (tableInfo.rowCount) {
929
- setNumberOfRows(tableInfo.rowCount);
930
- // @ts-ignore
931
- setTempReport((tempReport) => ({
932
- ...tempReport,
933
- rowCount: tableInfo.rowCount,
934
- }));
935
- }
936
- setRowCountIsLoading(false);
523
+ const previousState = stateStack[stateStack.length - 2];
524
+ setStateStack((prevStack) => prevStack.slice(0, -1));
525
+ handleMultiStateChange(previousState, true, false);
937
526
  };
938
- const fetchRowCountFromAST = async (ast, where) => {
939
- setRowCountIsLoading(true);
940
- const tableData = await (0, tableProcessing_1.fetchTableByAST)({ ...ast, where }, client, tenants, { page: REPORT_BUILDER_PAGINATION }, schemaData.customFields, false, true, dashboardName);
941
- if (tableData.rowCount) {
942
- setNumberOfRows(tableData.rowCount);
943
- // @ts-ignore
944
- setTempReport((tempReport) => ({
945
- ...tempReport,
946
- rowCount: tableData.rowCount,
947
- }));
948
- }
949
- setRowCountIsLoading(false);
950
- };
951
- const handleRunQuery = async (processing, resetRows = false, includeFilters = false) => {
952
- try {
953
- const isPivotPagination = !!(pivot && pivotData);
954
- setErrorMessage('');
955
- setTableLoading(true);
956
- const tableInfo = await (0, tableProcessing_1.fetchResultsByQuery)({
957
- query: isPivotPagination ? pivotData.pivotQuery : activeQuery,
958
- comparisonQuery: pivot && pivotData ? pivotData.comparisonPivotQuery : undefined,
959
- client,
960
- tenants,
961
- processing,
962
- customFields: schemaData.customFields,
963
- rowsOnly: true,
964
- dashboardName,
965
- pivot: pivot,
966
- getPivotRowCount: false,
967
- });
968
- if (tableInfo.error) {
969
- throw new Error(tableInfo.error);
970
- }
971
- else if (tableInfo.rows.length === 0) {
972
- throw new Error('No data found');
973
- }
974
- if (!isPivotPagination) {
975
- // fetching row count for non-pivot query
976
- fetchRowCount(processing, includeFilters);
977
- let tempRows = [...rows, ...tableInfo.rows];
978
- if (resetRows) {
979
- tempRows = tableInfo.rows;
980
- setPreviousPage(0);
981
- }
982
- setRows(tempRows);
983
- setFormattedRows((0, report_1.formatRowsFromReport)({ rows: tempRows, columns: tableInfo.columns }));
984
- setTempReport((tempReport) => ({
985
- ...tempReport,
986
- rows: tempRows,
987
- rowCount: tableInfo.rowCount ?? tempReport.rowCount,
988
- }));
989
- setColumns(tableInfo.columns);
990
- }
991
- else {
992
- let tempRows = [...pivotData.rows, ...tableInfo.rows];
993
- if (resetRows) {
994
- tempRows = tableInfo.rows;
995
- setPreviousPage(0);
996
- }
997
- setPivotData((oldPivotData) => {
998
- if (oldPivotData) {
999
- return {
1000
- ...oldPivotData,
1001
- rows: tempRows,
1002
- columns: tableInfo.columns,
1003
- };
1004
- }
1005
- return null;
1006
- });
1007
- setFormattedRows((0, report_1.formatRowsFromReport)({ rows: tempRows, columns: tableInfo.columns }));
1008
- }
1009
- setTableLoading(false);
1010
- }
1011
- catch (e) {
1012
- setTableLoading(false);
1013
- setErrorMessage('Failed to run SQL query: ' + e.message);
1014
- setRows([]);
1015
- setColumns([]);
527
+ const fetchDataFromReportBuilderState = (state, filtersChanged, tablesChanged) => {
528
+ if (!client) {
1016
529
  return;
1017
530
  }
1018
- };
1019
- /**
1020
- * Return whether all columns have been selected (used to hide select all
1021
- * and show clear button).
1022
- */
1023
- const isSelectedAllColumns = () => {
1024
- if (selectedColumns.length < 1)
1025
- return false;
1026
- const allColumns = orderedColumnNames.filter((row) => {
1027
- const [table] = row.split('.');
1028
- const selectedTable = selectedColumns[0].split('.')[0];
1029
- return selectedTable === table;
531
+ const ast = (0, reportBuilder_1.reportBuilderStateToAst)(state, client.databaseType?.toLowerCase() || 'postgresql');
532
+ fetchReportFromASTHelper({
533
+ ast,
534
+ pivot: state.pivot,
535
+ requiresNewFilteredUniqueValues: filtersChanged,
536
+ requiresNewUnfilteredUniqueValues: tablesChanged,
1030
537
  });
1031
- return selectedColumns.length === allColumns.length;
1032
538
  };
1033
- const nameToColumn = (name) => ({
1034
- type: 'expr',
1035
- expr: {
1036
- type: 'column_ref',
1037
- table: null,
1038
- column: name,
1039
- },
1040
- as: null,
1041
- });
1042
- const updateUniqueValue = (uniqueStrings, table) => {
1043
- const uniqueStringsObj = uniqueValues ?? {};
1044
- uniqueStringsObj[table] = uniqueStrings ?? {};
1045
- setUniqueValues(uniqueStringsObj);
1046
- updateFieldValuesMap(uniqueStringsObj, table);
1047
- return uniqueStringsObj;
1048
- };
1049
- const fetchReportFromASTHelper = async ({ baseAst, newFormData, curPivot, curSchema, previousReport, keepPivotHint = false, }) => {
1050
- const curFormData = newFormData !== undefined ? newFormData : formData;
539
+ const fetchReportFromASTHelper = async ({ ast, pivot, previousReport, requiresNewFilteredUniqueValues = false, requiresNewUnfilteredUniqueValues = false, }) => {
1051
540
  let reportBuilderInfo = undefined;
541
+ setErrorMessage('');
542
+ const schema = filteredSchema;
1052
543
  try {
1053
- setLoading(true);
544
+ if (!client || reportBuilderLoading) {
545
+ return;
546
+ }
547
+ setReportBuilderLoading(true);
1054
548
  reportBuilderInfo = await (0, report_1.fetchReportBuilderDataFromAST)({
1055
- baseAst,
1056
- formData: curFormData,
1057
- schema: curSchema ?? schemaData.schemaWithCustomFields,
549
+ baseAst: ast,
550
+ schema,
1058
551
  client,
1059
552
  tenants,
1060
- pivot: curPivot ?? pivot,
1061
- previousFormData: formData,
1062
- currentTable,
553
+ pivot: pivot ?? undefined,
1063
554
  previousRelevant: {
1064
- uniqueStrings: uniqueValues,
555
+ uniqueStringsByTable: unfilteredUniqueValues,
1065
556
  dateRanges: dateRanges ?? {},
557
+ uniqueStringsByColumn: requiresNewFilteredUniqueValues
558
+ ? {}
559
+ : columnUniqueValues,
1066
560
  },
1067
- report: previousReport ?? reportInfo ?? undefined,
561
+ requiresNewFilteredUniqueValues,
562
+ report: previousReport,
1068
563
  customFields: schemaData.customFields,
1069
564
  skipUniqueValues: true,
1070
565
  skipRowCount: true,
1071
566
  processing: { page: REPORT_BUILDER_PAGINATION },
1072
- dashboardName,
567
+ dashboardName: destinationDashboard,
1073
568
  });
1074
569
  if (reportBuilderInfo.error) {
1075
570
  throw new Error(reportBuilderInfo.error);
@@ -1078,58 +573,41 @@ function ReportBuilder({ initialTableName = '', onSubmitEditReport = () => void
1078
573
  catch (err) {
1079
574
  if (err instanceof Error) {
1080
575
  setErrorMessage(err.message);
1081
- setLoading(false);
576
+ setReportBuilderLoading(false);
1082
577
  return { error: true, message: err.message, rows: [] };
1083
578
  }
1084
- setLoading(false);
579
+ setReportBuilderLoading(false);
1085
580
  setErrorMessage('Failed to fetch');
1086
581
  return { error: true, message: 'Failed to fetch', rows: [] };
1087
582
  }
1088
583
  if (!reportBuilderInfo) {
1089
- setLoading(false);
584
+ setReportBuilderLoading(false);
1090
585
  setErrorMessage('Failed to fetch');
1091
586
  return;
1092
587
  }
1093
588
  const cleanedReport = await (0, dashboard_1.cleanDashboardItem)({
1094
589
  item: reportBuilderInfo.report,
1095
- dashboardFilters: specificDashboardFilters,
590
+ dashboardFilters: [],
1096
591
  client,
1097
592
  customFields: schemaData.customFields,
1098
593
  skipPivotFetch: true,
1099
594
  });
595
+ // set tempReport
1100
596
  setTempReport({
1101
597
  ...cleanedReport,
1102
598
  pagination: REPORT_BUILDER_PAGINATION,
1103
599
  });
1104
- fetchRowCountFromAST(baseAst, curFormData);
1105
- const reportTable = reportBuilderInfo.table;
1106
- const reportBuilderInfoColumns = reportBuilderInfo.columns.map((column) => {
1107
- return `${reportTable}.${column.field}`;
1108
- });
1109
- const prevFormData = formData;
1110
- const prevTable = currentTable;
1111
- setRows(reportBuilderInfo.rows);
1112
- setPreviousPage(0);
1113
- if (!(client.databaseType.toLowerCase() === 'bigquery') ||
600
+ setActiveQuery(reportBuilderInfo.query);
601
+ // table data
602
+ fetchRowCountFromAST(ast, ast.where);
603
+ setReportRows(reportBuilderInfo.rows);
604
+ setFormattedRows(reportBuilderInfo.formattedRows);
605
+ resetProcessing();
606
+ if (!(client.databaseType?.toLowerCase() === 'bigquery') ||
1114
607
  (reportBuilderInfo.rows && reportBuilderInfo.rows.length > 0)) {
1115
- setColumns(reportBuilderInfo.columns);
1116
- setSelectedColumns(reportBuilderInfoColumns);
1117
- }
1118
- if (prevTable !== reportBuilderInfo.table) {
1119
- setSelectedOrderedColumns([]); // reset selected ordered columns
1120
- }
1121
- setPivot(reportBuilderInfo.pivot
1122
- ? setTypesOnPivot(reportBuilderInfo.pivot, reportBuilderInfo.columns)
1123
- : null);
1124
- if (!keepPivotHint) {
1125
- setPivotHint('');
608
+ setReportColumns(reportBuilderInfo.columns);
1126
609
  }
1127
610
  setPivotData(reportBuilderInfo.pivotData);
1128
- setDateRanges(reportBuilderInfo.dateRanges);
1129
- setFormattedRows(reportBuilderInfo.formattedRows);
1130
- setDataDisplayed(true);
1131
- setCurrentTable(reportBuilderInfo.table);
1132
- setFormData(curFormData);
1133
611
  if (reportBuilderInfo.pivot) {
1134
612
  setPivotRowField(reportBuilderInfo.pivot.rowField);
1135
613
  setPivotColumnField(reportBuilderInfo.pivot.columnField);
@@ -1138,107 +616,109 @@ function ReportBuilder({ initialTableName = '', onSubmitEditReport = () => void
1138
616
  valueField: reportBuilderInfo.pivot.valueField,
1139
617
  valueField2: reportBuilderInfo.pivot.valueField2,
1140
618
  aggregationType: reportBuilderInfo.pivot.aggregationType,
1141
- },
1142
- ]);
1143
- }
1144
- else {
1145
- setLoading(false);
1146
- }
1147
- setReportInfo(reportBuilderInfo.report);
1148
- const schema = curSchema ?? schemaData.schemaWithCustomFields;
1149
- const tableInfo = schema.find((tableInfo) => tableInfo.name === reportBuilderInfo?.table);
1150
- let query = reportBuilderInfo.query;
1151
- if (!query && tableInfo) {
1152
- const ast = baseAst ??
1153
- (0, astProcessing_1.createBasicSelectASTFromColumns)(tableInfo.columns, reportBuilderInfo.table);
1154
- const queryResult = await fetchSqlQuery({
1155
- ...ast,
1156
- where: curFormData,
1157
- }, curFormData, false);
1158
- if (queryResult.error) {
1159
- console.error(queryResult.error);
1160
- }
1161
- else {
1162
- query = queryResult;
1163
- setActiveQuery(queryResult);
1164
- }
1165
- }
1166
- else if (query) {
1167
- setActiveQuery(query);
619
+ },
620
+ ]);
1168
621
  }
622
+ setPivot(reportBuilderInfo.pivot);
623
+ setPivotHint(reportBuilderInfo.pivotHint);
624
+ setDateRanges(reportBuilderInfo.dateRanges);
625
+ const tableNames = reportBuilderInfo.tables;
626
+ const columnInfo = tableNames.flatMap((table) => {
627
+ const tableInfo = schema.find((tableInfo) => tableInfo.name === table);
628
+ if (!tableInfo) {
629
+ return [];
630
+ }
631
+ return tableInfo.columns.map((col) => ({ ...col, table }));
632
+ });
1169
633
  // fetch unique values after everything else since it is the most expensive
1170
- if (prevTable !== reportBuilderInfo.table ||
1171
- !(0, fast_deep_equal_1.default)(prevFormData, curFormData)) {
1172
- try {
1173
- setUniqueValuesIsLoading(true);
634
+ try {
635
+ let uniqueStrings = filteredUniqueValues ?? unfilteredUniqueValues;
636
+ let uniqueValuesByColumn = columnUniqueValues;
637
+ if (requiresNewUnfilteredUniqueValues) {
638
+ fetchGlobalUniqueValues(columnInfo, tableNames);
639
+ }
640
+ if (requiresNewFilteredUniqueValues) {
1174
641
  if (reportBuilderInfo.pivot) {
1175
- setUnresolvedReportMessage('Processing pivot selection options...');
1176
- }
1177
- if (!tableInfo) {
1178
- throw new Error('Table info not found');
1179
- }
1180
- const uniqueStrings = await (0, tableProcessing_1.getUniqueStringValues)(tableInfo.columns, reportBuilderInfo.table, client, tenants, schemaData.customFields, undefined, true, query, dashboardName);
1181
- const newUnique = updateUniqueValue(uniqueStrings, reportBuilderInfo.table);
1182
- let pivotChanged = false;
1183
- let newPivot;
1184
- if (reportBuilderInfo.pivot &&
1185
- !isValidPivotForReport(reportBuilderInfo.pivot, newUnique, reportBuilderInfo.table, reportBuilderInfo.columns)) {
1186
- const { pivot, hint } = makePivotValid(reportBuilderInfo.pivot, newUnique, reportBuilderInfo.table, reportBuilderInfo.columns);
1187
- if (pivot) {
1188
- setPivot(setTypesOnPivot(pivot, reportBuilderInfo.columns));
1189
- newPivot = pivot;
1190
- pivotChanged = true;
1191
- setPivotHint(hint);
1192
- }
1193
- else {
1194
- setUnresolvedReportMessage('Not a valid pivot');
1195
- }
642
+ // if there's a pivot, these values would have had to been fetched
643
+ uniqueStrings = reportBuilderInfo.uniqueStringsByTable;
644
+ uniqueValuesByColumn = reportBuilderInfo.uniqueStringsByColumn;
1196
645
  }
1197
646
  else {
1198
- setUnresolvedReportMessage('');
1199
- }
1200
- setUniqueValuesIsLoading(false);
1201
- if (pivotChanged) {
1202
- fetchReportFromASTHelper({
1203
- baseAst,
1204
- newFormData: curFormData,
1205
- curPivot: newPivot,
1206
- curSchema,
1207
- previousReport,
1208
- keepPivotHint: true,
647
+ setFilteredUniqueValuesIsLoading(true);
648
+ const starQuery = await (0, dataFetcher_1.fetchSqlQuery)((0, astProcessing_1.createSelectStarFromAst)(ast), client);
649
+ uniqueStrings = await (0, tableProcessing_1.getUniqueStringValuesByTable)({
650
+ columns: columnInfo,
651
+ tables: tableNames,
652
+ client,
653
+ tenants,
654
+ customFields: schemaData.customFields ?? undefined,
655
+ withExceededColumns: true,
656
+ dashboardName: destinationDashboard,
657
+ queryTemplate: starQuery.query,
658
+ });
659
+ uniqueValuesByColumn = {};
660
+ reportBuilderInfo.reportBuilderColumns.forEach((col) => {
661
+ uniqueValuesByColumn[col.alias || col.field] =
662
+ uniqueStrings[col.table || '']?.[col.field] ?? [];
1209
663
  });
1210
- }
1211
- else {
1212
- setLoading(false);
1213
664
  }
1214
665
  }
1215
- catch (err) {
1216
- if (err instanceof Error) {
1217
- setErrorMessage(err.message);
1218
- setLoading(false);
1219
- return { error: true, message: err.message, rows: [] };
1220
- }
1221
- setLoading(false);
1222
- setErrorMessage('Failed to fetch');
1223
- return { error: true, message: 'Failed to fetch', rows: [] };
666
+ setFilteredUniqueValues(uniqueStrings);
667
+ setFilteredUniqueValuesIsLoading(false);
668
+ setColumnUniqueValues(uniqueValuesByColumn);
669
+ setReportBuilderLoading(false);
670
+ }
671
+ catch (err) {
672
+ if (err instanceof Error) {
673
+ setErrorMessage(err.message);
674
+ setReportBuilderLoading(false);
675
+ return { error: true, message: err.message, rows: [] };
1224
676
  }
677
+ setReportBuilderLoading(false);
678
+ setErrorMessage('Failed to fetch');
679
+ return { error: true, message: 'Failed to fetch', rows: [] };
1225
680
  }
1226
- else {
1227
- setLoading(false);
681
+ };
682
+ const fetchRowCountFromAST = async (ast, where) => {
683
+ setRowCountIsLoading(true);
684
+ if (!client) {
685
+ return;
686
+ }
687
+ const tableData = await (0, tableProcessing_1.fetchTableByAST)({ ...ast, where }, client, tenants, { page: REPORT_BUILDER_PAGINATION }, schemaData.customFields, false, true, destinationDashboard);
688
+ if (tableData.rowCount) {
689
+ setNumberOfRows(tableData.rowCount);
690
+ // @ts-ignore
691
+ setTempReport((tempReport) => ({
692
+ ...tempReport,
693
+ rowCount: tableData.rowCount,
694
+ }));
1228
695
  }
696
+ setRowCountIsLoading(false);
1229
697
  };
1230
698
  const fetchAstFromPromptHelper = async (overridePrompt) => {
1231
699
  let astInfo = {};
1232
700
  const prompt = overridePrompt || aiPrompt;
701
+ if (!client) {
702
+ return;
703
+ }
1233
704
  if (!prompt) {
1234
705
  setErrorMessage('Please supply a prompt.');
1235
706
  return;
1236
707
  }
1237
708
  try {
1238
- setLoading(true);
709
+ setReportBuilderLoading(true);
1239
710
  setAskAILoading(true);
1240
711
  setErrorMessage('');
1241
- astInfo = await (0, astProcessing_1.fetchAndProcessASTFromPrompt)(prompt, schemaData.schemaWithCustomFields, client, pivot ?? undefined, activeQuery, currentTable, dashboardName, tenants);
712
+ astInfo = await (0, astProcessing_1.fetchAndProcessASTFromPrompt)({
713
+ aiPrompt: prompt,
714
+ schema: filteredSchema,
715
+ client,
716
+ prevPivot: pivot ?? undefined,
717
+ currentQuery: activeQuery,
718
+ prevTable: tables?.[0]?.name,
719
+ dashboardName: destinationDashboard,
720
+ tenants,
721
+ });
1242
722
  if (astInfo.error) {
1243
723
  throw new Error(astInfo.error);
1244
724
  }
@@ -1247,246 +727,263 @@ function ReportBuilder({ initialTableName = '', onSubmitEditReport = () => void
1247
727
  if (err instanceof Error) {
1248
728
  setErrorMessage(err.message);
1249
729
  }
1250
- setLoading(false);
730
+ setReportBuilderLoading(false);
1251
731
  setAskAILoading(false);
1252
732
  return;
1253
733
  }
1254
734
  // check if pivot works with ReportBuilder constraints
1255
- if (uniqueValues[currentTable ?? ''] &&
735
+ if (Object.keys(columnUniqueValues).length > 0 &&
1256
736
  astInfo.pivot &&
1257
- !isValidPivotForReport(astInfo.pivot)) {
737
+ !(0, reportBuilder_1.isValidPivotForReport)(astInfo.pivot, columnUniqueValues, reportColumns)) {
1258
738
  astInfo.pivot = null;
1259
739
  astInfo.ast.groupby = null;
1260
740
  }
1261
- const _tables = (0, ast_1.getTableNames)(astInfo.ast);
1262
- const _table = _tables[0] ? _tables[0] : '';
1263
- const _columns = schemaData.schemaWithCustomFields.find((table) => {
1264
- return table.name === _table;
1265
- })?.columns;
1266
- // parse the whereAst first
1267
- const filterTree = (0, astFilterProcessing_1.astToFilterTree)(astInfo.whereAST, client.databaseType?.toLowerCase(), _columns);
1268
- const cleanAst = filterTree
1269
- ? (0, astFilterProcessing_1.filterTreeToAst)(filterTree, client.databaseType?.toLowerCase())
1270
- : null;
1271
- setFormData(cleanAst);
1272
- astInfo.ast.where = cleanAst;
1273
- setBaseAst(astInfo.ast);
1274
- fetchSqlQuery(astInfo.ast, cleanAst, false);
1275
741
  setAskAILoading(false);
1276
- await fetchReportFromASTHelper({
1277
- baseAst: astInfo.ast,
1278
- newFormData: cleanAst,
1279
- curPivot: astInfo.pivot,
742
+ const newState = (0, reportBuilder_1.astToReportBuilderState)(astInfo.ast, client.databaseType || 'postgresql', filteredSchema);
743
+ handleMultiStateChange({ ...newState, pivot: astInfo.pivot }, true);
744
+ };
745
+ const fetchGlobalUniqueValues = async (columns, tables) => {
746
+ if (!client) {
747
+ return;
748
+ }
749
+ setUnfilteredUniqueValuesIsLoading(true);
750
+ const uniqueStrings = await (0, tableProcessing_1.getUniqueStringValuesByTable)({
751
+ columns,
752
+ tables,
753
+ client,
754
+ tenants,
755
+ customFields: schemaData.customFields ?? undefined,
756
+ withExceededColumns: true,
757
+ dashboardName: destinationDashboard,
1280
758
  });
759
+ setUnfilteredUniqueValues(uniqueStrings);
760
+ setUnfilteredUniqueValuesIsLoading(false);
1281
761
  };
1282
- const pivotFormData = (pivot) => {
1283
- const yAxisField = pivot.columnField ?? (0, pivotConstructor_1.disambiguatedValueField)(pivot) ?? '';
1284
- const yAxisLabel = tempReport?.yAxisFields && tempReport?.yAxisFields?.length > 0
1285
- ? (tempReport.yAxisFields[0]?.label ?? '')
1286
- : ((0, pivotConstructor_1.disambiguatedValueField)(pivot) ?? '');
1287
- // date labels for pivots should be treated like strings since they are
1288
- const yAxisIsDate = pivot.columnField
1289
- ? (0, PivotModal_1.isDateField)(pivot.columnFieldType ?? '')
1290
- : false;
1291
- const chartType = tempReport?.chartType ?? (pivot.rowField ? 'column' : 'metric');
1292
- const result = {
1293
- pivot,
1294
- chartType: chartType,
1295
- xAxisField: pivot.rowField
1296
- ? pivot.rowField
1297
- : (0, pivotConstructor_1.disambiguatedValueField)(pivot),
1298
- xAxisFormat: (0, columnProcessing_1.isDateType)(pivot.rowFieldType ?? '')
1299
- ? 'string'
1300
- : (0, columnProcessing_1.isNumberType)(pivot.rowFieldType ?? '')
1301
- ? 'whole_number'
1302
- : 'string',
1303
- xAxisLabel: tempReport?.xAxisLabel || pivot.rowField,
1304
- yAxisFields: [
1305
- {
1306
- field: yAxisField,
1307
- label: yAxisLabel,
1308
- format: yAxisIsDate
1309
- ? 'string'
1310
- : tempReport?.yAxisFields && tempReport?.yAxisFields?.length > 0
1311
- ? (tempReport?.yAxisFields[0]?.format ?? 'whole_number')
1312
- : (tempReport?.columns.find((col) => col.field === (0, pivotConstructor_1.disambiguatedValueField)(pivot))?.format ?? 'whole_number'),
1313
- },
1314
- ],
1315
- };
1316
- return result;
762
+ const resetProcessing = () => {
763
+ setCurrentProcessing({ page: REPORT_BUILDER_PAGINATION });
764
+ setPreviousPage(0);
1317
765
  };
1318
- const makePivotValid = (pivot, uniqueValuesForPivot, reportTable, reportColumns) => {
1319
- if (!pivot) {
1320
- return { pivot: null, hint: '' };
1321
- }
1322
- // try flipping row and column field
1323
- let newPivot = {
1324
- ...pivot,
1325
- rowField: pivot.columnField,
1326
- columnField: pivot.rowField,
1327
- };
1328
- if (isValidPivotForReport(newPivot, uniqueValuesForPivot, reportTable, reportColumns)) {
1329
- return {
1330
- pivot: newPivot,
1331
- hint: 'Flipping pivot row and column fields to maintain validity',
1332
- };
766
+ const handlePagination = async (processing) => {
767
+ try {
768
+ if (!client) {
769
+ return;
770
+ }
771
+ const isPivotPagination = !!(pivot && pivotData);
772
+ setErrorMessage('');
773
+ setTableLoading(true);
774
+ const tableInfo = await (0, tableProcessing_1.fetchResultsByQuery)({
775
+ query: isPivotPagination ? pivotData.pivotQuery : activeQuery,
776
+ comparisonQuery: pivot && pivotData ? pivotData.comparisonPivotQuery : undefined,
777
+ client,
778
+ tenants,
779
+ processing,
780
+ customFields: schemaData.customFields,
781
+ rowsOnly: true,
782
+ dashboardName: destinationDashboard,
783
+ pivot: pivot,
784
+ getPivotRowCount: false,
785
+ });
786
+ if (tableInfo.error) {
787
+ throw new Error(tableInfo.error);
788
+ }
789
+ else if (tableInfo.rows.length === 0) {
790
+ throw new Error('No data found');
791
+ }
792
+ if (!isPivotPagination) {
793
+ const tempRows = [...reportRows, ...tableInfo.rows];
794
+ setReportRows(tempRows);
795
+ setFormattedRows((0, report_1.formatRowsFromReport)({ rows: tempRows, columns: tableInfo.columns }));
796
+ setTempReport((tempReport) => ({
797
+ ...tempReport,
798
+ rows: tempRows,
799
+ rowCount: tableInfo.rowCount ?? tempReport.rowCount,
800
+ }));
801
+ }
802
+ else {
803
+ const tempRows = [...pivotData.rows, ...tableInfo.rows];
804
+ setPivotData((oldPivotData) => {
805
+ if (oldPivotData) {
806
+ return {
807
+ ...oldPivotData,
808
+ rows: tempRows,
809
+ columns: tableInfo.columns,
810
+ };
811
+ }
812
+ return null;
813
+ });
814
+ setFormattedRows((0, report_1.formatRowsFromReport)({ rows: tempRows, columns: tableInfo.columns }));
815
+ }
816
+ setTableLoading(false);
1333
817
  }
1334
- // try removing column field
1335
- newPivot = {
1336
- ...pivot,
1337
- rowField: pivot.rowField,
1338
- columnField: undefined,
1339
- };
1340
- if (isValidPivotForReport(newPivot, uniqueValuesForPivot, reportTable, reportColumns)) {
1341
- return {
1342
- pivot: newPivot,
1343
- hint: 'Removing column field to maintain validity',
1344
- };
818
+ catch (e) {
819
+ setTableLoading(false);
820
+ setErrorMessage('Failed to run SQL query: ' + e.message);
821
+ setReportRows([]);
822
+ setReportColumns([]);
823
+ return;
1345
824
  }
1346
- return { pivot: null, hint: '' };
1347
825
  };
1348
- const isValidPivotForReport = (pivot, uniqueValuesForPivot, reportTable, reportColumns) => {
1349
- if (!(0, pivotProcessing_1.isValidPivot)(pivot).valid) {
1350
- return false;
1351
- }
1352
- const uniqueValuesToCheck = uniqueValuesForPivot ?? uniqueValues;
1353
- // check that pivot rows and columns
1354
- const pivotTable = reportTable ?? currentTable;
1355
- const pivotColumns = reportColumns ?? columns;
1356
- const possibleOptions = (0, pivotProcessing_1.getPossiblePivotFieldOptions)(pivotColumns, uniqueValuesToCheck[pivotTable] ?? {});
1357
- if (pivot.rowField &&
1358
- pivot.columnField &&
1359
- pivot.rowField === pivot.columnField) {
1360
- return false;
826
+ const onPageChange = (page, initiator = 'ReportBuilder') => {
827
+ const pagination = initiator === 'ReportBuilder'
828
+ ? REPORT_BUILDER_PAGINATION
829
+ : paginationProcessing_1.DEFAULT_PAGINATION;
830
+ if (currentProcessing.page &&
831
+ (0, paginationProcessing_1.shouldFetchMore)(pagination, page, previousPage, pivotData ? pivotData.rows.length : reportRows.length)) {
832
+ const newPagination = { ...currentProcessing.page, page };
833
+ const updatedProcessing = { ...currentProcessing, page: newPagination };
834
+ setCurrentProcessing(updatedProcessing);
835
+ handlePagination(updatedProcessing);
1361
836
  }
1362
- if (pivot.rowField && !possibleOptions.rowFields.includes(pivot.rowField)) {
1363
- return false;
837
+ if (page > previousPage) {
838
+ setPreviousPage(page);
1364
839
  }
1365
- if (pivot.columnField &&
1366
- !possibleOptions.columnFields.includes(pivot.columnField)) {
1367
- return false;
840
+ };
841
+ const onSortChange = (newSort, isDelete) => {
842
+ if (!newSort.field) {
843
+ return;
1368
844
  }
1369
- for (const agg of pivot.aggregations ?? []) {
1370
- if (agg.valueField &&
1371
- !possibleOptions.valueFields.includes(agg.valueField)) {
1372
- return false;
845
+ if (pivot) {
846
+ let newPivot = null;
847
+ if (isDelete) {
848
+ newPivot = {
849
+ ...pivot,
850
+ sort: undefined,
851
+ sortField: undefined,
852
+ sortDirection: undefined,
853
+ sortFieldType: undefined,
854
+ };
855
+ }
856
+ else {
857
+ newPivot = {
858
+ ...pivot,
859
+ sort: true,
860
+ sortField: newSort.field,
861
+ sortDirection: newSort.direction,
862
+ sortFieldType: reportColumns.find((col) => col.field === newSort.field)?.fieldType,
863
+ };
1373
864
  }
865
+ handlePivotChange(newPivot, true);
1374
866
  }
1375
- if (!pivot.aggregations || pivot.aggregations.length === 0) {
1376
- return false;
867
+ else {
868
+ const updatedSort = [...sort];
869
+ const existingSortIndex = updatedSort.findIndex((item) => item.field === newSort.field);
870
+ if (isDelete) {
871
+ if (existingSortIndex !== -1) {
872
+ updatedSort.splice(existingSortIndex, 1);
873
+ }
874
+ }
875
+ else if (existingSortIndex !== -1) {
876
+ updatedSort[existingSortIndex] = {
877
+ field: newSort.field,
878
+ direction: newSort.direction,
879
+ };
880
+ }
881
+ else {
882
+ updatedSort.push({
883
+ field: newSort.field,
884
+ direction: newSort.direction,
885
+ });
886
+ }
887
+ handleSortChange(updatedSort, true);
1377
888
  }
1378
- return true;
1379
889
  };
1380
- const handleDeleteColumn = (name) => {
1381
- if (!baseAst || !baseAst.columns.length || selectedColumns.length === 1) {
1382
- clearAllState();
1383
- return;
890
+ const onLimitChange = (limit) => {
891
+ if (limit) {
892
+ if (pivot) {
893
+ const newPivot = { ...pivot, rowLimit: limit };
894
+ handlePivotChange(newPivot, true);
895
+ }
896
+ else {
897
+ handleLimitChange({ value: limit }, true);
898
+ }
1384
899
  }
1385
- setSelectedColumns((selectedColumns) => selectedColumns.filter((column) => !column.endsWith(name)));
1386
- const columns = baseAst.columns.filter((col) => {
1387
- if (col.expr.type === 'column_ref') {
1388
- return (col.expr.column !== name &&
1389
- (!col.expr.column.expr || col.expr.column.expr.value !== name));
900
+ else {
901
+ if (pivot) {
902
+ const newPivot = { ...pivot, rowLimit: undefined };
903
+ handlePivotChange(newPivot, true);
1390
904
  }
1391
- else if (col.as) {
1392
- return col.as !== name;
905
+ else {
906
+ handleLimitChange(null, true);
1393
907
  }
1394
- return col.expr.value !== name;
1395
- });
1396
- if (columns.length === 0) {
1397
- clearAllState();
1398
- return;
1399
908
  }
1400
- const newAst = (0, util_1.deepCopy)({ ...baseAst, columns });
1401
- setBaseAst(newAst);
1402
- fetchSqlQuery(newAst);
1403
909
  };
1404
- const DraggableItem = ({ id, label, onDelete }) => {
1405
- const { attributes, listeners, setNodeRef, transform, transition } = (0, sortable_1.useSortable)({ id: id });
1406
- const style = {
1407
- transform: utilities_1.CSS.Transform.toString(transform),
1408
- transition,
910
+ (0, react_1.useEffect)(() => {
911
+ // Since the TextInput component takes a required numeric width parameter,
912
+ // we dynamically calculate the width of this component here.
913
+ function handleResize() {
914
+ (0, width_1.updateFirstChildWidth)(askAIContainerRef, setAskAIInputWidth, { gap: 12 });
915
+ }
916
+ handleResize();
917
+ window.addEventListener('resize', handleResize);
918
+ return () => {
919
+ window.removeEventListener('resize', handleResize);
1409
920
  };
1410
- return ((0, jsx_runtime_1.jsx)("div", { style: { ...style }, ref: setNodeRef, children: (0, jsx_runtime_1.jsx)(DraggableColumnComponent, { label: (0, textProcessing_1.snakeAndCamelCaseToTitleCase)(label), onDelete: onDelete, DragHandle: (props) => ((0, jsx_runtime_1.jsx)("div", { style: {
1411
- cursor: 'grab',
1412
- }, ...attributes, ...listeners, children: (0, jsx_runtime_1.jsx)(props.dragIcon, {}) })), deleteDisabled: loading || tableLoading }) }));
1413
- };
1414
- function DraggableColumns() {
1415
- const sensors = (0, core_1.useSensors)((0, core_1.useSensor)(core_1.PointerSensor), (0, core_1.useSensor)(core_1.KeyboardSensor, {
1416
- coordinateGetter: sortable_1.sortableKeyboardCoordinates,
1417
- }));
1418
- // When a drag event ends, switch the item order.
1419
- function handleDragEnd(event) {
1420
- const { active, over } = event;
1421
- if (!active || !over)
921
+ }, []);
922
+ (0, react_1.useEffect)(() => {
923
+ if (!client) {
924
+ return;
925
+ }
926
+ if (client.featureFlags?.['recommendedPivotsDisabled'] !== undefined) {
927
+ setPivotRecommendationsEnabledState(!client.featureFlags?.['recommendedPivotsDisabled']);
928
+ }
929
+ if (!initialTableName && !reportId && client.publicKey) {
930
+ clearAllState();
931
+ }
932
+ }, [client]);
933
+ // Initialize ReportBuilder with a report
934
+ (0, react_1.useEffect)(() => {
935
+ const loadChart = async () => {
936
+ let report;
937
+ if (!client) {
1422
938
  return;
1423
- if (active.id !== over.id) {
1424
- const oldIndex = orderedColumnNames.findIndex((c) => c.endsWith(`${currentTable}.${active.id}`));
1425
- const newIndex = orderedColumnNames.findIndex((c) => c.endsWith(`${currentTable}.${over.id}`));
1426
- const newOrder = (0, sortable_1.arrayMove)(orderedColumnNames, oldIndex, newIndex);
1427
- setOrderedColumnNames(newOrder);
1428
- const orderedSelectedColumns = [];
1429
- for (const value of newOrder) {
1430
- const [, ...rest] = value.split('.'); // table.field
1431
- const column = rest.join('.');
1432
- if (selectedColumns.includes(value)) {
1433
- orderedSelectedColumns.push(column);
1434
- }
1435
- }
1436
- setSelectedOrderedColumns(orderedSelectedColumns);
1437
- // If there is already an AST saved in state, only update the columns
1438
- // otherwise fill in the defaultAST shape and also update columns.
1439
- const fallbackAST = {
1440
- ...constants_1.defaultAST,
1441
- from: [{ ...constants_1.defaultTable }],
1442
- columns: orderedSelectedColumns.map((name) => nameToColumn(name)),
1443
- };
1444
- const newBaseAst = {
1445
- ...baseAst,
1446
- columns: baseAst?.columns.length
1447
- ? orderedSelectedColumns.map((name) => nameToColumn(name))
1448
- : baseAst?.columns,
1449
- };
1450
- const newAst = baseAst ? newBaseAst : fallbackAST;
1451
- setBaseAst(newAst);
1452
- fetchSqlQuery(newAst, undefined, false);
1453
939
  }
1454
- }
1455
- const columnNamesInAst = baseAst?.columns
1456
- .map((col) => {
1457
- if (col.expr.type === 'column_ref' && col.expr.column) {
1458
- if (typeof col.expr.column === 'string') {
1459
- return col.expr.column;
940
+ try {
941
+ if (!reportId) {
942
+ throw new Error('Report ID is required');
1460
943
  }
1461
- else {
1462
- return col.expr.column.expr.value;
944
+ report = dashboard[reportId];
945
+ if (!report) {
946
+ throw new Error('Report not found');
1463
947
  }
948
+ const { ast: newAst, pivot: newPivot } = await (0, astProcessing_1.fetchASTFromQuillReport)(report, client, filteredSchema);
949
+ const initialState = (0, reportBuilder_1.astToReportBuilderState)(newAst, client.databaseType || 'postgresql', filteredSchema);
950
+ setTempReport(report);
951
+ handleMultiStateChange({
952
+ ...initialState,
953
+ pivot: newPivot ?? null,
954
+ }, true);
1464
955
  }
1465
- else if (col.as) {
1466
- if (typeof col.as === 'string') {
1467
- return col.as;
1468
- }
1469
- else {
1470
- return col.as.expr?.value;
1471
- }
956
+ catch (err) {
957
+ console.error(err);
958
+ setErrorMessage('Error when loading chart');
1472
959
  }
1473
- else if (col.expr && col.expr.type === 'aggr_func') {
1474
- if (col.expr.args) {
1475
- return `${col.expr.name.toLowerCase()}(${col.expr.args.expr.value})`;
1476
- }
1477
- return col.expr.name;
960
+ };
961
+ if (reportId && client) {
962
+ loadChart();
963
+ }
964
+ }, [dashboard[reportId || ''], client]);
965
+ (0, react_1.useEffect)(() => {
966
+ if (initialTableName) {
967
+ const tableColumns = filteredSchema.find((table) => {
968
+ return table.name === initialTableName;
969
+ })?.columns ?? [];
970
+ if (tableColumns.length > 0) {
971
+ handleMultiStateChange({
972
+ ...ReportBuilder_1.EMPTY_REPORT_BUILDER_STATE,
973
+ tables: [{ name: initialTableName }],
974
+ columns: tableColumns.map((col) => ({
975
+ field: col.field,
976
+ table: initialTableName,
977
+ })),
978
+ }, true);
1478
979
  }
1479
- return col.expr.value;
1480
- })
1481
- .filter(
1482
- // remove duplicate entries
1483
- (value, index, self) => value && self.indexOf(value) === index) ?? [];
1484
- return ((0, jsx_runtime_1.jsx)(core_1.DndContext, { sensors: sensors, collisionDetection: core_1.closestCenter, onDragEnd: handleDragEnd, children: (0, jsx_runtime_1.jsx)(sortable_1.SortableContext, { items: columnNamesInAst, strategy: sortable_1.verticalListSortingStrategy, children: (0, jsx_runtime_1.jsxs)("div", { style: {
1485
- display: 'flex',
1486
- flexDirection: 'column',
1487
- gap: 8,
1488
- }, children: [columnNamesInAst.map((name) => ((0, jsx_runtime_1.jsx)(DraggableItem, { id: name, label: name, onDelete: () => !loading && handleDeleteColumn(name) }, name))), columnNamesInAst?.length > 0 && (0, jsx_runtime_1.jsx)("div", { style: { height: 6 } })] }) }) }));
1489
- }
980
+ }
981
+ }, [filteredSchema, initialTableName]);
982
+ (0, react_1.useEffect)(() => {
983
+ if (isChartBuilderOpen === false) {
984
+ onCloseChartBuilder && onCloseChartBuilder();
985
+ }
986
+ }, [isChartBuilderOpen]);
1490
987
  return ((0, jsx_runtime_1.jsxs)("div", { style: { backgroundColor: theme?.backgroundColor, ...containerStyle }, className: className, children: [(!isChartBuilderHorizontalView ||
1491
988
  (isChartBuilderHorizontalView && !isChartBuilderOpen)) && ((0, jsx_runtime_1.jsxs)("div", { ref: parentRef, style: {
1492
989
  display: 'flex',
@@ -1495,72 +992,37 @@ function ReportBuilder({ initialTableName = '', onSubmitEditReport = () => void
1495
992
  overflowY: 'auto',
1496
993
  boxSizing: 'border-box',
1497
994
  ...containerStyle,
1498
- }, className: className, children: [(0, jsx_runtime_1.jsxs)(SidebarComponent, { children: [(0, jsx_runtime_1.jsxs)("div", { style: { width: '100%' }, children: [(0, jsx_runtime_1.jsx)(SidebarHeadingComponent, { label: "Columns" }), (0, jsx_runtime_1.jsx)(DraggableColumns, {}), (0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { onClick: () => {
1499
- if (!orderedColumnNames) {
1500
- return;
1501
- }
995
+ }, className: className, children: [(0, jsx_runtime_1.jsxs)(SidebarComponent, { children: [(0, jsx_runtime_1.jsxs)("div", { style: { width: '100%' }, children: [(0, jsx_runtime_1.jsx)(SidebarHeadingComponent, { label: "Columns" }), (0, jsx_runtime_1.jsx)(DraggableColumns_1.default, { columns: columns, DraggableColumnComponent: DraggableColumnComponent, onColumnOrderChange: handleColumnsChange, loading: loading }), (0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { onClick: () => {
1502
996
  if (!openPopover) {
1503
997
  setOpenPopover('AddColumnModal');
1504
998
  }
1505
- }, label: "Select columns", disabled: tableLoading || loading }), (0, jsx_runtime_1.jsx)(ModalComponent, { isOpen: openPopover === 'AddColumnModal', setIsOpen: (isOpen) => {
999
+ }, label: "Select columns", disabled: loading }), (0, jsx_runtime_1.jsx)(ModalComponent, { isOpen: openPopover === 'AddColumnModal', setIsOpen: (isOpen) => {
1506
1000
  if (!isOpen) {
1507
1001
  // delay onClose callback so onClick no-ops
1508
1002
  setTimeout(() => {
1509
- setActiveEditItem(null);
1510
1003
  setOpenPopover(null);
1511
1004
  }, 100);
1512
1005
  }
1513
- }, title: "Select columns", children: (0, jsx_runtime_1.jsx)(AddColumnModal_1.default, { onSave: () => {
1514
- setActiveEditItem(null);
1006
+ }, title: "Select columns", children: (0, jsx_runtime_1.jsx)(AddColumnModal_1.default, { onSave: (tables, columns) => {
1007
+ handleMultiStateChange({
1008
+ ...ReportBuilder_1.EMPTY_REPORT_BUILDER_STATE,
1009
+ tables,
1010
+ columns,
1011
+ }, true);
1515
1012
  setOpenPopover(null);
1516
- }, orderedColumnNames: orderedColumnNames, setOrderedColumnNames: setOrderedColumnNames, selectedColumns: selectedColumns, setSelectedColumns: setSelectedColumns, isSelectedAllColumns: isSelectedAllColumns, clearAllState: clearAllState, nameToColumn: nameToColumn, baseAst: baseAst, setBaseAst: (ast) => {
1517
- if (baseAst &&
1518
- ast?.from?.[0]?.table !== baseAst?.from?.[0]?.table) {
1519
- // table changed, past presets no longer valid
1520
- setFormData(null);
1521
- setRecommendedPivots([]);
1522
- setCreatedPivots([]);
1523
- ast.where = null;
1524
- ast.orderby = null;
1525
- ast.limit = null;
1526
- ast.top = null;
1527
- setBaseAst(ast);
1528
- fetchSqlQuery(ast, null);
1529
- }
1530
- else {
1531
- setBaseAst(ast);
1532
- fetchSqlQuery(ast);
1533
- }
1534
- }, pivot: pivot, initialTableName: initialTableName, defaultAST: constants_1.defaultAST, defaultTable: constants_1.defaultTable, schemaLoading: schemaData.isSchemaLoading, setPivot: setPivot, TextInputComponent: TextInputComponent, SelectColumn: SelectColumnComponent, SecondaryButton: SecondaryButtonComponent, Button: ButtonComponent, ColumnSearchEmptyState: ColumnSearchEmptyState, LoadingComponent: LoadingComponent }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: { width: '100%' }, children: [(0, jsx_runtime_1.jsx)(SidebarHeadingComponent, { label: "Filters" }), formData && ((0, jsx_runtime_1.jsx)("div", { style: {
1013
+ },
1014
+ // selectedTables={tables} // Bring back after select table join UI
1015
+ selectedColumns: columns, schema: filteredSchema, schemaLoading: schemaData.isSchemaLoading, TextInputComponent: TextInputComponent, SelectColumn: SelectColumnComponent, SecondaryButton: SecondaryButtonComponent, Button: ButtonComponent, ColumnSearchEmptyState: ColumnSearchEmptyState, LoadingComponent: LoadingComponent }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: { width: '100%' }, children: [(0, jsx_runtime_1.jsx)(SidebarHeadingComponent, { label: "Filters" }), filterStack.length > 0 && ((0, jsx_runtime_1.jsx)("div", { style: {
1535
1016
  display: 'flex',
1536
1017
  flexDirection: 'column',
1537
1018
  gap: 8,
1538
1019
  marginBottom: 12,
1539
- }, children: (0, jsx_runtime_1.jsx)(FilterStack_1.default, { client: client, filterStack: filterStack, filterTree: filterTree, defaultAST: constants_1.defaultAST, baseAst: baseAst, setBaseAst: setBaseAst, setFormData: setFormData, fetchSqlQuery: fetchSqlQuery, schemaData: schemaData, defaultColumn: constants_1.defaultColumn, defaultTable: constants_1.defaultTable, currentTable: currentTable, initialTableName: initialTableName, globalUniqueValues: globalUniqueValues, globalUniqueValuesIsLoading: globalUniqueValuesIsLoading, columns: columns, removingFilter: removingFilter, setRemovingFilter: setRemovingFilter, TabsComponent: TabsComponent, FilterPopoverComponent: FilterPopoverComponent, FilterModal: FilterModal_1.default, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, MultiSelectComponent: MultiSelectComponent, actionsEnabled: !tableLoading && !loading, dashboardName: dashboardName }) })), (0, jsx_runtime_1.jsxs)("div", { style: {
1020
+ }, children: (0, jsx_runtime_1.jsx)(FilterStack_1.default, { client: client, filterStack: filterStack, handleFilterStackChange: handleFilterStackChange, schemaData: schemaData, uniqueValues: unfilteredUniqueValues, uniqueValuesIsLoading: unfilteredUniqueValuesIsLoading, tables: tables, TabsComponent: TabsComponent, FilterPopoverComponent: FilterPopoverComponent, FilterModal: FilterModal_1.default, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, MultiSelectComponent: MultiSelectComponent, actionsEnabled: !loading, dashboardName: destinationDashboard }) })), (0, jsx_runtime_1.jsxs)("div", { style: {
1540
1021
  display: 'flex',
1541
1022
  flexDirection: 'column',
1542
1023
  alignItems: 'flex-start',
1543
- }, children: [(0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { disabled: !baseAst || !dataDisplayed || loading || tableLoading, onClick: () => {
1544
- if (!selectedColumns ||
1545
- selectedColumns.length === 0 ||
1546
- loading) {
1547
- return;
1548
- }
1024
+ }, children: [(0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { disabled: columns.length === 0 || loading, onClick: () => {
1549
1025
  if (!openPopover) {
1550
- const value = orderedColumnNames[0];
1551
- const [, ...rest] = value.split('.'); // table.field
1552
- const column = rest.join('.');
1553
- const columnType = getColumnTypeByName(column);
1554
- if ((0, ast_1.isNumericColumnType)(columnType)) {
1555
- const newSubtree = (0, util_1.deepCopy)(constants_1.defaultNumericComparison);
1556
- newSubtree.left.column = column;
1557
- setActiveEditItem(newSubtree);
1558
- }
1559
- else {
1560
- const newSubtree = (0, util_1.deepCopy)(constants_1.defaultEntry);
1561
- newSubtree.left.args.value[0].column = column;
1562
- setActiveEditItem(newSubtree);
1563
- }
1564
1026
  setOpenPopover('AddFilterPopover');
1565
1027
  }
1566
1028
  }, label: 'Add filter' }), (0, jsx_runtime_1.jsx)("div", { style: {
@@ -1568,134 +1030,56 @@ function ReportBuilder({ initialTableName = '', onSubmitEditReport = () => void
1568
1030
  ...(openPopover === 'AddFilterPopover' && { top: 12 }),
1569
1031
  }, children: (0, jsx_runtime_1.jsx)(PopoverComponent, { isOpen: openPopover === 'AddFilterPopover', setIsOpen: (isOpen) => {
1570
1032
  if (!isOpen) {
1571
- // delay onClose callback so onClick no-ops
1572
1033
  setOpenPopover(null);
1573
- setTimeout(() => {
1574
- clearCheckboxes();
1575
- setActiveEditItem(null);
1576
- }, 300);
1577
1034
  }
1578
- }, popoverTitle: "Add filter", popoverChildren: (0, jsx_runtime_1.jsx)(FilterModal_1.default, { schema: schemaData.schemaWithCustomFields.find((s) => s.name === currentTable ||
1579
- s.displayName === currentTable) ?? schemaData.schemaWithCustomFields[0], fieldValuesMap: fieldValuesMap, fieldValuesMapIsLoading: uniqueValuesIsLoading, onSubmitFilter: (filter) => {
1035
+ }, popoverTitle: "Add filter", popoverChildren: (0, jsx_runtime_1.jsx)(FilterModal_1.default, { schema: filteredSchema, tables: tables.map((table) => table.name), fieldValuesMap: filteredUniqueValues ?? unfilteredUniqueValues, fieldValuesMapIsLoading: filteredUniqueValuesIsLoading ||
1036
+ unfilteredUniqueValuesIsLoading, onSubmitFilter: (filter) => {
1580
1037
  setOpenPopover(null);
1581
- handleInsertion(filter);
1582
- }, onDeleteFilter: () => { }, ButtonComponent: ButtonComponent, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, MultiSelectComponent: MultiSelectComponent }) }) })] })] }), (0, jsx_runtime_1.jsxs)("div", { style: { width: '100%' }, children: [(0, jsx_runtime_1.jsx)(SidebarHeadingComponent, { label: "Pivot" }), (0, jsx_runtime_1.jsx)(PivotModal_1.PivotModal, { pivotRowField: pivotRowField, setPivotRowField: setPivotRowField, pivotColumnField: pivotColumnField, setPivotColumnField: setPivotColumnField, pivotAggregations: pivotAggregations, setPivotAggregations: setPivotAggregations, createdPivots: createdPivots, setCreatedPivots: setCreatedPivots, recommendedPivots: recommendedPivots, setRecommendedPivots: setRecommendedPivots, popUpTitle: pivotPopUpTitle, setPopUpTitle: setPivotPopUpTitle, selectedTable: initialTableName, SubheaderComponent: SubHeaderComponent, DeleteButtonComponent: DeleteButtonComponent, 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: () => {
1583
- setPivot(null);
1584
- setPivotHint('');
1585
- setPivotData(null);
1586
- resetLimit();
1587
- resetSort(true);
1588
- setPreviousPage(0);
1589
- const formattedRows = formatRows(rows, columns, false);
1590
- setFormattedRows(formattedRows);
1591
- }, selectPivot: async (selectedPivot, uniqueValues, dateRange, pivotTable) => {
1038
+ handleFilterInsertion(filter);
1039
+ }, hideTableName: tables.length === 1, onDeleteFilter: () => { }, ButtonComponent: ButtonComponent, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, MultiSelectComponent: MultiSelectComponent }) }) })] })] }), (0, jsx_runtime_1.jsxs)("div", { style: { width: '100%' }, children: [(0, jsx_runtime_1.jsx)(SidebarHeadingComponent, { label: "Pivot" }), (0, jsx_runtime_1.jsx)(PivotModal_1.PivotModal, { pivotRowField: pivotRowField, setPivotRowField: setPivotRowField, pivotColumnField: pivotColumnField, setPivotColumnField: setPivotColumnField, pivotAggregations: pivotAggregations, setPivotAggregations: setPivotAggregations, createdPivots: createdPivots, setCreatedPivots: setCreatedPivots, recommendedPivots: recommendedPivots, setRecommendedPivots: setRecommendedPivots, popUpTitle: pivotPopUpTitle, setPopUpTitle: setPivotPopUpTitle, selectedTable: initialTableName, SubheaderComponent: SubHeaderComponent, DeleteButtonComponent: DeleteButtonComponent, 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: reportRows, columns: reportColumnsToStateColumns, triggerButtonText: 'Add pivot', selectedPivotIndex: selectedPivotIndex, setSelectedPivotIndex: setSelectedPivotIndex, removePivot: () => {
1040
+ handlePivotChange(null, sortOrLimitWasReset);
1041
+ }, selectPivot: async (selectedPivot) => {
1592
1042
  if (!selectedPivot)
1593
1043
  return;
1594
- // const newAst = { ...baseAst };
1595
- // newAst.orderby = null;
1596
- if (selectedPivot.rowFieldType === 'date') {
1597
- selectedPivot['sort'] = true;
1598
- selectedPivot['sortDirection'] = 'ASC';
1599
- }
1600
- // setBaseAst(newAst); // trigger refetch
1601
- let dateBucket = undefined;
1602
- if (dateRange) {
1603
- dateBucket = (0, dates_1.getDateBucketFromRange)(dateRange);
1604
- }
1605
- const processedPivot = setTypesOnPivot(selectedPivot, columns);
1606
- setPivot(processedPivot);
1607
- resetLimit();
1608
- resetSort();
1609
- setPreviousPage(0);
1610
- setPivotHint('');
1611
- try {
1612
- if (!pivotTable) {
1613
- setTableLoading(true);
1614
- pivotTable = await (0, PivotModal_1.generatePivotTable)({
1615
- pivot: processedPivot,
1616
- dateBucket,
1617
- report: tempReport,
1618
- client,
1619
- uniqueValues,
1620
- dashboardName,
1621
- tenants,
1622
- additionalProcessing: {
1623
- page: REPORT_BUILDER_PAGINATION,
1624
- },
1625
- });
1626
- }
1627
- resetProcessing();
1628
- setPivotData(pivotTable || []);
1629
- setTempReport({
1630
- ...tempReport,
1631
- ...pivotFormData(processedPivot),
1632
- });
1633
- const formattedRows = formatRows(pivotTable.rows, columns, true, selectedPivot.aggregationType, dateBucket);
1634
- setFormattedRows(formattedRows);
1635
- setErrorMessage('');
1636
- setPivotError(undefined);
1637
- }
1638
- catch (e) {
1639
- if (e instanceof Error)
1640
- setPivotError(e.message);
1641
- }
1642
- finally {
1643
- setTableLoading(false);
1644
- }
1645
- }, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent: LabelComponent, HeaderComponent: HeaderComponent, dateRange: undefined, pivotCountRequest: 4, query: activeQuery, initialUniqueValues: uniqueValues[currentTable], uniqueValuesIsLoading: uniqueValuesIsLoading, disabled: !baseAst || !dataDisplayed || tableLoading || loading, pivotRecommendationsEnabled: pivotRecommendationsEnabledState, report: tempReport, dashboardName: dashboardName }), pivot && ((0, jsx_runtime_1.jsx)(PivotForm_1.default, { columns: columns, uniqueValues: uniqueValues[currentTable], uniqueValuesIsLoading: uniqueValuesIsLoading, setPivotRowField: (value) => {
1646
- const prev = pivotRowField;
1044
+ handlePivotChange(selectedPivot, true);
1045
+ }, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent: LabelComponent, HeaderComponent: HeaderComponent, dateRange: undefined, pivotCountRequest: 4, query: activeQuery, initialUniqueValues: columnUniqueValues, uniqueValuesIsLoading: filteredUniqueValuesIsLoading ||
1046
+ unfilteredUniqueValuesIsLoading, disabled: !columns.length || tableLoading || loading, pivotRecommendationsEnabled: pivotRecommendationsEnabledState, report: tempReport, dashboardName: destinationDashboard }), pivot && ((0, jsx_runtime_1.jsx)(PivotForm_1.default, { columns: reportColumnsToStateColumns, uniqueValues: columnUniqueValues, uniqueValuesIsLoading: filteredUniqueValuesIsLoading ||
1047
+ unfilteredUniqueValuesIsLoading, setPivotRowField: (value) => {
1647
1048
  setPivotRowField(value);
1648
- updatePivot(value, 'rowField', prev);
1049
+ updatePivot(value, 'rowField');
1649
1050
  }, setPivotColumnField: (value) => {
1650
- const prev = pivotColumnField;
1651
1051
  setPivotColumnField(value);
1652
- updatePivot(value, 'columnField', prev);
1052
+ updatePivot(value, 'columnField');
1653
1053
  }, setPivotAggregations: (value) => {
1654
- const prev = pivotAggregations;
1655
1054
  setPivotAggregations(value);
1656
- updatePivot(value, 'aggregations', prev);
1055
+ updatePivot(value, 'aggregations');
1657
1056
  }, onDelete: () => {
1658
- setPivot(null);
1659
- setPivotError(undefined);
1660
- setPivotHint('');
1661
- setPivotData(null);
1662
- resetLimit();
1663
- resetSort();
1664
- setPreviousPage(0);
1665
- const formattedRows = formatRows(rows, columns, false);
1666
- setFormattedRows(formattedRows);
1057
+ handlePivotChange(null, sortOrLimitWasReset);
1667
1058
  }, isLoading: tableLoading || loading, pivotRowField: pivotRowField, pivotColumnField: pivotColumnField, pivotAggregations: pivotAggregations, SecondaryButtonComponent: SecondaryButtonComponent, SelectComponent: SelectComponent, PivotColumnContainer: PivotColumnContainer, DeleteButtonComponent: DeleteButtonComponent, pivotHint: pivotHint }))] }), (0, jsx_runtime_1.jsxs)("div", { style: { width: '100%' }, children: [(0, jsx_runtime_1.jsx)(SidebarHeadingComponent, { label: "Sort" }), pivot && pivot.sort && pivot.sortField && ((0, jsx_runtime_1.jsx)("div", { style: {
1668
1059
  display: 'flex',
1669
1060
  flexDirection: 'column',
1670
1061
  gap: 8,
1671
1062
  marginBottom: 12,
1672
- }, children: (0, jsx_runtime_1.jsx)(AddSortPopover_1.SortSentence, { sortField: pivot.sortField, sortDirection: pivot.sortDirection || 'ASC', columns: pivotData?.columns ?? [], setIsPending: () => { }, setEditPopoverKey: () => { }, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover: SortPopoverComponent, EditPopover: AddSortPopover_1.AddSortPopover, handleDelete: async () => {
1063
+ }, children: (0, jsx_runtime_1.jsx)(AddSortPopover_1.SortSentence, { sortField: pivot.sortField, sortDirection: pivot.sortDirection || 'ASC', columns: pivotData?.columns ?? [], setOpenPopover: setOpenPopover, SortPopover: SortPopoverComponent, EditPopover: AddSortPopover_1.AddSortPopover, handleDelete: async () => {
1673
1064
  onSortChange({
1674
1065
  field: pivot.sortField ?? '',
1675
1066
  direction: pivot.sortDirection ?? 'ASC',
1676
1067
  }, true);
1677
1068
  }, onSave: async (column, direction) => {
1678
1069
  onSortChange({ field: column, direction });
1679
- }, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, disabled: tableLoading || loading }, `sort-sentence-pivot`) })), baseAst && baseAst.orderby && baseAst.orderby.length > 0 && ((0, jsx_runtime_1.jsx)("div", { style: {
1070
+ }, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, disabled: tableLoading || loading }, `sort-sentence-pivot`) })), sort && sort.length > 0 && ((0, jsx_runtime_1.jsx)("div", { style: {
1680
1071
  display: 'flex',
1681
1072
  flexDirection: 'column',
1682
1073
  gap: 8,
1683
1074
  marginBottom: 12,
1684
- }, children: baseAst.orderby.map((sortData, id) => ((0, jsx_runtime_1.jsx)(AddSortPopover_1.SortSentence, { sortField: sortData.expr?.column || sortData.expr?.value, sortDirection: sortData.type, columns: columns, setIsPending: () => { }, setEditPopoverKey: () => { }, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover: SortPopoverComponent, EditPopover: AddSortPopover_1.AddSortPopover, handleDelete: () => {
1685
- onSortChange({
1686
- field: sortData.expr?.column || sortData.expr?.value,
1687
- direction: sortData.type,
1688
- }, true);
1075
+ }, children: sort.map((sortData, id) => ((0, jsx_runtime_1.jsx)(AddSortPopover_1.SortSentence, { sortField: sortData.field, sortDirection: sortData.direction, columns: reportColumnsToStateColumns, setOpenPopover: setOpenPopover, SortPopover: SortPopoverComponent, EditPopover: AddSortPopover_1.AddSortPopover, handleDelete: () => {
1076
+ onSortChange(sortData, true);
1689
1077
  }, onSave: (column, direction) => {
1690
1078
  onSortChange({ field: column, direction });
1691
- }, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, disabled: tableLoading || loading }, `sort-sentence-${id}`))) })), (0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { disabled: !baseAst ||
1692
- !dataDisplayed ||
1079
+ }, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, disabled: tableLoading || loading }, `sort-sentence-${id}`))) })), (0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { disabled: columns.length === 0 ||
1693
1080
  loading ||
1694
1081
  tableLoading ||
1695
- mssqlSortWarning, onClick: () => {
1696
- if (!selectedColumns || selectedColumns.length === 0) {
1697
- return;
1698
- }
1082
+ !!mssqlSortWarning, onClick: () => {
1699
1083
  if (!openPopover) {
1700
1084
  setOpenPopover('AddSortPopover');
1701
1085
  }
@@ -1704,103 +1088,25 @@ function ReportBuilder({ initialTableName = '', onSubmitEditReport = () => void
1704
1088
  ...(openPopover === 'AddSortPopover' && { top: 12 }),
1705
1089
  }, children: (0, jsx_runtime_1.jsx)(PopoverComponent, { isOpen: openPopover === 'AddSortPopover', setIsOpen: (isOpen) => {
1706
1090
  if (!isOpen) {
1707
- setActiveEditItem(null);
1708
1091
  setOpenPopover(null);
1709
1092
  }
1710
- }, popoverTitle: "Sort by", popoverChildren: (0, jsx_runtime_1.jsx)(AddSortPopover_1.AddSortPopover, { columns: pivotData ? pivotData.columns : columns, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, onSave: async (column, direction) => {
1711
- if (column === '')
1712
- return;
1713
- if (pivot) {
1714
- const sortFieldType = pivot.aggregations?.some((agg) => column === agg.valueField || column === 'count')
1715
- ? 'number'
1716
- : pivot.rowFieldType;
1717
- const tempPivot = setTypesOnPivot({
1718
- ...pivot,
1719
- sort: true,
1720
- sortDirection: direction,
1721
- sortField: column,
1722
- sortFieldType: sortFieldType,
1723
- }, columns);
1724
- setPivot(tempPivot);
1725
- setPivotHint('');
1726
- let dateBucket = undefined;
1727
- const tempDateRange = dateRanges &&
1728
- pivot.rowField &&
1729
- dateRanges[pivot.rowField];
1730
- if (tempDateRange) {
1731
- dateBucket = (0, dates_1.getDateBucketFromRange)(tempDateRange.dateRange);
1732
- }
1733
- try {
1734
- const pivotedData = await (0, PivotModal_1.generatePivotTable)({
1735
- pivot: tempPivot,
1736
- dateBucket,
1737
- report: tempReport,
1738
- client,
1739
- uniqueValues: uniqueValues[currentTable],
1740
- dashboardName,
1741
- tenants,
1742
- additionalProcessing: {
1743
- page: REPORT_BUILDER_PAGINATION,
1744
- },
1745
- });
1746
- resetProcessing();
1747
- setErrorMessage('');
1748
- setPivotData(pivotedData || []);
1749
- const formattedRows = formatRows(pivotedData.rows, columns, true, pivot.aggregationType, dateBucket);
1750
- setFormattedRows(formattedRows);
1751
- }
1752
- catch (e) {
1753
- if (e instanceof Error)
1754
- setPivotError(e.message);
1755
- }
1756
- setOpenPopover(null);
1757
- setBaseAst((0, util_1.deepCopy)(baseAst));
1758
- return;
1759
- }
1760
- else {
1761
- const newAst = { ...baseAst };
1762
- if (!newAst.orderby)
1763
- newAst.orderby = [];
1764
- const existingSortIndex = newAst.orderby.findIndex((item) => (0, astFilterProcessing_1.getFieldFromExpression)(item.expr) === column);
1765
- if (existingSortIndex !== -1) {
1766
- newAst.orderby[existingSortIndex] = {
1767
- expr: { type: 'column_ref', column },
1768
- type: direction,
1769
- };
1770
- }
1771
- else {
1772
- newAst.orderby.push({
1773
- expr: { type: 'column_ref', column },
1774
- type: direction,
1775
- });
1776
- }
1777
- // look through the columns
1778
- setOpenPopover(null);
1779
- setBaseAst((0, util_1.deepCopy)(newAst));
1780
- fetchSqlQuery((0, util_1.deepCopy)(newAst));
1781
- }
1782
- } }) }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: { width: '100%' }, children: [(0, jsx_runtime_1.jsx)(SidebarHeadingComponent, { label: "Limit" }), (baseAst &&
1783
- ((baseAst.limit && baseAst.limit.value?.length > 0) ||
1784
- (baseAst.top && baseAst.top.value))) ||
1785
- pivot?.rowLimit ? ((0, jsx_runtime_1.jsx)("div", { style: {
1093
+ }, popoverTitle: "Sort by", popoverChildren: (0, jsx_runtime_1.jsx)(AddSortPopover_1.AddSortPopover, { columns: pivotData
1094
+ ? pivotData.columns
1095
+ : reportColumnsToStateColumns, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, onSave: async (column, direction) => {
1096
+ onSortChange({ field: column, direction });
1097
+ setOpenPopover(null);
1098
+ } }) }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: { width: '100%' }, children: [(0, jsx_runtime_1.jsx)(SidebarHeadingComponent, { label: "Limit" }), limit || pivot?.rowLimit ? ((0, jsx_runtime_1.jsx)("div", { style: {
1786
1099
  display: 'flex',
1787
1100
  flexDirection: 'column',
1788
1101
  gap: 8,
1789
1102
  marginBottom: 12,
1790
- }, children: (0, jsx_runtime_1.jsx)(AddLimitPopover_1.LimitSentence, { limit: baseAst.limit?.value?.[0]?.value ||
1791
- baseAst.top?.value ||
1792
- pivot?.rowLimit ||
1793
- 0, setOpenPopover: setOpenPopover, LimitPopover: LimitPopoverComponent, EditPopover: AddLimitPopover_1.AddLimitPopover, handleDelete: () => {
1103
+ }, children: (0, jsx_runtime_1.jsx)(AddLimitPopover_1.LimitSentence, { limit: limit?.value || pivot?.rowLimit || 0, setOpenPopover: setOpenPopover, LimitPopover: LimitPopoverComponent, EditPopover: AddLimitPopover_1.AddLimitPopover, handleDelete: () => {
1794
1104
  onLimitChange(null);
1105
+ setOpenPopover(null);
1795
1106
  }, onSave: (limit) => {
1796
1107
  onLimitChange(limit);
1797
- }, TextInput: TextInputComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, disabled: tableLoading || loading }) })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { disabled: !baseAst || !dataDisplayed || loading || tableLoading, onClick: () => {
1798
- if (!selectedColumns || selectedColumns.length === 0) {
1799
- return;
1800
- }
1801
- if (!baseAst) {
1802
- return;
1803
- }
1108
+ setOpenPopover(null);
1109
+ }, TextInput: TextInputComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, disabled: tableLoading || loading }) })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { disabled: columns.length === 0 || loading || tableLoading, onClick: () => {
1804
1110
  if (!openPopover) {
1805
1111
  setOpenPopover('AddLimitPopover');
1806
1112
  }
@@ -1809,37 +1115,36 @@ function ReportBuilder({ initialTableName = '', onSubmitEditReport = () => void
1809
1115
  ...(openPopover === 'AddLimitPopover' && { top: 12 }),
1810
1116
  }, children: (0, jsx_runtime_1.jsx)(PopoverComponent, { isOpen: openPopover === 'AddLimitPopover', setIsOpen: (isOpen) => {
1811
1117
  if (!isOpen) {
1812
- setActiveEditItem(null);
1813
1118
  setOpenPopover(null);
1814
1119
  }
1815
1120
  }, popoverTitle: "Add limit", popoverChildren: (0, jsx_runtime_1.jsx)(AddLimitPopover_1.AddLimitPopover, { TextInputComponent: TextInputComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, onSave: (limit) => {
1816
1121
  onLimitChange(limit);
1122
+ setOpenPopover(null);
1817
1123
  } }) }) })] }))] }), (0, jsx_runtime_1.jsx)("div", { style: { width: '100%', minHeight: '30vh' } })] }), (0, jsx_runtime_1.jsxs)(ContainerComponent, { children: [isAIEnabled && ((0, jsx_runtime_1.jsx)("form", { ref: askAIContainerRef, onSubmit: (event) => {
1818
1124
  event.preventDefault();
1819
1125
  }, style: {
1820
1126
  display: 'flex',
1821
1127
  flexDirection: 'row',
1822
1128
  gap: 12,
1823
- visibility: askAIInputWidth === -1 && askAILoadingContainerWidth === -1
1824
- ? 'hidden'
1825
- : 'visible',
1826
- }, children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(TextInputComponent, { id: "ask_ai_input_bar", value: aiPrompt, width: askAIInputWidth !== -1
1827
- ? askAIInputWidth
1828
- : askAILoadingContainerWidth, onChange: (e) => setAiPrompt(e.target.value), placeholder: askedAQuestion
1829
- ? 'Ask a follow-up question...'
1830
- : 'Ask a question...' }), (0, jsx_runtime_1.jsx)(ButtonComponent, { onClick: () => {
1831
- fetchAstFromPromptHelper();
1832
- }, isLoading: askAILoading && !baseAst, label: 'Ask AI' }), ((baseAst && dataDisplayed) || initialLoad) && !reportId && ((0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { label: 'New report', onClick: clearAllState }))] }) })), baseAst && ((0, jsx_runtime_1.jsx)(TableComponent, { isLoading: tableLoading || (loading && errorMessage.length === 0), rows: formattedRows, rowCount: pivot ? pivotData?.rowCount : numberOfRows, rowCountIsLoading: rowCountIsLoading, rowsPerPage: 20, columns: pivot
1833
- ? pivotData?.columns || emptyPivotColumns()
1834
- : enforceOrderOnColumns(Object.keys(rows[0] ?? {})).map((c) => {
1129
+ visibility: askAIInputWidth === -1 ? 'hidden' : 'visible',
1130
+ }, children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(TextInputComponent, { id: "ask_ai_input_bar", value: aiPrompt, width: askAIInputWidth, onChange: (e) => setAiPrompt(e.target.value), placeholder: 'Ask a question...' }), (0, jsx_runtime_1.jsx)(UiComponents_1.QuillToolTip, { enabled: tables.length > 1, text: "Ask AI does not support joined tables right now", textStyle: {
1131
+ maxWidth: '250px',
1132
+ whiteSpace: 'normal',
1133
+ }, displayBelow: true, children: (0, jsx_runtime_1.jsx)(ButtonComponent, { disabled: tables.length > 1, onClick: () => {
1134
+ if (tables.length <= 1) {
1135
+ fetchAstFromPromptHelper();
1136
+ }
1137
+ }, isLoading: askAILoading && columns.length === 0, label: 'Ask AI' }) }), !reportId && ((0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { label: 'New report', onClick: clearAllState, disabled: columns.length === 0 || loading }))] }) })), columns.length > 0 && ((0, jsx_runtime_1.jsx)(TableComponent, { isLoading: tableLoading || (loading && errorMessage.length === 0), rows: formattedRows, rowCount: pivot ? pivotData?.rowCount : numberOfRows, rowCountIsLoading: rowCountIsLoading, rowsPerPage: 20, columns: pivot
1138
+ ? pivotData?.columns || []
1139
+ : reportColumnsToStateColumns.map((col) => {
1835
1140
  return {
1836
- label: (0, textProcessing_1.snakeAndCamelCaseToTitleCase)(c),
1837
- field: c,
1141
+ field: col.field,
1142
+ label: (0, textProcessing_1.snakeAndCamelCaseToTitleCase)(col.field),
1838
1143
  };
1839
1144
  }), onPageChange: onPageChange, onSortChange: (sort) => {
1840
1145
  onSortChange(sort);
1841
1146
  }, disableSort: !!mssqlSortWarning, containerStyle: {
1842
- maxHeight: Math.max(window.innerHeight - 290, 75 + Math.min(Math.max(10, rows.length), 20) * 37),
1147
+ maxHeight: Math.max(window.innerHeight - 290, 75 + Math.min(Math.max(10, reportRows.length), 20) * 37),
1843
1148
  } })), (0, jsx_runtime_1.jsxs)("div", { style: {
1844
1149
  display: 'flex',
1845
1150
  flexDirection: 'row',
@@ -1854,130 +1159,122 @@ function ReportBuilder({ initialTableName = '', onSubmitEditReport = () => void
1854
1159
  width: '100%',
1855
1160
  gap: 12,
1856
1161
  alignItems: 'center',
1857
- }, children: [(0, jsx_runtime_1.jsx)(ErrorMessageComponent, { errorMessage: errorMessage || pivotError || '' }), (0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { onClick: () => {
1162
+ }, children: [(0, jsx_runtime_1.jsx)(ErrorMessageComponent, { errorMessage: errorMessage || pivotError }), (0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { onClick: () => {
1858
1163
  fetchAstFromPromptHelper();
1859
- }, label: 'Retry' }), (0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { onClick: clearAllState, label: 'Reset' })] })) : ((0, jsx_runtime_1.jsx)("div", { style: { width: '100%' } })), baseAst && dataDisplayed && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [onDiscardChanges && ((0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { onClick: onDiscardChanges, label: "Discard changes" })), !hideCopySQL && ((0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { label: isCopying ? 'Copied' : 'Copy SQL', onClick: () => copySQLToClipboard() })), !isAdminEnabled ? null : ((0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { onClick: async () => {
1860
- const tempReportColumns = selectedOrderedColumns.length > 0
1861
- ? selectedOrderedColumns
1862
- .map((columnName) => {
1863
- return columns.find((col) => col.field === columnName);
1864
- })
1865
- .filter((col) => col !== undefined)
1866
- .map((c) => reportInfo?.columns.find((col) => col.field === c.field))
1867
- .filter((col) => col !== undefined)
1868
- : (reportInfo?.columns.filter((col) => {
1869
- return columns.find((c) => {
1870
- return col.field === c.field;
1871
- });
1872
- }) ?? []);
1164
+ }, label: 'Retry' }), (0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { onClick: clearAllState, label: 'Reset' })] })) : ((0, jsx_runtime_1.jsx)("div", { style: { width: '100%' } })), columns.length > 0 && activeQuery && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [undoButtonEnabled && stateStack.length > 1 && ((0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { onClick: handleUndo, label: "Undo", disabled: stateStack.length <= 1 || loading })), onDiscardChanges && ((0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { onClick: onDiscardChanges, label: "Discard changes" })), !hideCopySQL && ((0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { label: isCopying ? 'Copied' : 'Copy SQL', onClick: () => copySQLToClipboard() })), !isAdminEnabled ? null : ((0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { onClick: async () => {
1165
+ const tempReportColumns = columns
1166
+ .map((column) => {
1167
+ return reportColumnsToStateColumns.find((col) => col.field === (column.alias || column.field));
1168
+ })
1169
+ .filter((col) => col !== undefined);
1170
+ let customFieldColumns = [];
1171
+ if (client && isSelectStar && schemaData.customFields) {
1172
+ customFieldColumns = tables.flatMap((table) => {
1173
+ return (schemaData.customFields?.[table.name || ''] || []).map((field) => field.field);
1174
+ });
1175
+ }
1873
1176
  setTempReport({
1874
- ...(reportInfo
1875
- ? {
1876
- ...reportInfo,
1877
- ...tempReport,
1878
- id: Report_1.TEMP_REPORT_ID,
1879
- dashboardName: 'quill-saved-queries',
1880
- chartType: 'table',
1881
- pivot: pivot,
1882
- yAxisFields: reportInfo?.pivot && !pivot
1883
- ? []
1884
- : reportInfo?.yAxisFields,
1885
- columns: isSelectedAllColumns()
1886
- ? // if SELECT *, filter out custom fields from tabular view
1887
- // so Automatic Custom Fields can be applied
1888
- tempReportColumns.filter((col) => {
1889
- return !schemaData.customFields?.[currentTable]?.some((field) => {
1890
- return field.field === col.field;
1891
- });
1892
- })
1893
- : tempReportColumns,
1894
- queryString: isSelectedAllColumns()
1895
- ? (0, convert_1.convertQueryToSelectStar)(activeQuery)
1896
- : activeQuery,
1897
- includeCustomFields: isSelectedAllColumns(),
1898
- rows: rows,
1899
- pivotRows: pivotData?.rows,
1900
- pivotColumns: pivotData?.columns,
1901
- pivotRowCount: pivotData?.rowCount,
1902
- pivotQuery: pivotData?.pivotQuery,
1903
- comparisonPivotQuery: pivotData?.comparisonPivotQuery,
1904
- flags: reportInfo?.flags ?? tempReport?.flags,
1905
- }
1906
- : {
1907
- ...tempReport,
1908
- chartType: 'table',
1909
- id: Report_1.TEMP_REPORT_ID,
1910
- flags: tempReport?.flags,
1911
- }),
1177
+ ...tempReport,
1178
+ ...(pivot
1179
+ ? (0, pivotProcessing_1.pivotFormData)(pivot, reportColumnsToStateColumns, tempReport, tempReport.chartType, pivotData ?? undefined)
1180
+ : {}),
1181
+ id: Report_1.TEMP_REPORT_ID,
1182
+ dashboardName: destinationDashboard,
1183
+ pivot: pivot,
1184
+ yAxisFields: tempReport?.pivot && !pivot
1185
+ ? []
1186
+ : tempReport?.yAxisFields,
1187
+ columns: isSelectStar
1188
+ ? // if SELECT *, filter out custom fields from tabular view
1189
+ // so Automatic Custom Fields can be applied
1190
+ tempReportColumns.filter((col) => {
1191
+ return !customFieldColumns.includes(col.field);
1192
+ })
1193
+ : tempReportColumns,
1194
+ columnInternal: isSelectStar
1195
+ ? // if SELECT *, filter out custom fields from tabular view
1196
+ // so Automatic Custom Fields can be applied
1197
+ tempReportColumns.filter((col) => {
1198
+ return !customFieldColumns.includes(col.field);
1199
+ })
1200
+ : tempReportColumns,
1201
+ queryString: isSelectStar
1202
+ ? (0, convert_1.convertQueryToSelectStar)(activeQuery)
1203
+ : activeQuery,
1204
+ includeCustomFields: isSelectStar,
1205
+ rows: reportRows,
1206
+ pivotRows: pivotData?.rows,
1207
+ pivotColumns: pivotData?.columns,
1208
+ pivotRowCount: pivotData?.rowCount,
1209
+ pivotQuery: pivotData?.pivotQuery,
1210
+ comparisonPivotQuery: pivotData?.comparisonPivotQuery,
1211
+ flags: tempReport?.flags,
1912
1212
  });
1913
1213
  setIsSaveQueryModalOpen(true);
1914
1214
  }, disabled: !!errorMessage ||
1915
1215
  !!pivotError ||
1916
1216
  tableLoading ||
1917
1217
  loading ||
1918
- unresolvedReportMessage, label: 'Save query', tooltipText: unresolvedReportMessage })), (0, jsx_runtime_1.jsx)(ButtonComponent, { onClick: async () => {
1218
+ !!unresolvedReportMessage, label: 'Save query', tooltipText: unresolvedReportMessage })), (0, jsx_runtime_1.jsx)(ButtonComponent, { onClick: async () => {
1919
1219
  onSaveChanges && onSaveChanges();
1920
- const tempReportColumns = selectedOrderedColumns.length > 0
1921
- ? selectedOrderedColumns
1922
- .map((columnName) => {
1923
- return columns.find((col) => col.field === columnName);
1924
- })
1925
- .filter((col) => col !== undefined)
1926
- .map((c) => reportInfo?.columns.find((col) => col.field === c.field))
1927
- .filter((col) => col !== undefined)
1928
- : (reportInfo?.columns.filter((col) => {
1929
- return columns.find((c) => {
1930
- return col.field === c.field;
1931
- });
1932
- }) ?? []);
1220
+ const tempReportColumns = columns
1221
+ .map((column) => {
1222
+ return reportColumnsToStateColumns.find((col) => col.field === (column.alias || column.field));
1223
+ })
1224
+ .filter((col) => col !== undefined);
1225
+ let customFieldColumns = [];
1226
+ if (client && isSelectStar && schemaData.customFields) {
1227
+ customFieldColumns = tables.flatMap((table) => {
1228
+ return (schemaData.customFields?.[table.name || ''] || []).map((field) => field.field);
1229
+ });
1230
+ }
1933
1231
  setTempReport({
1934
- ...(reportInfo
1935
- ? {
1936
- ...reportInfo,
1937
- ...tempReport,
1938
- id: Report_1.TEMP_REPORT_ID,
1939
- dashboardName: destinationDashboard,
1940
- pivot: pivot,
1941
- yAxisFields: reportInfo?.pivot && !pivot
1942
- ? []
1943
- : reportInfo?.yAxisFields,
1944
- columns: isSelectedAllColumns()
1945
- ? // if SELECT *, filter out custom fields from tabular view
1946
- // so Automatic Custom Fields can be applied
1947
- tempReportColumns.filter((col) => {
1948
- return !schemaData.customFields?.[currentTable]?.some((field) => {
1949
- return field.field === col.field;
1950
- });
1951
- })
1952
- : tempReportColumns,
1953
- queryString: isSelectedAllColumns()
1954
- ? (0, convert_1.convertQueryToSelectStar)(activeQuery)
1955
- : activeQuery,
1956
- includeCustomFields: isSelectedAllColumns(),
1957
- rows: rows,
1958
- pivotRows: pivotData?.rows,
1959
- pivotColumns: pivotData?.columns,
1960
- pivotRowCount: pivotData?.rowCount,
1961
- pivotQuery: pivotData?.pivotQuery,
1962
- comparisonPivotQuery: pivotData?.comparisonPivotQuery,
1963
- flags: reportInfo?.flags ?? tempReport?.flags,
1964
- }
1965
- : {
1966
- ...tempReport,
1967
- id: Report_1.TEMP_REPORT_ID,
1968
- flags: tempReport?.flags,
1969
- }),
1232
+ ...tempReport,
1233
+ ...(pivot
1234
+ ? (0, pivotProcessing_1.pivotFormData)(pivot, reportColumnsToStateColumns, tempReport, tempReport.chartType, pivotData ?? undefined)
1235
+ : {}),
1236
+ id: Report_1.TEMP_REPORT_ID,
1237
+ dashboardName: destinationDashboard,
1238
+ pivot: pivot,
1239
+ yAxisFields: tempReport?.pivot && !pivot
1240
+ ? []
1241
+ : tempReport?.yAxisFields,
1242
+ columns: isSelectStar
1243
+ ? // if SELECT *, filter out custom fields from tabular view
1244
+ // so Automatic Custom Fields can be applied
1245
+ tempReportColumns.filter((col) => {
1246
+ return !customFieldColumns.includes(col.field);
1247
+ })
1248
+ : tempReportColumns,
1249
+ columnInternal: isSelectStar
1250
+ ? // if SELECT *, filter out custom fields from tabular view
1251
+ // so Automatic Custom Fields can be applied
1252
+ tempReportColumns.filter((col) => {
1253
+ return !customFieldColumns.includes(col.field);
1254
+ })
1255
+ : tempReportColumns,
1256
+ queryString: isSelectStar
1257
+ ? (0, convert_1.convertQueryToSelectStar)(activeQuery)
1258
+ : activeQuery,
1259
+ includeCustomFields: isSelectStar,
1260
+ rows: reportRows,
1261
+ pivotRows: pivotData?.rows,
1262
+ pivotColumns: pivotData?.columns,
1263
+ pivotRowCount: pivotData?.rowCount,
1264
+ pivotQuery: pivotData?.pivotQuery,
1265
+ comparisonPivotQuery: pivotData?.comparisonPivotQuery,
1266
+ flags: tempReport?.flags,
1970
1267
  });
1971
1268
  setIsChartBuilderOpen(true);
1972
1269
  }, disabled: !!errorMessage ||
1973
1270
  !!pivotError ||
1974
1271
  tableLoading ||
1975
1272
  loading ||
1976
- unresolvedReportMessage, label: reportId ? 'Save changes' : 'Add to dashboard', tooltipText: unresolvedReportMessage })] }))] })] }), (0, jsx_runtime_1.jsx)("style", { children: `body{margin:0;}` })] })), (!isChartBuilderHorizontalView || isChartBuilderOpen) && ((0, jsx_runtime_1.jsx)(ChartBuilder_1.ChartBuilderWithModal, { tempReport: tempReport, reportId: reportId, isAdmin: isAdminEnabled, title: chartBuilderTitle
1273
+ !!unresolvedReportMessage, label: reportId ? 'Save changes' : 'Add to dashboard', tooltipText: unresolvedReportMessage })] }))] })] }), (0, jsx_runtime_1.jsx)("style", { children: `body{margin:0;}` })] })), (!isChartBuilderHorizontalView || isChartBuilderOpen) && ((0, jsx_runtime_1.jsx)(ChartBuilder_1.ChartBuilderWithModal, { tempReport: tempReport, reportId: reportId, isAdmin: isAdminEnabled, title: chartBuilderTitle
1977
1274
  ? chartBuilderTitle
1978
1275
  : reportId
1979
1276
  ? 'Save changes'
1980
- : 'Add to dashboard', isHorizontalView: true, isOpen: isChartBuilderOpen, setIsOpen: setIsChartBuilderOpen, onAddToDashboardComplete: reportId ? onSubmitEditReport : onSubmitCreateReport, organizationName: organizationName, initialUniqueValues: uniqueValues[currentTable], initialUniqueValuesIsLoading: uniqueValuesIsLoading, pivotRecommendationsEnabled: pivotRecommendationsEnabledState, 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, CheckboxComponent: CheckboxComponent, FormContainer: ChartBuilderFormContainer, hideDateRangeFilter: true, hideDeleteButton: true, buttonLabel: !!reportId ? 'Save changes' : 'Add to dashboard', onClickChartElement: onClickChartElement, filtersEnabled: filtersEnabled, onFiltersEnabledChanged: (enabled) => {
1277
+ : 'Add to dashboard', isHorizontalView: true, isOpen: isChartBuilderOpen, setIsOpen: setIsChartBuilderOpen, onAddToDashboardComplete: reportId ? onSubmitEditReport : onSubmitCreateReport, destinationDashboard: destinationDashboard, organizationName: organizationName, initialUniqueValues: columnUniqueValues, initialUniqueValuesIsLoading: filteredUniqueValuesIsLoading || unfilteredUniqueValuesIsLoading, pivotRecommendationsEnabled: pivotRecommendationsEnabledState, 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, CheckboxComponent: CheckboxComponent, FormContainer: ChartBuilderFormContainer, hideDateRangeFilter: true, hideDeleteButton: true, buttonLabel: !!reportId ? 'Save changes' : 'Add to dashboard', onClickChartElement: onClickChartElement, filtersEnabled: filtersEnabled, onFiltersEnabledChanged: (enabled) => {
1981
1278
  setFiltersEnabled(enabled);
1982
1279
  }, isEditingMode: true })), isSaveQueryModalOpen && ((0, jsx_runtime_1.jsx)(ChartBuilder_1.ChartBuilderWithModal, { isHorizontalView: false, hideTableView: true, hideChartView: true, hidePivotForm: true, hideChartType: true, isOpen: isSaveQueryModalOpen, setIsOpen: setIsSaveQueryModalOpen, onAddToDashboardComplete: onSubmitSaveQuery, destinationDashboard: 'quill-saved-queries', isAdmin: false, title: 'Save query', buttonLabel: 'Save query', tempReport: tempReport, reportId: reportId, organizationName: organizationName, CardComponent: CardComponent, TableComponent: TableComponent, ModalComponent: ModalComponent, ButtonComponent: ButtonComponent, TextInputComponent: TextInputComponent, SelectComponent: SelectComponent, SecondaryButtonComponent: SecondaryButtonComponent, HeaderComponent: HeaderComponent, SubHeaderComponent: SubHeaderComponent, LabelComponent: LabelComponent, TextComponent: TextComponent, PopoverComponent: PopoverComponent, DeleteButtonComponent: DeleteButtonComponent, LoadingComponent: LoadingComponent, ChartBuilderInputRowContainer: ChartBuilderInputRowContainer, ChartBuilderInputColumnContainer: ChartBuilderInputColumnContainer, ErrorMessageComponent: ErrorMessageComponent, PivotRowContainer: PivotRowContainer, PivotColumnContainer: PivotColumnContainer, FormContainer: ChartBuilderFormContainer, CheckboxComponent: CheckboxComponent, hideDateRangeFilter: true, hideDeleteButton: true, hideDiscardChanges: true, hideSQLQuery: false, onClickChartElement: onClickChartElement,
1983
1280
  // hide filters table, make it a table chart etc