@quillsql/react 2.14.14 → 2.14.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/dist/cjs/Chart.d.ts.map +1 -1
  2. package/dist/cjs/Chart.js +0 -12
  3. package/dist/cjs/ChartBuilder.d.ts +2 -3
  4. package/dist/cjs/ChartBuilder.d.ts.map +1 -1
  5. package/dist/cjs/ChartBuilder.js +16 -105
  6. package/dist/cjs/ChartEditor.d.ts.map +1 -1
  7. package/dist/cjs/ChartEditor.js +0 -2
  8. package/dist/cjs/Context.d.ts +2 -6
  9. package/dist/cjs/Context.d.ts.map +1 -1
  10. package/dist/cjs/Context.js +32 -159
  11. package/dist/cjs/Dashboard.d.ts.map +1 -1
  12. package/dist/cjs/Dashboard.js +16 -93
  13. package/dist/cjs/QuillProvider.d.ts +1 -38
  14. package/dist/cjs/QuillProvider.d.ts.map +1 -1
  15. package/dist/cjs/QuillProvider.js +2 -2
  16. package/dist/cjs/ReportBuilder.d.ts +1 -4
  17. package/dist/cjs/ReportBuilder.d.ts.map +1 -1
  18. package/dist/cjs/ReportBuilder.js +1270 -103
  19. package/dist/cjs/SQLEditor.d.ts.map +1 -1
  20. package/dist/cjs/SQLEditor.js +6 -50
  21. package/dist/cjs/Table.d.ts.map +1 -1
  22. package/dist/cjs/Table.js +0 -12
  23. package/dist/cjs/components/Chart/InternalChart.d.ts.map +1 -1
  24. package/dist/cjs/components/Chart/InternalChart.js +1 -24
  25. package/dist/cjs/components/Dashboard/DashboardTemplate.d.ts.map +1 -1
  26. package/dist/cjs/components/Dashboard/DashboardTemplate.js +1 -2
  27. package/dist/cjs/components/Dashboard/DataLoader.d.ts.map +1 -1
  28. package/dist/cjs/components/Dashboard/DataLoader.js +2 -73
  29. package/dist/cjs/components/Dashboard/util.d.ts +1 -2
  30. package/dist/cjs/components/Dashboard/util.d.ts.map +1 -1
  31. package/dist/cjs/components/Dashboard/util.js +1 -12
  32. package/dist/cjs/components/QuillTable.d.ts +1 -2
  33. package/dist/cjs/components/QuillTable.d.ts.map +1 -1
  34. package/dist/cjs/components/QuillTable.js +2 -2
  35. package/dist/cjs/components/ReportBuilder/AddColumnModal.d.ts.map +1 -1
  36. package/dist/cjs/components/ReportBuilder/AddColumnModal.js +1 -7
  37. package/dist/cjs/components/ReportBuilder/ui.d.ts.map +1 -1
  38. package/dist/cjs/components/ReportBuilder/ui.js +1 -3
  39. package/dist/cjs/components/UiComponents.d.ts +2 -5
  40. package/dist/cjs/components/UiComponents.d.ts.map +1 -1
  41. package/dist/cjs/components/UiComponents.js +5 -6
  42. package/dist/cjs/hooks/useAskQuill.d.ts.map +1 -1
  43. package/dist/cjs/hooks/useAskQuill.js +0 -38
  44. package/dist/cjs/hooks/useDashboard.d.ts.map +1 -1
  45. package/dist/cjs/hooks/useDashboard.js +4 -60
  46. package/dist/cjs/hooks/useExport.d.ts.map +1 -1
  47. package/dist/cjs/hooks/useExport.js +2 -5
  48. package/dist/cjs/hooks/useQuill.d.ts.map +1 -1
  49. package/dist/cjs/hooks/useQuill.js +1 -25
  50. package/dist/cjs/hooks/useVirtualTables.d.ts.map +1 -1
  51. package/dist/cjs/hooks/useVirtualTables.js +2 -27
  52. package/dist/cjs/index.d.ts +0 -11
  53. package/dist/cjs/index.d.ts.map +1 -1
  54. package/dist/cjs/index.js +1 -17
  55. package/dist/cjs/internals/ReportBuilder/PivotForm.d.ts +1 -14
  56. package/dist/cjs/internals/ReportBuilder/PivotForm.d.ts.map +1 -1
  57. package/dist/cjs/internals/ReportBuilder/PivotForm.js +3 -86
  58. package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts +2 -18
  59. package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
  60. package/dist/cjs/internals/ReportBuilder/PivotModal.js +141 -420
  61. package/dist/cjs/utils/astProcessing.d.ts +2 -4
  62. package/dist/cjs/utils/astProcessing.d.ts.map +1 -1
  63. package/dist/cjs/utils/astProcessing.js +2 -25
  64. package/dist/cjs/utils/client.d.ts +1 -2
  65. package/dist/cjs/utils/client.d.ts.map +1 -1
  66. package/dist/cjs/utils/client.js +1 -12
  67. package/dist/cjs/utils/dashboard.d.ts +1 -3
  68. package/dist/cjs/utils/dashboard.d.ts.map +1 -1
  69. package/dist/cjs/utils/dashboard.js +3 -44
  70. package/dist/cjs/utils/filterProcessing.d.ts +1 -2
  71. package/dist/cjs/utils/filterProcessing.d.ts.map +1 -1
  72. package/dist/cjs/utils/filterProcessing.js +1 -12
  73. package/dist/cjs/utils/pivotConstructor.d.ts.map +1 -1
  74. package/dist/cjs/utils/pivotConstructor.js +9 -11
  75. package/dist/cjs/utils/pivotProcessing.d.ts.map +1 -1
  76. package/dist/cjs/utils/pivotProcessing.js +3 -1
  77. package/dist/cjs/utils/queryConstructor.d.ts.map +1 -1
  78. package/dist/cjs/utils/queryConstructor.js +9 -1
  79. package/dist/cjs/utils/report.d.ts +5 -10
  80. package/dist/cjs/utils/report.d.ts.map +1 -1
  81. package/dist/cjs/utils/report.js +7 -51
  82. package/dist/cjs/utils/reportBuilder.d.ts.map +1 -1
  83. package/dist/cjs/utils/reportBuilder.js +2 -5
  84. package/dist/cjs/utils/schema.d.ts +2 -5
  85. package/dist/cjs/utils/schema.d.ts.map +1 -1
  86. package/dist/cjs/utils/schema.js +2 -14
  87. package/dist/cjs/utils/tableProcessing.d.ts +10 -17
  88. package/dist/cjs/utils/tableProcessing.d.ts.map +1 -1
  89. package/dist/cjs/utils/tableProcessing.js +17 -99
  90. package/dist/esm/Chart.d.ts.map +1 -1
  91. package/dist/esm/Chart.js +1 -13
  92. package/dist/esm/ChartBuilder.d.ts +2 -3
  93. package/dist/esm/ChartBuilder.d.ts.map +1 -1
  94. package/dist/esm/ChartBuilder.js +18 -107
  95. package/dist/esm/ChartEditor.d.ts.map +1 -1
  96. package/dist/esm/ChartEditor.js +1 -3
  97. package/dist/esm/Context.d.ts +2 -6
  98. package/dist/esm/Context.d.ts.map +1 -1
  99. package/dist/esm/Context.js +31 -158
  100. package/dist/esm/Dashboard.d.ts.map +1 -1
  101. package/dist/esm/Dashboard.js +17 -94
  102. package/dist/esm/QuillProvider.d.ts +1 -38
  103. package/dist/esm/QuillProvider.d.ts.map +1 -1
  104. package/dist/esm/QuillProvider.js +2 -2
  105. package/dist/esm/ReportBuilder.d.ts +1 -4
  106. package/dist/esm/ReportBuilder.d.ts.map +1 -1
  107. package/dist/esm/ReportBuilder.js +1270 -106
  108. package/dist/esm/SQLEditor.d.ts.map +1 -1
  109. package/dist/esm/SQLEditor.js +7 -51
  110. package/dist/esm/Table.d.ts.map +1 -1
  111. package/dist/esm/Table.js +1 -13
  112. package/dist/esm/components/Chart/InternalChart.d.ts.map +1 -1
  113. package/dist/esm/components/Chart/InternalChart.js +2 -25
  114. package/dist/esm/components/Dashboard/DashboardTemplate.d.ts.map +1 -1
  115. package/dist/esm/components/Dashboard/DashboardTemplate.js +2 -3
  116. package/dist/esm/components/Dashboard/DataLoader.d.ts.map +1 -1
  117. package/dist/esm/components/Dashboard/DataLoader.js +3 -74
  118. package/dist/esm/components/Dashboard/util.d.ts +1 -2
  119. package/dist/esm/components/Dashboard/util.d.ts.map +1 -1
  120. package/dist/esm/components/Dashboard/util.js +1 -12
  121. package/dist/esm/components/QuillTable.d.ts +1 -2
  122. package/dist/esm/components/QuillTable.d.ts.map +1 -1
  123. package/dist/esm/components/QuillTable.js +2 -2
  124. package/dist/esm/components/ReportBuilder/AddColumnModal.d.ts.map +1 -1
  125. package/dist/esm/components/ReportBuilder/AddColumnModal.js +1 -7
  126. package/dist/esm/components/ReportBuilder/ui.d.ts.map +1 -1
  127. package/dist/esm/components/ReportBuilder/ui.js +2 -4
  128. package/dist/esm/components/UiComponents.d.ts +2 -5
  129. package/dist/esm/components/UiComponents.d.ts.map +1 -1
  130. package/dist/esm/components/UiComponents.js +5 -6
  131. package/dist/esm/hooks/useAskQuill.d.ts.map +1 -1
  132. package/dist/esm/hooks/useAskQuill.js +1 -39
  133. package/dist/esm/hooks/useDashboard.d.ts.map +1 -1
  134. package/dist/esm/hooks/useDashboard.js +5 -61
  135. package/dist/esm/hooks/useExport.d.ts.map +1 -1
  136. package/dist/esm/hooks/useExport.js +3 -6
  137. package/dist/esm/hooks/useQuill.d.ts.map +1 -1
  138. package/dist/esm/hooks/useQuill.js +2 -26
  139. package/dist/esm/hooks/useVirtualTables.d.ts.map +1 -1
  140. package/dist/esm/hooks/useVirtualTables.js +3 -28
  141. package/dist/esm/index.d.ts +0 -11
  142. package/dist/esm/index.d.ts.map +1 -1
  143. package/dist/esm/index.js +0 -8
  144. package/dist/esm/internals/ReportBuilder/PivotForm.d.ts +1 -14
  145. package/dist/esm/internals/ReportBuilder/PivotForm.d.ts.map +1 -1
  146. package/dist/esm/internals/ReportBuilder/PivotForm.js +4 -87
  147. package/dist/esm/internals/ReportBuilder/PivotModal.d.ts +2 -18
  148. package/dist/esm/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
  149. package/dist/esm/internals/ReportBuilder/PivotModal.js +143 -422
  150. package/dist/esm/utils/astProcessing.d.ts +2 -4
  151. package/dist/esm/utils/astProcessing.d.ts.map +1 -1
  152. package/dist/esm/utils/astProcessing.js +2 -25
  153. package/dist/esm/utils/client.d.ts +1 -2
  154. package/dist/esm/utils/client.d.ts.map +1 -1
  155. package/dist/esm/utils/client.js +1 -12
  156. package/dist/esm/utils/dashboard.d.ts +1 -3
  157. package/dist/esm/utils/dashboard.d.ts.map +1 -1
  158. package/dist/esm/utils/dashboard.js +3 -44
  159. package/dist/esm/utils/filterProcessing.d.ts +1 -2
  160. package/dist/esm/utils/filterProcessing.d.ts.map +1 -1
  161. package/dist/esm/utils/filterProcessing.js +1 -12
  162. package/dist/esm/utils/pivotConstructor.d.ts.map +1 -1
  163. package/dist/esm/utils/pivotConstructor.js +9 -11
  164. package/dist/esm/utils/pivotProcessing.d.ts.map +1 -1
  165. package/dist/esm/utils/pivotProcessing.js +3 -1
  166. package/dist/esm/utils/queryConstructor.d.ts.map +1 -1
  167. package/dist/esm/utils/queryConstructor.js +9 -1
  168. package/dist/esm/utils/report.d.ts +5 -10
  169. package/dist/esm/utils/report.d.ts.map +1 -1
  170. package/dist/esm/utils/report.js +7 -51
  171. package/dist/esm/utils/reportBuilder.d.ts.map +1 -1
  172. package/dist/esm/utils/reportBuilder.js +2 -5
  173. package/dist/esm/utils/schema.d.ts +2 -5
  174. package/dist/esm/utils/schema.d.ts.map +1 -1
  175. package/dist/esm/utils/schema.js +2 -14
  176. package/dist/esm/utils/tableProcessing.d.ts +10 -17
  177. package/dist/esm/utils/tableProcessing.d.ts.map +1 -1
  178. package/dist/esm/utils/tableProcessing.js +17 -99
  179. package/package.json +1 -1
  180. package/dist/cjs/components/ReportBuilder/ColumnComponent.d.ts +0 -48
  181. package/dist/cjs/components/ReportBuilder/ColumnComponent.d.ts.map +0 -1
  182. package/dist/cjs/components/ReportBuilder/ColumnComponent.js +0 -46
  183. package/dist/cjs/components/ReportBuilder/FilterComponent.d.ts +0 -65
  184. package/dist/cjs/components/ReportBuilder/FilterComponent.d.ts.map +0 -1
  185. package/dist/cjs/components/ReportBuilder/FilterComponent.js +0 -51
  186. package/dist/cjs/components/ReportBuilder/LimitComponent.d.ts +0 -42
  187. package/dist/cjs/components/ReportBuilder/LimitComponent.d.ts.map +0 -1
  188. package/dist/cjs/components/ReportBuilder/LimitComponent.js +0 -50
  189. package/dist/cjs/components/ReportBuilder/PivotComponent.d.ts +0 -66
  190. package/dist/cjs/components/ReportBuilder/PivotComponent.d.ts.map +0 -1
  191. package/dist/cjs/components/ReportBuilder/PivotComponent.js +0 -47
  192. package/dist/cjs/components/ReportBuilder/SaveReport.d.ts +0 -162
  193. package/dist/cjs/components/ReportBuilder/SaveReport.d.ts.map +0 -1
  194. package/dist/cjs/components/ReportBuilder/SaveReport.js +0 -31
  195. package/dist/cjs/components/ReportBuilder/SortComponent.d.ts +0 -42
  196. package/dist/cjs/components/ReportBuilder/SortComponent.d.ts.map +0 -1
  197. package/dist/cjs/components/ReportBuilder/SortComponent.js +0 -50
  198. package/dist/cjs/components/ReportBuilder/TableComponent.d.ts +0 -28
  199. package/dist/cjs/components/ReportBuilder/TableComponent.d.ts.map +0 -1
  200. package/dist/cjs/components/ReportBuilder/TableComponent.js +0 -24
  201. package/dist/cjs/hooks/useLongLoading.d.ts +0 -13
  202. package/dist/cjs/hooks/useLongLoading.d.ts.map +0 -1
  203. package/dist/cjs/hooks/useLongLoading.js +0 -67
  204. package/dist/cjs/hooks/useReportBuilder.d.ts +0 -178
  205. package/dist/cjs/hooks/useReportBuilder.d.ts.map +0 -1
  206. package/dist/cjs/hooks/useReportBuilder.js +0 -1476
  207. package/dist/esm/components/ReportBuilder/ColumnComponent.d.ts +0 -48
  208. package/dist/esm/components/ReportBuilder/ColumnComponent.d.ts.map +0 -1
  209. package/dist/esm/components/ReportBuilder/ColumnComponent.js +0 -39
  210. package/dist/esm/components/ReportBuilder/FilterComponent.d.ts +0 -65
  211. package/dist/esm/components/ReportBuilder/FilterComponent.d.ts.map +0 -1
  212. package/dist/esm/components/ReportBuilder/FilterComponent.js +0 -44
  213. package/dist/esm/components/ReportBuilder/LimitComponent.d.ts +0 -42
  214. package/dist/esm/components/ReportBuilder/LimitComponent.d.ts.map +0 -1
  215. package/dist/esm/components/ReportBuilder/LimitComponent.js +0 -46
  216. package/dist/esm/components/ReportBuilder/PivotComponent.d.ts +0 -66
  217. package/dist/esm/components/ReportBuilder/PivotComponent.d.ts.map +0 -1
  218. package/dist/esm/components/ReportBuilder/PivotComponent.js +0 -40
  219. package/dist/esm/components/ReportBuilder/SaveReport.d.ts +0 -162
  220. package/dist/esm/components/ReportBuilder/SaveReport.d.ts.map +0 -1
  221. package/dist/esm/components/ReportBuilder/SaveReport.js +0 -31
  222. package/dist/esm/components/ReportBuilder/SortComponent.d.ts +0 -42
  223. package/dist/esm/components/ReportBuilder/SortComponent.d.ts.map +0 -1
  224. package/dist/esm/components/ReportBuilder/SortComponent.js +0 -46
  225. package/dist/esm/components/ReportBuilder/TableComponent.d.ts +0 -28
  226. package/dist/esm/components/ReportBuilder/TableComponent.d.ts.map +0 -1
  227. package/dist/esm/components/ReportBuilder/TableComponent.js +0 -20
  228. package/dist/esm/hooks/useLongLoading.d.ts +0 -13
  229. package/dist/esm/hooks/useLongLoading.d.ts.map +0 -1
  230. package/dist/esm/hooks/useLongLoading.js +0 -64
  231. package/dist/esm/hooks/useReportBuilder.d.ts +0 -178
  232. package/dist/esm/hooks/useReportBuilder.d.ts.map +0 -1
  233. package/dist/esm/hooks/useReportBuilder.js +0 -1471
@@ -1,23 +1,38 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useContext, useEffect, useRef, useState, } from 'react';
2
+ import { useContext, useEffect, useMemo, useRef, useState, } from 'react';
3
3
  import { MemoizedButton, MemoizedDeleteButton, MemoizedHeader, MemoizedLabel, MemoizedSecondaryButton, MemoizedText, MemoizedPopover, QuillTabs, MemoizedModal, QuillChartBuilderInputRowContainer, QuillChartBuilderInputColumnContainer, MemoizedSubHeader, QuillErrorMessageComponent, QuillPivotRowContainer, QuillPivotColumnContainer, QuillColumnSearchEmptyState, QuillChartBuilderFormContainer, QuillLoadingComponent, QuillTableReportBuilderComponent, QuillChartBuilderCheckboxComponent, QuillToolTip, } from './components/UiComponents';
4
- import { ThemeContext } from './Context';
4
+ import { ClientContext, FetchContext, SchemaDataContext, TenantContext, ThemeContext, } from './Context';
5
5
  import { ChartBuilderWithModal } from './ChartBuilder';
6
6
  import { QuillTextInput } from './components/UiComponents';
7
7
  import { QuillSidebar, CustomContainer, QuillSelectColumn, QuillDraggableColumn, QuillSidebarHeading, QuillFilterPopover, QuillSortPopover, QuillLimitPopover, } from './components/ReportBuilder/ui';
8
+ import { AddSortPopover, SortSentence, } from './components/ReportBuilder/AddSortPopover';
9
+ import { PivotModal } from './internals/ReportBuilder/PivotModal';
10
+ import { snakeAndCamelCaseToTitleCase } from './utils/textProcessing';
11
+ import { AddLimitPopover, LimitSentence, } from './components/ReportBuilder/AddLimitPopover';
8
12
  import { updateFirstChildWidth } from './utils/width';
9
13
  import { QuillSelectComponent } from './components/QuillSelect';
10
14
  import { QuillCard } from './components/QuillCard';
15
+ import { isValidPivot, pivotFormData } from './utils/pivotProcessing';
16
+ import { fetchResultsByQuery, fetchTableByAST, getUniqueStringValuesByTable, } from './utils/tableProcessing';
17
+ import { createSelectStarFromAst, fetchAndProcessASTFromPrompt, fetchASTFromQuillReport, } from './utils/astProcessing';
18
+ import PivotForm from './internals/ReportBuilder/PivotForm';
19
+ import FilterModal from './components/ReportBuilder/FilterModal';
11
20
  import { QuillMultiSelectComponentWithCombo } from './components/QuillMultiSelectWithCombo';
12
- import { SAVED_QUERIES_DASHBOARD } from './utils/constants';
13
- import { useReportBuilderInternal } from './hooks/useReportBuilder';
14
- import { AddColumns } from './components/ReportBuilder/ColumnComponent';
15
- import { AddFilters } from './components/ReportBuilder/FilterComponent';
16
- import { AddPivot } from './components/ReportBuilder/PivotComponent';
17
- import { AddLimit } from './components/ReportBuilder/LimitComponent';
18
- import { AddSort } from './components/ReportBuilder/SortComponent';
19
- import { SaveReport } from './components/ReportBuilder/SaveReport';
20
- import { ReportTable } from './components/ReportBuilder/TableComponent';
21
+ import { DEFAULT_PAGINATION, shouldFetchMore, } from './utils/paginationProcessing';
22
+ import { EMPTY_INTERNAL_REPORT, fetchReportBuilderDataFromAST, formatRowsFromReport, } from './utils/report';
23
+ import { TEMP_REPORT_ID, } from './models/Report';
24
+ import FilterStack from './components/ReportBuilder/FilterStack';
25
+ import { SINGLE_TENANT, SAVED_QUERIES_DASHBOARD } from './utils/constants';
26
+ import { convertQueryToSelectStar } from './components/ReportBuilder/convert';
27
+ import { cleanDashboardItem } from './utils/dashboard';
28
+ import { useAllReports, useDashboardInternal, useDashboards, } from './hooks/useDashboard';
29
+ import { EMPTY_REPORT_BUILDER_STATE, } from './models/ReportBuilder';
30
+ import DraggableColumns from './components/ReportBuilder/DraggableColumns';
31
+ import AddColumnModal from './components/ReportBuilder/AddColumnModal';
32
+ import { astToReportBuilderState, formatRows, isValidPivotForReport, reportBuilderStateToAst, setTypesOnPivot, validatedReportBuilderState, } from './utils/reportBuilder';
33
+ import { fetchSqlQuery } from './utils/dataFetcher';
34
+ import { getSchemaForeignKeyMapping } from './utils/schema';
35
+ import { filterSentence } from './utils/filterProcessing';
21
36
  /**
22
37
  * Quill Report Builder
23
38
  *
@@ -89,45 +104,928 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
89
104
  // isChartBuilderHorizontalView: whether the chart builder is in horizontal view mode
90
105
  // onClickChartElement: a callback function triggered when a chart element is clicked
91
106
  // Contexts
107
+ const { allReportsById } = useAllReports();
108
+ const [schemaData] = useContext(SchemaDataContext);
109
+ const { dashboards } = useDashboards();
110
+ const { data, isLoading: dashboardIsLoading, reload, } = useDashboardInternal(destinationDashboard);
111
+ const { getToken } = useContext(FetchContext);
112
+ const destinationDashboardConfig = useMemo(() => {
113
+ return dashboards?.find((d) => d.name === destinationDashboard);
114
+ }, [dashboards, destinationDashboard]);
115
+ const filteredSchema = useMemo(() => {
116
+ return schemaData.schemaWithCustomFields?.filter((table) => {
117
+ return (destinationDashboardConfig?.tenantKeys?.[0] === SINGLE_TENANT ||
118
+ !table.ownerTenantFields ||
119
+ table.ownerTenantFields?.length === 0 ||
120
+ table.ownerTenantFields?.includes(destinationDashboardConfig?.tenantKeys?.[0] ?? ''));
121
+ });
122
+ }, [
123
+ schemaData.schemaWithCustomFields,
124
+ destinationDashboardConfig?.tenantKeys,
125
+ ]);
126
+ const { tenants } = useContext(TenantContext);
92
127
  const [theme] = useContext(ThemeContext);
128
+ const [client] = useContext(ClientContext);
93
129
  // Refs
94
130
  const parentRef = useRef(null);
95
- const askAIContainerRef = useRef(null);
96
- const [askAIInputWidth, setAskAIInputWidth] = useState(-1);
97
- // UI
98
- const [isCopying, setIsCopying] = useState(false);
131
+ // Consts
132
+ const REPORT_BUILDER_PAGINATION = {
133
+ page: 0,
134
+ rowsPerPage: 20,
135
+ rowsPerRequest: 100,
136
+ };
137
+ // ReportBuilder UI States
99
138
  const [isChartBuilderOpen, setIsChartBuilderOpen] = useState(false);
139
+ const [filtersEnabled, setFiltersEnabled] = useState(!!reportId);
100
140
  const [isSaveQueryModalOpen, setIsSaveQueryModalOpen] = useState(false);
101
- // Main
102
- const reportBuilder = useReportBuilderInternal({
103
- reportId,
104
- initialTableName,
105
- destinationDashboard,
106
- pivotRecommendationsEnabled,
107
- onSaveChanges,
141
+ const [openPopover, setOpenPopover] = useState(null);
142
+ const [aiPrompt, setAiPrompt] = useState('');
143
+ const [reportBuilderLoading, setReportBuilderLoading] = useState(false);
144
+ const [tableLoading, setTableLoading] = useState(false);
145
+ const [errorMessage, setErrorMessage] = useState('');
146
+ const [unresolvedReportMessage, setUnresolvedReportMessage] = useState('');
147
+ // Core Report states
148
+ // Table order matters for joins. For now, assumed to have one 'primary' table (the first one)
149
+ const [tables, setTables] = useState([]);
150
+ const [columns, setColumns] = useState([]);
151
+ const [filterStack, setFilterStack] = useState([]);
152
+ const [pivot, setPivot] = useState(null);
153
+ const [sort, setSort] = useState([]);
154
+ const [limit, setLimit] = useState(null);
155
+ const reportBuilderState = useMemo(() => {
156
+ return {
157
+ tables,
158
+ columns,
159
+ filterStack,
160
+ pivot,
161
+ sort,
162
+ limit,
163
+ };
164
+ }, [columns, filterStack, limit, pivot, sort, tables]);
165
+ // For undo/redo
166
+ const [stateStack, setStateStack] = useState([]);
167
+ const [poppedStateStack, setPoppedStateStack] = useState([]);
168
+ // Other Report states
169
+ const [activeQuery, setActiveQuery] = useState('');
170
+ const [queryOutOfSync, setQueryOutOfSync] = useState(false);
171
+ const [unfilteredUniqueValues, setUnfilteredUniqueValues] = useState({}); // unique values before filtering
172
+ const [unfilteredUniqueValuesIsLoading, setUnfilteredUniqueValuesIsLoading] = useState(false);
173
+ const [filteredUniqueValues, setFilteredUniqueValues] = useState(null); // unique values after filtering
174
+ const [filteredUniqueValuesIsLoading, setFilteredUniqueValuesIsLoading] = useState(false);
175
+ const [columnUniqueValues, setColumnUniqueValues] = useState({});
176
+ const [dateRanges, setDateRanges] = useState(null);
177
+ const [tempReport, setTempReport] = useState({
178
+ ...EMPTY_INTERNAL_REPORT,
179
+ pagination: REPORT_BUILDER_PAGINATION,
180
+ });
181
+ const [currentProcessing, setCurrentProcessing] = useState({
182
+ page: REPORT_BUILDER_PAGINATION,
108
183
  });
109
- const {
110
- // Core state
111
- columns, tables, activeQuery, tempReport, stateStack, poppedStateStack,
112
- // UI state
113
- errorMessage, unresolvedReportMessage, loading, tableLoading, askAILoading,
114
- // Pivot state and handlers
115
- pivot, pivotData, pivotError,
116
- // Schema and client info
117
- // foreignKeyMap,
118
- // AI features
119
- aiPrompt, setAiPrompt, fetchAstFromPromptHelper,
120
- // Action handlers
121
- clearAllState,
122
- // handleMultiStateChange,
123
- // handleColumnsChange,
124
- handleUndo, handleRedo, onSaveQuery, onSaveReport, } = reportBuilder;
184
+ const [previousPage, setPreviousPage] = useState(0);
185
+ const [isCopying, setIsCopying] = useState(false);
186
+ const [sortOrLimitWasReset, setSortOrLimitWasReset] = useState(false);
187
+ // Table display states
188
+ const [reportColumns, setReportColumns] = useState([]);
189
+ const [reportRows, setReportRows] = useState([]);
190
+ const [formattedRows, setFormattedRows] = useState([]);
191
+ const [pivotData, setPivotData] = useState(null);
192
+ const [numberOfRows, setNumberOfRows] = useState(0);
193
+ const [rowCountIsLoading, setRowCountIsLoading] = useState(false);
194
+ const reportColumnsToStateColumns = useMemo(() => {
195
+ const positionMap = {};
196
+ columns.forEach((column, index) => {
197
+ positionMap[column.field] = index;
198
+ if (column.alias) {
199
+ positionMap[column.alias] = index;
200
+ }
201
+ });
202
+ // Sort reportColumns based on the position in columns
203
+ return [...reportColumns]
204
+ .filter((reportColumn) => positionMap[reportColumn.field] !== undefined)
205
+ .sort((a, b) => {
206
+ const posA = positionMap[a.field];
207
+ const posB = positionMap[b.field];
208
+ if (posA !== undefined && posB !== undefined) {
209
+ return posA - posB;
210
+ }
211
+ else {
212
+ return 0;
213
+ }
214
+ });
215
+ }, [columns, reportColumns]);
216
+ // Pivot form states
217
+ const [pivotRowField, setPivotRowField] = useState(undefined);
218
+ const [pivotColumnField, setPivotColumnField] = useState(undefined);
219
+ const [pivotAggregations, setPivotAggregations] = useState([]);
220
+ const [pivotHint, setPivotHint] = useState('');
221
+ const [pivotError, setPivotError] = useState('');
222
+ const [createdPivots, setCreatedPivots] = useState([]);
223
+ const [recommendedPivots, setRecommendedPivots] = useState([]);
224
+ const [pivotPopUpTitle, setPivotPopUpTitle] = useState('Add pivot');
225
+ const [showPivotPopover, setShowPivotPopover] = useState(false);
226
+ const [isEditingPivot, setIsEditingPivot] = useState(false);
227
+ const [selectedPivotIndex, setSelectedPivotIndex] = useState(-1);
228
+ const [pivotRecommendationsEnabledState, setPivotRecommendationsEnabledState,] = useState(pivotRecommendationsEnabled);
229
+ // Ask AI
230
+ const [askAILoading, setAskAILoading] = useState(false);
231
+ const askAIContainerRef = useRef(null);
232
+ const [askAIInputWidth, setAskAIInputWidth] = useState(-1);
233
+ const loading = reportBuilderLoading || tableLoading;
234
+ const isSelectStar = useMemo(() => {
235
+ if (tables.length === 1) {
236
+ // Check if all columns are selected
237
+ const totalColumnLength = tables.reduce((acc, table) => {
238
+ const tableColumns = filteredSchema.find((t) => t.name === table.name)?.columns.length ??
239
+ 0;
240
+ return acc + tableColumns;
241
+ }, 0);
242
+ return totalColumnLength === columns.length;
243
+ }
244
+ else {
245
+ // TODO: Implement this to work with joins
246
+ // SELECT * won't work if joined table has shared column name
247
+ return false;
248
+ }
249
+ }, [tables, columns, filteredSchema]);
250
+ const mssqlSortWarning = useMemo(() => {
251
+ if (!client || client?.databaseType !== 'mssql') {
252
+ return undefined;
253
+ }
254
+ else if (!pivot && !limit) {
255
+ return 'Please add a limit.';
256
+ }
257
+ }, [client, limit, pivot]);
258
+ const foreignKeyMap = useMemo(() => {
259
+ return getSchemaForeignKeyMapping(filteredSchema);
260
+ }, [filteredSchema]);
261
+ // State changing functions
262
+ const clearAllState = (resetStateStack = true) => {
263
+ setActiveQuery('');
264
+ setQueryOutOfSync(false);
265
+ handleMultiStateChange({
266
+ state: EMPTY_REPORT_BUILDER_STATE,
267
+ fetchData: false,
268
+ updateStateStack: true,
269
+ });
270
+ if (resetStateStack) {
271
+ setStateStack([]);
272
+ setPoppedStateStack([]);
273
+ }
274
+ setFilteredUniqueValues(null);
275
+ setUnfilteredUniqueValues({});
276
+ setColumnUniqueValues({});
277
+ setDateRanges(null);
278
+ setTempReport({
279
+ ...EMPTY_INTERNAL_REPORT,
280
+ pagination: REPORT_BUILDER_PAGINATION,
281
+ });
282
+ resetProcessing();
283
+ setReportColumns([]);
284
+ setReportRows([]);
285
+ setFormattedRows([]);
286
+ setPivotData(null);
287
+ setNumberOfRows(0);
288
+ setRowCountIsLoading(false);
289
+ setPivotRowField(undefined);
290
+ setPivotColumnField(undefined);
291
+ setPivotAggregations([]);
292
+ setCreatedPivots([]);
293
+ setRecommendedPivots([]);
294
+ setSelectedPivotIndex(-1);
295
+ setAskAILoading(false);
296
+ setReportBuilderLoading(false);
297
+ setTableLoading(false);
298
+ setPivotError('');
299
+ setErrorMessage('');
300
+ setUnresolvedReportMessage('');
301
+ setPivotHint('');
302
+ };
125
303
  const copySQLToClipboard = () => {
126
304
  const query = pivot && pivotData ? pivotData.pivotQuery : activeQuery;
127
305
  setIsCopying(true);
128
306
  navigator.clipboard.writeText(query);
129
307
  setTimeout(() => setIsCopying(false), 800);
130
308
  };
309
+ const handleTablesChange = (newTables, updateStateStack = true) => {
310
+ setTables(newTables);
311
+ if (updateStateStack) {
312
+ setStateStack((prevStack) => [
313
+ ...prevStack,
314
+ { ...reportBuilderState, tables: newTables },
315
+ ]);
316
+ setPoppedStateStack([]);
317
+ }
318
+ };
319
+ const handleColumnsChange = (newColumns, fetchData, updateStateStack = true, bypassConfirmation = false) => {
320
+ const validReportBuilderState = bypassConfirmation
321
+ ? { ...reportBuilderState, columns: newColumns }
322
+ : validatedReportBuilderState({
323
+ ...reportBuilderState,
324
+ columns: newColumns,
325
+ }, foreignKeyMap);
326
+ if (validReportBuilderState.tables.length === 0 && !bypassConfirmation) {
327
+ if (!confirm('Removing all columns will clear all state. Are you sure you want to continue?')) {
328
+ return;
329
+ }
330
+ else {
331
+ handleMultiStateChange({
332
+ state: EMPTY_REPORT_BUILDER_STATE,
333
+ fetchData: false,
334
+ updateStateStack: true,
335
+ });
336
+ return;
337
+ }
338
+ }
339
+ const tablesAffected = tables.length - validReportBuilderState.tables.length >= 2;
340
+ const filtersAffected = validReportBuilderState.filterStack.length !== filterStack.length;
341
+ const deletedTables = tables
342
+ .filter((table) => {
343
+ return !validReportBuilderState.tables.some((t) => t.name === table.name);
344
+ })
345
+ .map((table) => table.name);
346
+ const deletedFilters = filterStack
347
+ .filter((filter) => filter.value)
348
+ .filter((filter) => {
349
+ return deletedTables.some((table) => table === filter.value.table);
350
+ })
351
+ .map((filter) => filterSentence(filter.value));
352
+ if (tablesAffected && filtersAffected) {
353
+ if (!confirm(`Removing this column will remove the following table${deletedTables.length > 1 ? 's' : ''}:
354
+ ${deletedTables.join(', ')}.
355
+ It will also remove the following filter${deletedFilters.length > 1 ? 's' : ''}:
356
+ ${deletedFilters.join(', ')}.
357
+ Are you sure you want to continue?
358
+ `
359
+ .replace(/\s+/g, ' ')
360
+ .trim())) {
361
+ return;
362
+ }
363
+ }
364
+ else if (tablesAffected) {
365
+ if (!confirm(`Removing this column will remove the following table${deletedTables.length > 1 ? 's' : ''}:
366
+ ${deletedTables.join(', ')}.
367
+ Are you sure you want to continue?
368
+ `
369
+ .replace(/\s+/g, ' ')
370
+ .trim())) {
371
+ return;
372
+ }
373
+ }
374
+ else if (filtersAffected) {
375
+ if (!confirm(`Removing this column will remove the following filter${deletedFilters.length > 1 ? 's' : ''}:
376
+ ${deletedFilters.join(', ')}.
377
+ Are you sure you want to continue?
378
+ `
379
+ .replace(/\s+/g, ' ')
380
+ .trim())) {
381
+ return;
382
+ }
383
+ }
384
+ if (validReportBuilderState.tables.length !== tables.length) {
385
+ handleTablesChange(validReportBuilderState.tables, false);
386
+ fetchData = true;
387
+ }
388
+ if (validReportBuilderState.filterStack.length !== filterStack.length) {
389
+ handleFilterStackChange(validReportBuilderState.filterStack, false, false);
390
+ fetchData = true;
391
+ }
392
+ if (validReportBuilderState.sort.length !== sort.length) {
393
+ handleSortChange(validReportBuilderState.sort, false, false);
394
+ fetchData = true;
395
+ }
396
+ if (pivot && !validReportBuilderState.pivot) {
397
+ handlePivotChange(validReportBuilderState.pivot, false, false);
398
+ }
399
+ setColumns(validReportBuilderState.columns);
400
+ if (updateStateStack) {
401
+ setStateStack((prevStack) => [...prevStack, validReportBuilderState]);
402
+ setPoppedStateStack([]);
403
+ }
404
+ if (fetchData) {
405
+ fetchDataFromReportBuilderState(validReportBuilderState);
406
+ }
407
+ else {
408
+ setQueryOutOfSync(true);
409
+ }
410
+ };
411
+ const handleFilterInsertion = (newFilter) => {
412
+ const newFilterStack = [...filterStack];
413
+ if (newFilterStack.length > 0) {
414
+ const tabNode = {
415
+ leaf: false,
416
+ operator: 'and',
417
+ leftNode: null,
418
+ rightNode: null,
419
+ };
420
+ newFilterStack.push(tabNode);
421
+ }
422
+ const newItem = {
423
+ leaf: true,
424
+ operator: null,
425
+ leftNode: null,
426
+ rightNode: null,
427
+ value: newFilter,
428
+ };
429
+ newFilterStack.push(newItem);
430
+ handleFilterStackChange(newFilterStack, true);
431
+ };
432
+ const handleFilterStackChange = (newFilterStack, fetchData, updateStateStack = true) => {
433
+ setFilterStack(newFilterStack);
434
+ if (newFilterStack.length === 0) {
435
+ setFilteredUniqueValues(null);
436
+ }
437
+ if (updateStateStack) {
438
+ setStateStack((prevStack) => [
439
+ ...prevStack,
440
+ { ...reportBuilderState, filterStack: newFilterStack },
441
+ ]);
442
+ setPoppedStateStack([]);
443
+ }
444
+ if (fetchData) {
445
+ fetchDataFromReportBuilderState({
446
+ ...reportBuilderState,
447
+ filterStack: newFilterStack,
448
+ }, true);
449
+ }
450
+ };
451
+ const handlePivotChange = (newPivot, fetchData, updateStateStack = true) => {
452
+ setPivot(newPivot ? setTypesOnPivot(newPivot, reportColumns) : null);
453
+ setPivotHint('');
454
+ setPivotError('');
455
+ if (!newPivot) {
456
+ setPivotData(null);
457
+ if (!fetchData) {
458
+ const formattedRows = formatRows(reportRows, reportColumns, false);
459
+ setFormattedRows(formattedRows);
460
+ }
461
+ }
462
+ let resetSortAndLimit = false;
463
+ if (!pivot && newPivot && (sort.length > 0 || limit)) {
464
+ setSort([]);
465
+ setLimit(null);
466
+ resetSortAndLimit = true;
467
+ }
468
+ setSortOrLimitWasReset(resetSortAndLimit);
469
+ if (updateStateStack) {
470
+ setStateStack((prevStack) => [
471
+ ...prevStack,
472
+ {
473
+ ...reportBuilderState,
474
+ pivot: newPivot,
475
+ sort: resetSortAndLimit ? [] : sort,
476
+ limit: resetSortAndLimit ? null : limit,
477
+ },
478
+ ]);
479
+ setPoppedStateStack([]);
480
+ }
481
+ if (fetchData) {
482
+ fetchDataFromReportBuilderState({
483
+ ...reportBuilderState,
484
+ pivot: newPivot,
485
+ sort: resetSortAndLimit ? [] : sort,
486
+ limit: resetSortAndLimit ? null : limit,
487
+ }, false, resetSortAndLimit);
488
+ }
489
+ };
490
+ const updatePivot = async (changeField, fieldKey) => {
491
+ if (!client || !pivot) {
492
+ return;
493
+ }
494
+ let newPivot = { ...pivot };
495
+ setPivotError('');
496
+ // @ts-ignore
497
+ newPivot[fieldKey] = changeField;
498
+ newPivot.rowLimit = undefined;
499
+ newPivot.sort = undefined;
500
+ newPivot.sortDirection = undefined;
501
+ newPivot.sortField = undefined;
502
+ newPivot.sortFieldType = undefined;
503
+ if (fieldKey === 'rowField') {
504
+ if (changeField === '' || changeField === undefined) {
505
+ setPivotColumnField(undefined);
506
+ // set all percentage aggregations to undefined
507
+ setPivotAggregations(pivotAggregations.map((agg) => ({
508
+ ...agg,
509
+ aggregationType: agg.aggregationType === 'percentage'
510
+ ? undefined
511
+ : agg.aggregationType,
512
+ })));
513
+ }
514
+ }
515
+ newPivot = setTypesOnPivot(newPivot, reportColumns);
516
+ if (newPivot.aggregations?.length === 0 ||
517
+ newPivot.aggregations?.some((agg) => !agg.aggregationType) ||
518
+ newPivot.aggregations?.some((agg) => !agg.valueField && agg.aggregationType !== 'count')) {
519
+ return;
520
+ }
521
+ const { valid, reason } = isValidPivot(newPivot);
522
+ if (!valid) {
523
+ setPivotError(reason);
524
+ return;
525
+ }
526
+ handlePivotChange(newPivot, true);
527
+ };
528
+ const handleSortChange = (newSort, fetchData, updateStateStack = true) => {
529
+ setSort(newSort);
530
+ if (updateStateStack) {
531
+ setStateStack((prevStack) => [
532
+ ...prevStack,
533
+ { ...reportBuilderState, sort: newSort },
534
+ ]);
535
+ setPoppedStateStack([]);
536
+ }
537
+ if (fetchData) {
538
+ fetchDataFromReportBuilderState({
539
+ ...reportBuilderState,
540
+ sort: newSort,
541
+ });
542
+ }
543
+ };
544
+ const handleLimitChange = (newLimit, fetchData, updateStateStack = true) => {
545
+ setLimit(newLimit);
546
+ if (updateStateStack) {
547
+ setStateStack((prevStack) => [
548
+ ...prevStack,
549
+ { ...reportBuilderState, limit: newLimit },
550
+ ]);
551
+ setPoppedStateStack([]);
552
+ }
553
+ if (fetchData) {
554
+ fetchDataFromReportBuilderState({
555
+ ...reportBuilderState,
556
+ limit: newLimit,
557
+ }, false, true);
558
+ }
559
+ };
560
+ const handleMultiStateChange = ({ state, fetchData, updateStateStack = true, report, skipPivotColumnFetch = false, }) => {
561
+ if (state.tables !== undefined) {
562
+ handleTablesChange(state.tables, false);
563
+ }
564
+ if (state.columns !== undefined) {
565
+ handleColumnsChange(state.columns, false, false, true);
566
+ }
567
+ if (state.filterStack !== undefined) {
568
+ handleFilterStackChange(state.filterStack, false, false);
569
+ }
570
+ if (state.pivot !== undefined) {
571
+ handlePivotChange(state.pivot, false, false);
572
+ }
573
+ if (state.sort !== undefined) {
574
+ handleSortChange(state.sort, false, false);
575
+ }
576
+ if (state.limit !== undefined) {
577
+ handleLimitChange(state.limit, false, false);
578
+ }
579
+ if (updateStateStack) {
580
+ setStateStack((prevStack) => [
581
+ ...prevStack,
582
+ { ...reportBuilderState, ...state },
583
+ ]);
584
+ setPoppedStateStack([]);
585
+ }
586
+ if (fetchData) {
587
+ fetchDataFromReportBuilderState({ ...reportBuilderState, ...state }, !!state.filterStack, !!state.limit, !!state.tables, report, skipPivotColumnFetch);
588
+ }
589
+ };
590
+ const handleUndo = () => {
591
+ if (stateStack.length <= 1) {
592
+ return;
593
+ }
594
+ const previousState = stateStack[stateStack.length - 2];
595
+ setPoppedStateStack((prevStack) => [
596
+ ...prevStack,
597
+ stateStack[stateStack.length - 1],
598
+ ]);
599
+ setStateStack((prevStack) => prevStack.slice(0, -1));
600
+ // Only fetch data if the previous state has columns
601
+ handleMultiStateChange({
602
+ state: previousState,
603
+ fetchData: previousState.columns.length > 0,
604
+ updateStateStack: false,
605
+ });
606
+ };
607
+ const handleRedo = () => {
608
+ if (poppedStateStack.length === 0) {
609
+ return;
610
+ }
611
+ const lastState = poppedStateStack[poppedStateStack.length - 1];
612
+ setStateStack((prevStack) => [...prevStack, lastState]);
613
+ setPoppedStateStack((prevStack) => prevStack.slice(0, -1));
614
+ // Only fetch data if the last state has columns
615
+ handleMultiStateChange({
616
+ state: lastState,
617
+ fetchData: lastState.columns.length > 0,
618
+ updateStateStack: false,
619
+ });
620
+ };
621
+ const fetchDataFromReportBuilderState = (state, filtersChanged, limitChanged, tablesChanged, report, skipPivotColumnFetch) => {
622
+ if (!client) {
623
+ return;
624
+ }
625
+ const ast = reportBuilderStateToAst(state, client.databaseType?.toLowerCase() || 'postgresql');
626
+ fetchReportFromASTHelper({
627
+ ast,
628
+ pivot: state.pivot,
629
+ previousReport: report,
630
+ requiresNewFilteredUniqueValues: filtersChanged || limitChanged,
631
+ requiresNewUnfilteredUniqueValues: tablesChanged,
632
+ skipPivotColumnFetch,
633
+ });
634
+ };
635
+ const fetchReportFromASTHelper = async ({ ast, pivot, previousReport = tempReport, requiresNewFilteredUniqueValues = false, requiresNewUnfilteredUniqueValues = false, skipPivotColumnFetch = false, }) => {
636
+ let reportBuilderInfo = undefined;
637
+ setErrorMessage('');
638
+ const schema = filteredSchema;
639
+ try {
640
+ if (!client || reportBuilderLoading) {
641
+ return;
642
+ }
643
+ setReportBuilderLoading(true);
644
+ reportBuilderInfo = await fetchReportBuilderDataFromAST({
645
+ baseAst: ast,
646
+ schema,
647
+ client,
648
+ tenants,
649
+ pivot: pivot ?? undefined,
650
+ skipPivotColumnFetch,
651
+ previousRelevant: {
652
+ uniqueStringsByTable: unfilteredUniqueValues,
653
+ dateRanges: dateRanges ?? {},
654
+ uniqueStringsByColumn: requiresNewFilteredUniqueValues
655
+ ? {}
656
+ : columnUniqueValues,
657
+ },
658
+ requiresNewFilteredUniqueValues,
659
+ report: previousReport,
660
+ customFields: schemaData.customFields,
661
+ skipUniqueValues: true,
662
+ skipRowCount: true,
663
+ processing: { page: REPORT_BUILDER_PAGINATION },
664
+ dashboardName: destinationDashboard,
665
+ getToken,
666
+ });
667
+ if (reportBuilderInfo.error) {
668
+ throw new Error(reportBuilderInfo.error);
669
+ }
670
+ }
671
+ catch (err) {
672
+ if (err instanceof Error) {
673
+ setErrorMessage(err.message);
674
+ setReportBuilderLoading(false);
675
+ return { error: true, message: err.message, rows: [] };
676
+ }
677
+ setReportBuilderLoading(false);
678
+ setErrorMessage('Failed to fetch');
679
+ return { error: true, message: 'Failed to fetch', rows: [] };
680
+ }
681
+ if (!reportBuilderInfo) {
682
+ setReportBuilderLoading(false);
683
+ setErrorMessage('Failed to fetch');
684
+ return;
685
+ }
686
+ const cleanedReport = await cleanDashboardItem({
687
+ item: reportBuilderInfo.report,
688
+ dashboardFilters: [],
689
+ getToken,
690
+ client,
691
+ customFields: schemaData.customFields,
692
+ skipPivotFetch: true,
693
+ tenants,
694
+ });
695
+ // set tempReport
696
+ setTempReport({
697
+ ...cleanedReport,
698
+ pagination: REPORT_BUILDER_PAGINATION,
699
+ });
700
+ setActiveQuery(reportBuilderInfo.query);
701
+ setQueryOutOfSync(false);
702
+ // table data
703
+ fetchRowCountFromAST(ast, ast.where);
704
+ setReportRows(reportBuilderInfo.rows);
705
+ setFormattedRows(reportBuilderInfo.formattedRows);
706
+ resetProcessing();
707
+ if (!(client.databaseType?.toLowerCase() === 'bigquery') ||
708
+ (reportBuilderInfo.rows && reportBuilderInfo.rows.length > 0)) {
709
+ setReportColumns(reportBuilderInfo.columns);
710
+ }
711
+ setPivotData(reportBuilderInfo.pivotData);
712
+ if (reportBuilderInfo.pivot) {
713
+ setPivotRowField(reportBuilderInfo.pivot.rowField);
714
+ setPivotColumnField(reportBuilderInfo.pivot.columnField);
715
+ setPivotAggregations(reportBuilderInfo.pivot.aggregations ?? [
716
+ {
717
+ valueField: reportBuilderInfo.pivot.valueField,
718
+ valueField2: reportBuilderInfo.pivot.valueField2,
719
+ aggregationType: reportBuilderInfo.pivot.aggregationType,
720
+ },
721
+ ]);
722
+ }
723
+ setPivot(reportBuilderInfo.pivot);
724
+ setPivotHint(reportBuilderInfo.pivotHint);
725
+ setDateRanges(reportBuilderInfo.dateRanges);
726
+ const tableNames = reportBuilderInfo.tables;
727
+ const columnInfo = tableNames.flatMap((table) => {
728
+ const tableInfo = schema.find((tableInfo) => tableInfo.name === table);
729
+ if (!tableInfo) {
730
+ return [];
731
+ }
732
+ return tableInfo.columns.map((col) => ({ ...col, table }));
733
+ });
734
+ setReportBuilderLoading(false);
735
+ // fetch unique values after everything else since it is the most expensive
736
+ try {
737
+ let uniqueStrings = filteredUniqueValues ?? unfilteredUniqueValues;
738
+ let uniqueValuesByColumn = columnUniqueValues;
739
+ if (requiresNewUnfilteredUniqueValues) {
740
+ fetchGlobalUniqueValues(columnInfo, tableNames);
741
+ }
742
+ if (requiresNewFilteredUniqueValues) {
743
+ if (reportBuilderInfo.pivot) {
744
+ // if there's a pivot, these values would have had to been fetched
745
+ uniqueStrings = reportBuilderInfo.uniqueStringsByTable;
746
+ uniqueValuesByColumn = reportBuilderInfo.uniqueStringsByColumn;
747
+ }
748
+ else {
749
+ setFilteredUniqueValuesIsLoading(true);
750
+ const starQuery = await fetchSqlQuery(createSelectStarFromAst(ast), client, getToken);
751
+ uniqueStrings = await getUniqueStringValuesByTable({
752
+ columns: columnInfo,
753
+ tables: tableNames,
754
+ client,
755
+ tenants,
756
+ customFields: schemaData.customFields ?? undefined,
757
+ withExceededColumns: true,
758
+ dashboardName: destinationDashboard,
759
+ queryTemplate: starQuery.query,
760
+ getToken,
761
+ });
762
+ uniqueValuesByColumn = {};
763
+ reportBuilderInfo.reportBuilderColumns.forEach((col) => {
764
+ uniqueValuesByColumn[col.alias || col.field] =
765
+ uniqueStrings[col.table || '']?.[col.field] ?? [];
766
+ });
767
+ }
768
+ }
769
+ setFilteredUniqueValues(uniqueStrings);
770
+ setFilteredUniqueValuesIsLoading(false);
771
+ setColumnUniqueValues(uniqueValuesByColumn);
772
+ }
773
+ catch (err) {
774
+ if (err instanceof Error) {
775
+ setErrorMessage(err.message);
776
+ return { error: true, message: err.message, rows: [] };
777
+ }
778
+ setErrorMessage('Failed to fetch unique values');
779
+ return {
780
+ error: true,
781
+ message: 'Failed to fetch unique values',
782
+ rows: [],
783
+ };
784
+ }
785
+ };
786
+ const fetchRowCountFromAST = async (ast, where) => {
787
+ setRowCountIsLoading(true);
788
+ if (!client) {
789
+ return;
790
+ }
791
+ const tableData = await fetchTableByAST({ ...ast, where }, client, getToken, tenants, destinationDashboard, { page: REPORT_BUILDER_PAGINATION }, schemaData.customFields, false, true);
792
+ if (tableData.rowCount) {
793
+ setNumberOfRows(tableData.rowCount);
794
+ // @ts-ignore
795
+ setTempReport((tempReport) => ({
796
+ ...tempReport,
797
+ rowCount: tableData.rowCount,
798
+ }));
799
+ }
800
+ setRowCountIsLoading(false);
801
+ };
802
+ const fetchAstFromPromptHelper = async (overridePrompt) => {
803
+ let astInfo = {};
804
+ const prompt = overridePrompt || aiPrompt;
805
+ if (!client) {
806
+ return;
807
+ }
808
+ if (!prompt) {
809
+ setErrorMessage('Please supply a prompt.');
810
+ return;
811
+ }
812
+ try {
813
+ setReportBuilderLoading(true);
814
+ setAskAILoading(true);
815
+ setErrorMessage('');
816
+ astInfo = await fetchAndProcessASTFromPrompt({
817
+ aiPrompt: prompt,
818
+ schema: filteredSchema,
819
+ client,
820
+ prevPivot: pivot ?? undefined,
821
+ currentQuery: activeQuery,
822
+ prevTable: tables?.[0]?.name,
823
+ dashboardName: destinationDashboard,
824
+ tenants,
825
+ getToken,
826
+ });
827
+ if (astInfo.error) {
828
+ throw new Error(astInfo.error);
829
+ }
830
+ }
831
+ catch (err) {
832
+ if (err instanceof Error) {
833
+ setErrorMessage(err.message);
834
+ }
835
+ setReportBuilderLoading(false);
836
+ setAskAILoading(false);
837
+ return;
838
+ }
839
+ // check if pivot works with ReportBuilder constraints
840
+ if (Object.keys(columnUniqueValues).length > 0 &&
841
+ astInfo.pivot &&
842
+ !isValidPivotForReport(astInfo.pivot, columnUniqueValues, reportColumns)) {
843
+ astInfo.pivot = null;
844
+ astInfo.ast.groupby = null;
845
+ }
846
+ setAskAILoading(false);
847
+ const newState = astToReportBuilderState(astInfo.ast, client.databaseType || 'postgresql', filteredSchema);
848
+ handleMultiStateChange({
849
+ state: { ...newState, pivot: astInfo.pivot },
850
+ fetchData: true,
851
+ });
852
+ };
853
+ const fetchGlobalUniqueValues = async (columns, tables) => {
854
+ if (!client) {
855
+ return;
856
+ }
857
+ setUnfilteredUniqueValuesIsLoading(true);
858
+ const uniqueStrings = await getUniqueStringValuesByTable({
859
+ columns,
860
+ tables,
861
+ client,
862
+ getToken,
863
+ tenants,
864
+ customFields: schemaData.customFields ?? undefined,
865
+ withExceededColumns: true,
866
+ dashboardName: destinationDashboard,
867
+ });
868
+ setUnfilteredUniqueValues(uniqueStrings);
869
+ setUnfilteredUniqueValuesIsLoading(false);
870
+ };
871
+ const fetchQueryFromReportBuilderState = async (state) => {
872
+ if (!client) {
873
+ return '';
874
+ }
875
+ const ast = reportBuilderStateToAst(state, client.databaseType?.toLowerCase() || 'postgresql');
876
+ const query = await fetchSqlQuery(ast, client, getToken);
877
+ setActiveQuery(query.query);
878
+ return query.query;
879
+ };
880
+ const resetProcessing = () => {
881
+ setCurrentProcessing({ page: REPORT_BUILDER_PAGINATION });
882
+ setPreviousPage(0);
883
+ };
884
+ const handlePagination = async (processing) => {
885
+ try {
886
+ if (!client) {
887
+ return;
888
+ }
889
+ const isPivotPagination = !!(pivot && pivotData);
890
+ setErrorMessage('');
891
+ setTableLoading(true);
892
+ const tableInfo = await fetchResultsByQuery({
893
+ query: isPivotPagination ? pivotData.pivotQuery : activeQuery,
894
+ comparisonQuery: pivot && pivotData ? pivotData.comparisonPivotQuery : undefined,
895
+ client,
896
+ tenants,
897
+ processing,
898
+ customFields: schemaData.customFields,
899
+ rowsOnly: true,
900
+ dashboardName: destinationDashboard,
901
+ pivot: pivot,
902
+ getPivotRowCount: false,
903
+ getToken,
904
+ });
905
+ if (tableInfo.error) {
906
+ throw new Error(tableInfo.error);
907
+ }
908
+ else if (tableInfo.rows.length === 0) {
909
+ throw new Error('No data found');
910
+ }
911
+ if (!isPivotPagination) {
912
+ const tempRows = [...reportRows, ...tableInfo.rows];
913
+ setReportRows(tempRows);
914
+ setFormattedRows(formatRowsFromReport({ rows: tempRows, columns: tableInfo.columns }));
915
+ setTempReport((tempReport) => ({
916
+ ...tempReport,
917
+ rows: tempRows,
918
+ rowCount: tableInfo.rowCount ?? tempReport.rowCount,
919
+ }));
920
+ }
921
+ else {
922
+ const tempRows = [...pivotData.rows, ...tableInfo.rows];
923
+ setPivotData((oldPivotData) => {
924
+ if (oldPivotData) {
925
+ return {
926
+ ...oldPivotData,
927
+ rows: tempRows,
928
+ columns: tableInfo.columns,
929
+ };
930
+ }
931
+ return null;
932
+ });
933
+ setFormattedRows(formatRowsFromReport({ rows: tempRows, columns: tableInfo.columns }));
934
+ }
935
+ setTableLoading(false);
936
+ }
937
+ catch (e) {
938
+ setTableLoading(false);
939
+ setErrorMessage('Failed to run SQL query: ' + e.message);
940
+ setReportRows([]);
941
+ setReportColumns([]);
942
+ return;
943
+ }
944
+ };
945
+ const onPageChange = (page, initiator = 'ReportBuilder') => {
946
+ const pagination = initiator === 'ReportBuilder'
947
+ ? REPORT_BUILDER_PAGINATION
948
+ : DEFAULT_PAGINATION;
949
+ if (currentProcessing.page &&
950
+ shouldFetchMore(pagination, page, previousPage, pivotData ? pivotData.rows.length : reportRows.length)) {
951
+ const newPagination = { ...currentProcessing.page, page };
952
+ const updatedProcessing = { ...currentProcessing, page: newPagination };
953
+ setCurrentProcessing(updatedProcessing);
954
+ handlePagination(updatedProcessing);
955
+ }
956
+ if (page > previousPage) {
957
+ setPreviousPage(page);
958
+ }
959
+ };
960
+ const onSortChange = (newSort, isDelete) => {
961
+ if (!newSort.field) {
962
+ return;
963
+ }
964
+ if (pivot) {
965
+ let newPivot = null;
966
+ if (isDelete) {
967
+ newPivot = {
968
+ ...pivot,
969
+ sort: undefined,
970
+ sortField: undefined,
971
+ sortDirection: undefined,
972
+ sortFieldType: undefined,
973
+ };
974
+ }
975
+ else {
976
+ newPivot = {
977
+ ...pivot,
978
+ sort: true,
979
+ sortField: newSort.field,
980
+ sortDirection: newSort.direction,
981
+ sortFieldType: reportColumns.find((col) => col.field === newSort.field)?.fieldType,
982
+ };
983
+ }
984
+ handlePivotChange(newPivot, true);
985
+ }
986
+ else {
987
+ const updatedSort = [...sort];
988
+ const existingSortIndex = updatedSort.findIndex((item) => item.field === newSort.field);
989
+ if (isDelete) {
990
+ if (existingSortIndex !== -1) {
991
+ updatedSort.splice(existingSortIndex, 1);
992
+ }
993
+ }
994
+ else if (existingSortIndex !== -1) {
995
+ updatedSort[existingSortIndex] = {
996
+ field: newSort.field,
997
+ direction: newSort.direction,
998
+ };
999
+ }
1000
+ else {
1001
+ updatedSort.push({
1002
+ field: newSort.field,
1003
+ direction: newSort.direction,
1004
+ });
1005
+ }
1006
+ handleSortChange(updatedSort, true);
1007
+ }
1008
+ };
1009
+ const onLimitChange = (limit) => {
1010
+ if (limit) {
1011
+ if (pivot) {
1012
+ const newPivot = { ...pivot, rowLimit: limit };
1013
+ handlePivotChange(newPivot, true);
1014
+ }
1015
+ else {
1016
+ handleLimitChange({ value: limit }, true);
1017
+ }
1018
+ }
1019
+ else {
1020
+ if (pivot) {
1021
+ const newPivot = { ...pivot, rowLimit: undefined };
1022
+ handlePivotChange(newPivot, true);
1023
+ }
1024
+ else {
1025
+ handleLimitChange(null, true);
1026
+ }
1027
+ }
1028
+ };
131
1029
  useEffect(() => {
132
1030
  // Since the TextInput component takes a required numeric width parameter,
133
1031
  // we dynamically calculate the width of this component here.
@@ -140,6 +1038,81 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
140
1038
  window.removeEventListener('resize', handleResize);
141
1039
  };
142
1040
  }, []);
1041
+ useEffect(() => {
1042
+ if (!client) {
1043
+ return;
1044
+ }
1045
+ if (client.featureFlags?.['recommendedPivotsDisabled'] !== undefined) {
1046
+ setPivotRecommendationsEnabledState(!client.featureFlags?.['recommendedPivotsDisabled']);
1047
+ }
1048
+ if (!initialTableName && !reportId && client.publicKey) {
1049
+ clearAllState();
1050
+ }
1051
+ }, [client]);
1052
+ // Initialize ReportBuilder with a report
1053
+ useEffect(() => {
1054
+ const loadChart = async () => {
1055
+ let report;
1056
+ if (!client) {
1057
+ return;
1058
+ }
1059
+ try {
1060
+ if (!reportId) {
1061
+ throw new Error('Report ID is required');
1062
+ }
1063
+ report = allReportsById[reportId];
1064
+ if (!report) {
1065
+ console.log('no report');
1066
+ throw new Error('Report not found');
1067
+ }
1068
+ const { ast: newAst, pivot: newPivot } = await fetchASTFromQuillReport(report, client, filteredSchema, getToken);
1069
+ const initialState = astToReportBuilderState(newAst, client.databaseType || 'postgresql', filteredSchema);
1070
+ setTempReport(report);
1071
+ handleMultiStateChange({
1072
+ state: {
1073
+ ...initialState,
1074
+ pivot: newPivot ?? null,
1075
+ },
1076
+ fetchData: true,
1077
+ report,
1078
+ skipPivotColumnFetch: true,
1079
+ });
1080
+ }
1081
+ catch (err) {
1082
+ console.error(err);
1083
+ setErrorMessage('Error when loading chart');
1084
+ }
1085
+ };
1086
+ if (reportId && client) {
1087
+ loadChart();
1088
+ }
1089
+ }, [allReportsById[reportId || ''], client]);
1090
+ useEffect(() => {
1091
+ if (initialTableName) {
1092
+ const tableColumns = filteredSchema.find((table) => {
1093
+ return table.name === initialTableName;
1094
+ })?.columns ?? [];
1095
+ if (tableColumns.length > 0) {
1096
+ handleMultiStateChange({
1097
+ state: {
1098
+ ...EMPTY_REPORT_BUILDER_STATE,
1099
+ tables: [{ name: initialTableName }],
1100
+ columns: tableColumns.map((col) => ({
1101
+ field: col.field,
1102
+ table: initialTableName,
1103
+ })),
1104
+ },
1105
+ fetchData: true,
1106
+ });
1107
+ }
1108
+ }
1109
+ }, [filteredSchema, initialTableName]);
1110
+ useEffect(() => {
1111
+ if (!data && !dashboardIsLoading) {
1112
+ // need dashboard to be in Context for filteredSchema
1113
+ reload();
1114
+ }
1115
+ }, [data, dashboardIsLoading]);
143
1116
  useEffect(() => {
144
1117
  if (isChartBuilderOpen === false) {
145
1118
  onCloseChartBuilder && onCloseChartBuilder();
@@ -156,7 +1129,136 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
156
1129
  : '100%',
157
1130
  overscrollBehavior: 'none',
158
1131
  ...containerStyle,
159
- }, className: className, children: [_jsxs(SidebarComponent, { children: [_jsxs("div", { style: { width: '100%' }, children: [_jsx(SidebarHeadingComponent, { label: "Columns" }), _jsx(AddColumns, { reportBuilder: reportBuilder, ModalComponent: ModalComponent, ButtonComponent: ButtonComponent, DraggableColumnComponent: DraggableColumnComponent, TextInputComponent: TextInputComponent, SelectColumnComponent: SelectColumnComponent, SecondaryButtonComponent: SecondaryButtonComponent, ColumnSearchEmptyState: ColumnSearchEmptyState, LoadingComponent: LoadingComponent })] }), _jsxs("div", { style: { width: '100%' }, children: [_jsx(SidebarHeadingComponent, { label: "Filters" }), _jsx(AddFilters, { reportBuilder: reportBuilder, TabsComponent: TabsComponent, FilterPopoverComponent: FilterPopoverComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, MultiSelectComponent: MultiSelectComponent, PopoverComponent: PopoverComponent })] }), _jsxs("div", { style: { width: '100%' }, children: [_jsx(SidebarHeadingComponent, { label: "Pivot" }), _jsx(AddPivot, { reportBuilder: reportBuilder, parentRef: parentRef, SubHeaderComponent: SubHeaderComponent, DeleteButtonComponent: DeleteButtonComponent, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, CardComponent: CardComponent, SecondaryButtonComponent: SecondaryButtonComponent, PopoverComponent: PopoverComponent, TextComponent: TextComponent, ErrorMessageComponent: ErrorMessageComponent, PivotRowContainer: PivotRowContainer, PivotColumnContainer: PivotColumnContainer, LoadingComponent: LoadingComponent, LabelComponent: LabelComponent, HeaderComponent: HeaderComponent })] }), _jsxs("div", { style: { width: '100%' }, children: [_jsx(SidebarHeadingComponent, { label: "Sort" }), _jsx(AddSort, { reportBuilder: reportBuilder, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, SelectComponent: SelectComponent, PopoverComponent: PopoverComponent, SortPopoverComponent: SortPopoverComponent })] }), _jsxs("div", { style: { width: '100%' }, children: [_jsx(SidebarHeadingComponent, { label: "Limit" }), _jsx(AddLimit, { reportBuilder: reportBuilder, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, TextInputComponent: TextInputComponent, PopoverComponent: PopoverComponent, LimitPopoverComponent: LimitPopoverComponent })] }), _jsx("div", { style: { width: '100%', minHeight: '30vh' } })] }), _jsxs(ContainerComponent, { children: [isAIEnabled && (_jsx("form", { ref: askAIContainerRef, onSubmit: (event) => {
1132
+ }, className: className, children: [_jsxs(SidebarComponent, { children: [_jsxs("div", { style: { width: '100%' }, children: [_jsx(SidebarHeadingComponent, { label: "Columns" }), _jsx(DraggableColumns, { columns: columns, DraggableColumnComponent: DraggableColumnComponent, onColumnOrderChange: handleColumnsChange, loading: loading }), _jsx(SecondaryButtonComponent, { onClick: () => {
1133
+ if (!openPopover) {
1134
+ setOpenPopover('AddColumnModal');
1135
+ }
1136
+ }, label: "Select columns", disabled: loading }), _jsx(ModalComponent, { isOpen: openPopover === 'AddColumnModal', setIsOpen: (isOpen) => {
1137
+ if (!isOpen) {
1138
+ // delay onClose callback so onClick no-ops
1139
+ setTimeout(() => {
1140
+ setOpenPopover(null);
1141
+ }, 100);
1142
+ }
1143
+ }, title: "Select columns", children: _jsx(AddColumnModal, { onSave: (tables, columns) => {
1144
+ handleMultiStateChange({
1145
+ state: {
1146
+ ...EMPTY_REPORT_BUILDER_STATE,
1147
+ tables,
1148
+ columns,
1149
+ },
1150
+ fetchData: true,
1151
+ });
1152
+ setOpenPopover(null);
1153
+ }, selectedTables: tables, selectedColumns: columns, schema: filteredSchema, foreignKeyMap: foreignKeyMap, schemaLoading: schemaData.isSchemaLoading, TextInputComponent: TextInputComponent, SelectColumn: SelectColumnComponent, SecondaryButton: SecondaryButtonComponent, Button: ButtonComponent, ColumnSearchEmptyState: ColumnSearchEmptyState, LoadingComponent: LoadingComponent }) })] }), _jsxs("div", { style: { width: '100%' }, children: [_jsx(SidebarHeadingComponent, { label: "Filters" }), filterStack.length > 0 && (_jsx("div", { style: {
1154
+ display: 'flex',
1155
+ flexDirection: 'column',
1156
+ gap: 8,
1157
+ marginBottom: 12,
1158
+ }, children: _jsx(FilterStack, { client: client, filterStack: filterStack, handleFilterStackChange: handleFilterStackChange, schemaData: schemaData, uniqueValues: unfilteredUniqueValues, uniqueValuesIsLoading: unfilteredUniqueValuesIsLoading, tables: tables, TabsComponent: TabsComponent, FilterPopoverComponent: FilterPopoverComponent, FilterModal: FilterModal, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, MultiSelectComponent: MultiSelectComponent, actionsEnabled: !loading, dashboardName: destinationDashboard, getToken: getToken, reportBuilderColumns: columns }) })), _jsxs("div", { style: {
1159
+ display: 'flex',
1160
+ flexDirection: 'column',
1161
+ alignItems: 'flex-start',
1162
+ }, children: [_jsx(SecondaryButtonComponent, { disabled: columns.length === 0 || loading, onClick: () => {
1163
+ if (!openPopover) {
1164
+ setOpenPopover('AddFilterPopover');
1165
+ }
1166
+ }, label: 'Add filter' }), _jsx("div", { style: {
1167
+ position: 'relative',
1168
+ ...(openPopover === 'AddFilterPopover' && { top: 12 }),
1169
+ }, children: _jsx(PopoverComponent, { isOpen: openPopover === 'AddFilterPopover', setIsOpen: (isOpen) => {
1170
+ if (!isOpen) {
1171
+ setOpenPopover(null);
1172
+ }
1173
+ }, popoverTitle: "Add filter", popoverChildren: _jsx(FilterModal, { schema: filteredSchema, tables: tables.map((table) => table.name), fieldValuesMap: filteredUniqueValues ?? unfilteredUniqueValues, fieldValuesMapIsLoading: filteredUniqueValuesIsLoading ||
1174
+ unfilteredUniqueValuesIsLoading, onSubmitFilter: (filter) => {
1175
+ setOpenPopover(null);
1176
+ handleFilterInsertion(filter);
1177
+ }, hideTableName: tables.length === 1, onDeleteFilter: () => { }, ButtonComponent: ButtonComponent, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, MultiSelectComponent: MultiSelectComponent, reportBuilderColumns: columns }) }) })] })] }), _jsxs("div", { style: { width: '100%' }, children: [_jsx(SidebarHeadingComponent, { label: "Pivot" }), _jsx(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: () => {
1178
+ handlePivotChange(null, sortOrLimitWasReset);
1179
+ }, selectPivot: async (selectedPivot) => {
1180
+ if (!selectedPivot)
1181
+ return;
1182
+ handlePivotChange(selectedPivot, true);
1183
+ }, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent: LabelComponent, HeaderComponent: HeaderComponent, dateRange: undefined, pivotCountRequest: 4, query: activeQuery, initialUniqueValues: columnUniqueValues, uniqueValuesIsLoading: filteredUniqueValuesIsLoading ||
1184
+ unfilteredUniqueValuesIsLoading, disabled: !columns.length || tableLoading || loading, pivotRecommendationsEnabled: pivotRecommendationsEnabledState, report: tempReport, dashboardName: destinationDashboard }), pivot && (_jsx(PivotForm, { columns: reportColumnsToStateColumns, uniqueValues: columnUniqueValues, uniqueValuesIsLoading: filteredUniqueValuesIsLoading ||
1185
+ unfilteredUniqueValuesIsLoading, setPivotRowField: (value) => {
1186
+ setPivotRowField(value);
1187
+ updatePivot(value, 'rowField');
1188
+ }, setPivotColumnField: (value) => {
1189
+ setPivotColumnField(value);
1190
+ updatePivot(value, 'columnField');
1191
+ }, setPivotAggregations: (value) => {
1192
+ setPivotAggregations(value);
1193
+ updatePivot(value, 'aggregations');
1194
+ }, onDelete: () => {
1195
+ handlePivotChange(null, sortOrLimitWasReset);
1196
+ }, isLoading: tableLoading || loading, pivotRowField: pivotRowField, pivotColumnField: pivotColumnField, pivotAggregations: pivotAggregations, SecondaryButtonComponent: SecondaryButtonComponent, SelectComponent: SelectComponent, PivotColumnContainer: PivotColumnContainer, DeleteButtonComponent: DeleteButtonComponent, pivotHint: pivotHint }))] }), _jsxs("div", { style: { width: '100%' }, children: [_jsx(SidebarHeadingComponent, { label: "Sort" }), pivot && pivot.sort && pivot.sortField && (_jsx("div", { style: {
1197
+ display: 'flex',
1198
+ flexDirection: 'column',
1199
+ gap: 8,
1200
+ marginBottom: 12,
1201
+ }, children: _jsx(SortSentence, { sortField: pivot.sortField, sortDirection: pivot.sortDirection || 'ASC', columns: pivotData?.columns ?? [], setOpenPopover: setOpenPopover, SortPopover: SortPopoverComponent, EditPopover: AddSortPopover, handleDelete: async () => {
1202
+ onSortChange({
1203
+ field: pivot.sortField ?? '',
1204
+ direction: pivot.sortDirection ?? 'ASC',
1205
+ }, true);
1206
+ }, onSave: async (column, direction) => {
1207
+ onSortChange({ field: column, direction });
1208
+ }, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, disabled: tableLoading || loading }, `sort-sentence-pivot`) })), sort && sort.length > 0 && (_jsx("div", { style: {
1209
+ display: 'flex',
1210
+ flexDirection: 'column',
1211
+ gap: 8,
1212
+ marginBottom: 12,
1213
+ }, children: sort.map((sortData, id) => (_jsx(SortSentence, { sortField: sortData.field, sortDirection: sortData.direction, columns: reportColumnsToStateColumns, setOpenPopover: setOpenPopover, SortPopover: SortPopoverComponent, EditPopover: AddSortPopover, handleDelete: () => {
1214
+ onSortChange(sortData, true);
1215
+ }, onSave: (column, direction) => {
1216
+ onSortChange({ field: column, direction });
1217
+ }, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, disabled: tableLoading || loading }, `sort-sentence-${id}`))) })), _jsx(SecondaryButtonComponent, { disabled: columns.length === 0 ||
1218
+ loading ||
1219
+ tableLoading ||
1220
+ !!mssqlSortWarning, onClick: () => {
1221
+ if (!openPopover) {
1222
+ setOpenPopover('AddSortPopover');
1223
+ }
1224
+ }, label: 'Add sort', tooltipText: mssqlSortWarning }), _jsx("div", { style: {
1225
+ position: 'relative',
1226
+ ...(openPopover === 'AddSortPopover' && { top: 12 }),
1227
+ }, children: _jsx(PopoverComponent, { isOpen: openPopover === 'AddSortPopover', setIsOpen: (isOpen) => {
1228
+ if (!isOpen) {
1229
+ setOpenPopover(null);
1230
+ }
1231
+ }, popoverTitle: "Sort by", popoverChildren: _jsx(AddSortPopover, { columns: pivotData
1232
+ ? pivotData.columns
1233
+ : reportColumnsToStateColumns, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, onSave: async (column, direction) => {
1234
+ onSortChange({ field: column, direction });
1235
+ setOpenPopover(null);
1236
+ } }) }) })] }), _jsxs("div", { style: { width: '100%' }, children: [_jsx(SidebarHeadingComponent, { label: "Limit" }), limit || pivot?.rowLimit ? (_jsx("div", { style: {
1237
+ display: 'flex',
1238
+ flexDirection: 'column',
1239
+ gap: 8,
1240
+ marginBottom: 12,
1241
+ }, children: _jsx(LimitSentence, { limit: limit?.value || pivot?.rowLimit || 0, setOpenPopover: setOpenPopover, LimitPopover: LimitPopoverComponent, EditPopover: AddLimitPopover, handleDelete: () => {
1242
+ onLimitChange(null);
1243
+ setOpenPopover(null);
1244
+ }, onSave: (limit) => {
1245
+ onLimitChange(limit);
1246
+ setOpenPopover(null);
1247
+ }, TextInput: TextInputComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, disabled: tableLoading || loading }) })) : (_jsxs(_Fragment, { children: [_jsx(SecondaryButtonComponent, { disabled: columns.length === 0 || loading || tableLoading, onClick: () => {
1248
+ if (!openPopover) {
1249
+ setOpenPopover('AddLimitPopover');
1250
+ }
1251
+ }, label: 'Add limit' }), _jsx("div", { style: {
1252
+ position: 'relative',
1253
+ ...(openPopover === 'AddLimitPopover' && { top: 12 }),
1254
+ }, children: _jsx(PopoverComponent, { isOpen: openPopover === 'AddLimitPopover', setIsOpen: (isOpen) => {
1255
+ if (!isOpen) {
1256
+ setOpenPopover(null);
1257
+ }
1258
+ }, popoverTitle: "Add limit", popoverChildren: _jsx(AddLimitPopover, { TextInputComponent: TextInputComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, onSave: (limit) => {
1259
+ onLimitChange(limit);
1260
+ setOpenPopover(null);
1261
+ } }) }) })] }))] }), _jsx("div", { style: { width: '100%', minHeight: '30vh' } })] }), _jsxs(ContainerComponent, { children: [isAIEnabled && (_jsx("form", { ref: askAIContainerRef, onSubmit: (event) => {
160
1262
  event.preventDefault();
161
1263
  }, style: {
162
1264
  display: 'flex',
@@ -172,7 +1274,18 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
172
1274
  if (tables.length <= 1) {
173
1275
  fetchAstFromPromptHelper();
174
1276
  }
175
- }, isLoading: askAILoading && columns.length === 0, label: 'Ask AI' }) }), !reportId && (_jsx(SecondaryButtonComponent, { label: 'New report', onClick: () => clearAllState(false), disabled: columns.length === 0 || loading }))] }) })), columns.length > 0 && (_jsx(ReportTable, { reportBuilder: reportBuilder, TableComponent: TableComponent })), _jsxs("div", { style: {
1277
+ }, isLoading: askAILoading && columns.length === 0, label: 'Ask AI' }) }), !reportId && (_jsx(SecondaryButtonComponent, { label: 'New report', onClick: () => clearAllState(false), disabled: columns.length === 0 || loading }))] }) })), columns.length > 0 && (_jsx(TableComponent, { isLoading: tableLoading || (loading && errorMessage.length === 0), rows: formattedRows, rowCount: pivot ? pivotData?.rowCount : numberOfRows, rowCountIsLoading: rowCountIsLoading, rowsPerPage: 20, columns: pivot
1278
+ ? pivotData?.columns || []
1279
+ : reportColumnsToStateColumns.map((col) => {
1280
+ return {
1281
+ field: col.field,
1282
+ label: snakeAndCamelCaseToTitleCase(col.field),
1283
+ };
1284
+ }), onPageChange: onPageChange, onSortChange: (sort) => {
1285
+ onSortChange(sort);
1286
+ }, disableSort: !!mssqlSortWarning, containerStyle: {
1287
+ maxHeight: Math.max(window.innerHeight - 290, 75 + Math.min(Math.max(10, reportRows.length), 20) * 37),
1288
+ } })), _jsxs("div", { style: {
176
1289
  display: 'flex',
177
1290
  flexDirection: 'row',
178
1291
  gap: '12px',
@@ -189,81 +1302,132 @@ export default function ReportBuilder({ initialTableName = '', onSubmitEditRepor
189
1302
  }, children: [_jsx(ErrorMessageComponent, { errorMessage: errorMessage || pivotError }), aiPrompt.trim().length > 500 && (_jsx(SecondaryButtonComponent, { onClick: () => {
190
1303
  fetchAstFromPromptHelper();
191
1304
  }, label: 'Retry' })), _jsx(SecondaryButtonComponent, { onClick: () => clearAllState(false), label: 'Reset' })] })) : (_jsx("div", { style: { width: '100%' } })), stateStack.length > 0 && (_jsx(SecondaryButtonComponent, { onClick: handleUndo, label: "", icon: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", className: "size-6", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" }) }), disabled: stateStack.length <= 1 || loading })), stateStack.length > 0 && (_jsx(SecondaryButtonComponent, { onClick: handleRedo, label: "", icon: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", className: "size-6", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "m15 15 6-6m0 0-6-6m6 6H9a6 6 0 0 0 0 12h3" }) }), disabled: poppedStateStack.length < 1 || loading })), columns.length > 0 && activeQuery && (_jsxs(_Fragment, { children: [onDiscardChanges && (_jsx(SecondaryButtonComponent, { onClick: onDiscardChanges, label: "Discard changes" })), !hideCopySQL && (_jsx(SecondaryButtonComponent, { label: isCopying ? 'Copied' : 'Copy SQL', onClick: () => copySQLToClipboard() })), !isAdminEnabled || reportId ? null : (_jsx(SecondaryButtonComponent, { onClick: async () => {
192
- onSaveQuery();
1305
+ let tempReportQuery = activeQuery;
1306
+ if (queryOutOfSync) {
1307
+ tempReportQuery =
1308
+ await fetchQueryFromReportBuilderState(reportBuilderState);
1309
+ }
1310
+ const tempReportColumns = columns
1311
+ .map((column) => {
1312
+ return reportColumnsToStateColumns.find((col) => col.field === (column.alias || column.field));
1313
+ })
1314
+ .filter((col) => col !== undefined);
1315
+ let customFieldColumns = [];
1316
+ if (client && isSelectStar && schemaData.customFields) {
1317
+ customFieldColumns = tables.flatMap((table) => {
1318
+ return (schemaData.customFields?.[table.name || ''] || []).map((field) => field.field);
1319
+ });
1320
+ }
1321
+ setTempReport({
1322
+ ...tempReport,
1323
+ ...(pivot
1324
+ ? pivotFormData(pivot, reportColumnsToStateColumns, tempReport, tempReport.chartType, pivotData ?? undefined)
1325
+ : {}),
1326
+ id: TEMP_REPORT_ID,
1327
+ dashboardName: destinationDashboard,
1328
+ pivot: pivot,
1329
+ yAxisFields: tempReport?.pivot && !pivot
1330
+ ? []
1331
+ : tempReport?.yAxisFields,
1332
+ columns: isSelectStar
1333
+ ? // if SELECT *, filter out custom fields from tabular view
1334
+ // so Automatic Custom Fields can be applied
1335
+ tempReportColumns.filter((col) => {
1336
+ return !customFieldColumns.includes(col.field);
1337
+ })
1338
+ : tempReportColumns,
1339
+ columnInternal: isSelectStar
1340
+ ? // if SELECT *, filter out custom fields from tabular view
1341
+ // so Automatic Custom Fields can be applied
1342
+ tempReportColumns.filter((col) => {
1343
+ return !customFieldColumns.includes(col.field);
1344
+ })
1345
+ : tempReportColumns,
1346
+ queryString: isSelectStar
1347
+ ? convertQueryToSelectStar(tempReportQuery)
1348
+ : tempReportQuery,
1349
+ includeCustomFields: isSelectStar,
1350
+ rows: reportRows,
1351
+ pivotRows: pivotData?.rows,
1352
+ pivotColumns: pivotData?.columns,
1353
+ pivotRowCount: pivotData?.rowCount,
1354
+ pivotQuery: pivotData?.pivotQuery,
1355
+ comparisonPivotQuery: pivotData?.comparisonPivotQuery,
1356
+ flags: tempReport?.flags,
1357
+ chartType: 'table',
1358
+ });
193
1359
  setIsSaveQueryModalOpen(true);
194
1360
  }, disabled: !!errorMessage ||
195
1361
  !!pivotError ||
196
1362
  tableLoading ||
197
1363
  loading ||
198
1364
  !!unresolvedReportMessage, label: 'Save query', tooltipText: unresolvedReportMessage })), _jsx(ButtonComponent, { onClick: async () => {
199
- onSaveReport();
1365
+ let tempReportQuery = activeQuery;
1366
+ if (queryOutOfSync) {
1367
+ tempReportQuery =
1368
+ await fetchQueryFromReportBuilderState(reportBuilderState);
1369
+ }
1370
+ onSaveChanges && onSaveChanges();
1371
+ const tempReportColumns = columns
1372
+ .map((column) => {
1373
+ return reportColumnsToStateColumns.find((col) => col.field === (column.alias || column.field));
1374
+ })
1375
+ .filter((col) => col !== undefined);
1376
+ let customFieldColumns = [];
1377
+ if (client && isSelectStar && schemaData.customFields) {
1378
+ customFieldColumns = tables.flatMap((table) => {
1379
+ return (schemaData.customFields?.[table.name || ''] || []).map((field) => field.field);
1380
+ });
1381
+ }
1382
+ setTempReport({
1383
+ ...tempReport,
1384
+ ...(pivot
1385
+ ? pivotFormData(pivot, reportColumnsToStateColumns, tempReport, tempReport.chartType, pivotData ?? undefined)
1386
+ : {}),
1387
+ id: TEMP_REPORT_ID,
1388
+ dashboardName: destinationDashboard,
1389
+ pivot: pivot,
1390
+ yAxisFields: tempReport?.pivot && !pivot
1391
+ ? []
1392
+ : tempReport?.yAxisFields,
1393
+ columns: isSelectStar
1394
+ ? // if SELECT *, filter out custom fields from tabular view
1395
+ // so Automatic Custom Fields can be applied
1396
+ tempReportColumns.filter((col) => {
1397
+ return !customFieldColumns.includes(col.field);
1398
+ })
1399
+ : tempReportColumns,
1400
+ columnInternal: isSelectStar
1401
+ ? // if SELECT *, filter out custom fields from tabular view
1402
+ // so Automatic Custom Fields can be applied
1403
+ tempReportColumns.filter((col) => {
1404
+ return !customFieldColumns.includes(col.field);
1405
+ })
1406
+ : tempReportColumns,
1407
+ queryString: isSelectStar
1408
+ ? convertQueryToSelectStar(tempReportQuery)
1409
+ : tempReportQuery,
1410
+ includeCustomFields: isSelectStar,
1411
+ rows: reportRows,
1412
+ pivotRows: pivotData?.rows,
1413
+ pivotColumns: pivotData?.columns,
1414
+ pivotRowCount: pivotData?.rowCount,
1415
+ pivotQuery: pivotData?.pivotQuery,
1416
+ comparisonPivotQuery: pivotData?.comparisonPivotQuery,
1417
+ flags: tempReport?.flags,
1418
+ });
200
1419
  setIsChartBuilderOpen(true);
201
1420
  }, disabled: !!errorMessage ||
202
1421
  !!pivotError ||
203
1422
  tableLoading ||
204
1423
  loading ||
205
- !!unresolvedReportMessage, label: reportId ? 'Save changes' : 'Add to dashboard', tooltipText: unresolvedReportMessage })] }))] })] }), _jsx("style", { children: `body{margin:0;}` })] })), (!isChartBuilderHorizontalView || isChartBuilderOpen) && (_jsx(SaveReport
206
- // The reason this isn't just using the default trigger and
207
- // directly replacing the Add To Dashboard button above is because
208
- // that button is in a div with overflow: hidden
209
- , {
210
- // The reason this isn't just using the default trigger and
211
- // directly replacing the Add To Dashboard button above is because
212
- // that button is in a div with overflow: hidden
213
- SaveTrigger: null, reportBuilder: reportBuilder, isOpen: isChartBuilderOpen, setIsOpen: setIsChartBuilderOpen, isAdminEnabled: isAdminEnabled, chartBuilderTitle: chartBuilderTitle, onSubmitEditReport: onSubmitEditReport, onSubmitCreateReport: onSubmitCreateReport, destinationSection: destinationSection, ModalComponent: ChartBuilderModalComponent, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, HeaderComponent: HeaderComponent, SubHeaderComponent: SubHeaderComponent, LabelComponent: LabelComponent, TextComponent: TextComponent, CardComponent: CardComponent, PopoverComponent: PopoverComponent, TableComponent: TableComponent, DeleteButtonComponent: DeleteButtonComponent, LoadingComponent: LoadingComponent, ChartBuilderInputRowContainer: ChartBuilderInputRowContainer, ChartBuilderInputColumnContainer: ChartBuilderInputColumnContainer, CheckboxComponent: CheckboxComponent, ChartBuilderFormContainer: ChartBuilderFormContainer, ErrorMessageComponent: ErrorMessageComponent, PivotRowContainer: PivotRowContainer, PivotColumnContainer: PivotColumnContainer, onClickChartElement: onClickChartElement })
214
- // <ChartBuilderWithModal
215
- // tempReport={tempReport}
216
- // reportId={reportId}
217
- // isAdmin={isAdminEnabled}
218
- // title={
219
- // chartBuilderTitle
220
- // ? chartBuilderTitle
221
- // : reportId
222
- // ? 'Save changes'
223
- // : 'Add to dashboard'
224
- // }
225
- // isHorizontalView={true}
226
- // isOpen={isChartBuilderOpen}
227
- // setIsOpen={setIsChartBuilderOpen}
228
- // onAddToDashboardComplete={
229
- // reportId ? onSubmitEditReport : onSubmitCreateReport
230
- // }
231
- // destinationDashboard={destinationDashboard}
232
- // destinationSection={destinationSection}
233
- // organizationName={organizationName}
234
- // initialUniqueValues={columnUniqueValues}
235
- // initialUniqueValuesIsLoading={
236
- // filteredUniqueValuesIsLoading || unfilteredUniqueValuesIsLoading
237
- // }
238
- // pivotRecommendationsEnabled={pivotRecommendationsEnabled}
239
- // SelectComponent={SelectComponent}
240
- // TextInputComponent={TextInputComponent}
241
- // ButtonComponent={ButtonComponent}
242
- // SecondaryButtonComponent={SecondaryButtonComponent}
243
- // HeaderComponent={HeaderComponent}
244
- // SubHeaderComponent={SubHeaderComponent}
245
- // LabelComponent={LabelComponent}
246
- // TextComponent={TextComponent}
247
- // CardComponent={CardComponent}
248
- // ModalComponent={ChartBuilderModalComponent}
249
- // PopoverComponent={PopoverComponent}
250
- // TableComponent={TableComponent}
251
- // DeleteButtonComponent={DeleteButtonComponent}
252
- // LoadingComponent={LoadingComponent}
253
- // ChartBuilderInputRowContainer={ChartBuilderInputRowContainer}
254
- // ChartBuilderInputColumnContainer={ChartBuilderInputColumnContainer}
255
- // CheckboxComponent={CheckboxComponent}
256
- // FormContainer={ChartBuilderFormContainer}
257
- // hideDateRangeFilter={true}
258
- // hideDeleteButton={true}
259
- // buttonLabel={!!reportId ? 'Save changes' : 'Add to dashboard'}
260
- // onClickChartElement={onClickChartElement}
261
- // filtersEnabled={filtersEnabled}
262
- // onFiltersEnabledChanged={(enabled: boolean) => {
263
- // setFiltersEnabled(enabled);
264
- // }}
265
- // isEditingMode={true}
266
- // runQueryOnMount={filtersEnabled}
267
- // />
268
- ), isSaveQueryModalOpen && (_jsx(ChartBuilderWithModal, { isHorizontalView: false, hideTableView: true, hideChartView: true, hidePivotForm: true, hideChartType: true, isOpen: isSaveQueryModalOpen, setIsOpen: setIsSaveQueryModalOpen, onAddToDashboardComplete: onSubmitSaveQuery, destinationDashboard: SAVED_QUERIES_DASHBOARD, destinationSection: destinationSection, 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, isEditingMode: true }))] }));
1424
+ !!unresolvedReportMessage, label: reportId ? 'Save changes' : 'Add to dashboard', tooltipText: unresolvedReportMessage })] }))] })] }), _jsx("style", { children: `body{margin:0;}` })] })), (!isChartBuilderHorizontalView || isChartBuilderOpen) && (_jsx(ChartBuilderWithModal, { tempReport: tempReport, reportId: reportId, isAdmin: isAdminEnabled, title: chartBuilderTitle
1425
+ ? chartBuilderTitle
1426
+ : reportId
1427
+ ? 'Save changes'
1428
+ : 'Add to dashboard', isHorizontalView: true, isOpen: isChartBuilderOpen, setIsOpen: setIsChartBuilderOpen, onAddToDashboardComplete: reportId ? onSubmitEditReport : onSubmitCreateReport, destinationDashboard: destinationDashboard, destinationSection: destinationSection, 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) => {
1429
+ setFiltersEnabled(enabled);
1430
+ }, isEditingMode: true, runQueryOnMount: filtersEnabled })), isSaveQueryModalOpen && (_jsx(ChartBuilderWithModal, { isHorizontalView: false, hideTableView: true, hideChartView: true, hidePivotForm: true, hideChartType: true, isOpen: isSaveQueryModalOpen, setIsOpen: setIsSaveQueryModalOpen, onAddToDashboardComplete: onSubmitSaveQuery, destinationDashboard: SAVED_QUERIES_DASHBOARD, destinationSection: destinationSection, 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,
1431
+ // hide filters table, make it a table chart etc
1432
+ filtersEnabled: filtersEnabled, onFiltersEnabledChanged: (enabled) => setFiltersEnabled(enabled), isEditingMode: true }))] }));
269
1433
  }