@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.
- package/dist/cjs/Chart.d.ts.map +1 -1
- package/dist/cjs/Chart.js +2 -2
- package/dist/cjs/ChartBuilder.d.ts +1 -0
- package/dist/cjs/ChartBuilder.d.ts.map +1 -1
- package/dist/cjs/ChartBuilder.js +48 -14
- package/dist/cjs/ChartEditor.d.ts +1 -1
- package/dist/cjs/ChartEditor.d.ts.map +1 -1
- package/dist/cjs/ChartEditor.js +2 -2
- package/dist/cjs/Context.d.ts.map +1 -1
- package/dist/cjs/Context.js +37 -26
- package/dist/cjs/Dashboard.d.ts +2 -2
- package/dist/cjs/Dashboard.d.ts.map +1 -1
- package/dist/cjs/Dashboard.js +115 -99
- package/dist/cjs/ReportBuilder.d.ts.map +1 -1
- package/dist/cjs/ReportBuilder.js +871 -1574
- package/dist/cjs/SQLEditor.d.ts.map +1 -1
- package/dist/cjs/SQLEditor.js +23 -4
- package/dist/cjs/Table.d.ts.map +1 -1
- package/dist/cjs/components/Chart/CustomReferenceLine.js +1 -1
- package/dist/cjs/components/Chart/GaugeChart.js +0 -6
- package/dist/cjs/components/Dashboard/DashboardFilter.d.ts.map +1 -1
- package/dist/cjs/components/Dashboard/DashboardFilter.js +3 -3
- package/dist/cjs/components/Dashboard/DashboardSection.d.ts +1 -1
- package/dist/cjs/components/Dashboard/DashboardSection.d.ts.map +1 -1
- package/dist/cjs/components/Dashboard/DashboardSection.js +20 -19
- package/dist/cjs/components/Dashboard/MetricComponent.d.ts.map +1 -1
- package/dist/cjs/components/Dashboard/MetricComponent.js +1 -0
- package/dist/cjs/components/Dashboard/TableComponent.d.ts.map +1 -1
- package/dist/cjs/components/Dashboard/TableComponent.js +5 -1
- package/dist/cjs/components/QuillMultiSelectWithCombo.d.ts.map +1 -1
- package/dist/cjs/components/QuillMultiSelectWithCombo.js +58 -8
- package/dist/cjs/components/QuillSelect.d.ts.map +1 -1
- package/dist/cjs/components/QuillSelect.js +91 -14
- package/dist/cjs/components/QuillSelectWithCombo.js +6 -6
- package/dist/cjs/components/ReportBuilder/AddColumnModal.d.ts +6 -16
- package/dist/cjs/components/ReportBuilder/AddColumnModal.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/AddColumnModal.js +172 -75
- package/dist/cjs/components/ReportBuilder/AddSortPopover.d.ts +1 -5
- package/dist/cjs/components/ReportBuilder/AddSortPopover.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/AddSortPopover.js +2 -9
- package/dist/cjs/components/ReportBuilder/DraggableColumns.d.ts +17 -0
- package/dist/cjs/components/ReportBuilder/DraggableColumns.d.ts.map +1 -0
- package/dist/cjs/components/ReportBuilder/DraggableColumns.js +52 -0
- package/dist/cjs/components/ReportBuilder/DraggableItem.d.ts +17 -0
- package/dist/cjs/components/ReportBuilder/DraggableItem.d.ts.map +1 -0
- package/dist/cjs/components/ReportBuilder/DraggableItem.js +17 -0
- package/dist/cjs/components/ReportBuilder/FilterModal.d.ts +6 -12
- package/dist/cjs/components/ReportBuilder/FilterModal.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/FilterModal.js +29 -20
- package/dist/cjs/components/ReportBuilder/FilterStack.d.ts +8 -17
- package/dist/cjs/components/ReportBuilder/FilterStack.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/FilterStack.js +20 -86
- package/dist/cjs/components/ReportBuilder/convert.js +6 -6
- package/dist/cjs/components/ReportBuilder/ui.d.ts +8 -9
- package/dist/cjs/components/ReportBuilder/ui.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/ui.js +30 -8
- package/dist/cjs/components/ReportBuilder/util.d.ts +2 -5
- package/dist/cjs/components/ReportBuilder/util.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/util.js +1 -1
- package/dist/cjs/components/UiComponents.d.ts +3 -2
- package/dist/cjs/components/UiComponents.d.ts.map +1 -1
- package/dist/cjs/components/UiComponents.js +13 -13
- package/dist/cjs/hooks/useAskQuill.d.ts +1 -1
- package/dist/cjs/hooks/useAskQuill.d.ts.map +1 -1
- package/dist/cjs/hooks/useAskQuill.js +14 -12
- package/dist/cjs/hooks/useDashboard.d.ts +5 -3
- package/dist/cjs/hooks/useDashboard.d.ts.map +1 -1
- package/dist/cjs/hooks/useDashboard.js +8 -6
- package/dist/cjs/hooks/useOnClickOutside.d.ts +1 -0
- package/dist/cjs/hooks/useOnClickOutside.d.ts.map +1 -1
- package/dist/cjs/hooks/useOnClickOutside.js +33 -0
- package/dist/cjs/internals/ReportBuilder/PivotForm.d.ts +2 -1
- package/dist/cjs/internals/ReportBuilder/PivotForm.d.ts.map +1 -1
- package/dist/cjs/internals/ReportBuilder/PivotForm.js +22 -15
- package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts +7 -5
- package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
- package/dist/cjs/internals/ReportBuilder/PivotModal.js +100 -48
- package/dist/cjs/models/Client.d.ts +4 -0
- package/dist/cjs/models/Client.d.ts.map +1 -1
- package/dist/cjs/models/Dashboard.d.ts +1 -0
- package/dist/cjs/models/Dashboard.d.ts.map +1 -1
- package/dist/cjs/models/Report.d.ts +2 -0
- package/dist/cjs/models/Report.d.ts.map +1 -1
- package/dist/cjs/models/ReportBuilder.d.ts +46 -0
- package/dist/cjs/models/ReportBuilder.d.ts.map +1 -0
- package/dist/cjs/models/ReportBuilder.js +19 -0
- package/dist/cjs/models/Tables.d.ts +5 -5
- package/dist/cjs/models/Tables.d.ts.map +1 -1
- package/dist/cjs/utils/astFilterProcessing.d.ts +4 -0
- package/dist/cjs/utils/astFilterProcessing.d.ts.map +1 -1
- package/dist/cjs/utils/astFilterProcessing.js +301 -97
- package/dist/cjs/utils/astProcessing.d.ts +14 -4
- package/dist/cjs/utils/astProcessing.d.ts.map +1 -1
- package/dist/cjs/utils/astProcessing.js +38 -4
- package/dist/cjs/utils/dashboard.d.ts.map +1 -1
- package/dist/cjs/utils/dashboard.js +18 -3
- package/dist/cjs/utils/dataFetcher.d.ts.map +1 -1
- package/dist/cjs/utils/dataFetcher.js +4 -3
- package/dist/cjs/utils/filterProcessing.d.ts +2 -11
- package/dist/cjs/utils/filterProcessing.d.ts.map +1 -1
- package/dist/cjs/utils/filterProcessing.js +4 -16
- package/dist/cjs/utils/pivotConstructor.d.ts +2 -1
- package/dist/cjs/utils/pivotConstructor.d.ts.map +1 -1
- package/dist/cjs/utils/pivotConstructor.js +4 -2
- package/dist/cjs/utils/pivotProcessing.d.ts +17 -7
- package/dist/cjs/utils/pivotProcessing.d.ts.map +1 -1
- package/dist/cjs/utils/pivotProcessing.js +60 -51
- package/dist/cjs/utils/queryConstructor.d.ts.map +1 -1
- package/dist/cjs/utils/queryConstructor.js +15 -2
- package/dist/cjs/utils/report.d.ts +12 -9
- package/dist/cjs/utils/report.d.ts.map +1 -1
- package/dist/cjs/utils/report.js +114 -47
- package/dist/cjs/utils/reportBuilder.d.ts +88 -0
- package/dist/cjs/utils/reportBuilder.d.ts.map +1 -0
- package/dist/cjs/utils/reportBuilder.js +395 -0
- package/dist/cjs/utils/schema.d.ts +7 -0
- package/dist/cjs/utils/schema.d.ts.map +1 -1
- package/dist/cjs/utils/schema.js +36 -2
- package/dist/cjs/utils/tableProcessing.d.ts +59 -29
- package/dist/cjs/utils/tableProcessing.d.ts.map +1 -1
- package/dist/cjs/utils/tableProcessing.js +75 -90
- package/dist/cjs/utils/ui.d.ts +2 -0
- package/dist/cjs/utils/ui.d.ts.map +1 -0
- package/dist/cjs/utils/ui.js +18 -0
- package/dist/esm/Chart.d.ts.map +1 -1
- package/dist/esm/Chart.js +2 -2
- package/dist/esm/ChartBuilder.d.ts +1 -0
- package/dist/esm/ChartBuilder.d.ts.map +1 -1
- package/dist/esm/ChartBuilder.js +49 -15
- package/dist/esm/ChartEditor.d.ts +1 -1
- package/dist/esm/ChartEditor.d.ts.map +1 -1
- package/dist/esm/ChartEditor.js +2 -2
- package/dist/esm/Context.d.ts.map +1 -1
- package/dist/esm/Context.js +37 -26
- package/dist/esm/Dashboard.d.ts +2 -2
- package/dist/esm/Dashboard.d.ts.map +1 -1
- package/dist/esm/Dashboard.js +119 -103
- package/dist/esm/ReportBuilder.d.ts.map +1 -1
- package/dist/esm/ReportBuilder.js +878 -1581
- package/dist/esm/SQLEditor.d.ts.map +1 -1
- package/dist/esm/SQLEditor.js +23 -4
- package/dist/esm/Table.d.ts.map +1 -1
- package/dist/esm/components/Chart/CustomReferenceLine.js +1 -1
- package/dist/esm/components/Chart/GaugeChart.js +0 -6
- package/dist/esm/components/Dashboard/DashboardFilter.d.ts.map +1 -1
- package/dist/esm/components/Dashboard/DashboardFilter.js +3 -3
- package/dist/esm/components/Dashboard/DashboardSection.d.ts +1 -1
- package/dist/esm/components/Dashboard/DashboardSection.d.ts.map +1 -1
- package/dist/esm/components/Dashboard/DashboardSection.js +21 -20
- package/dist/esm/components/Dashboard/MetricComponent.d.ts.map +1 -1
- package/dist/esm/components/Dashboard/MetricComponent.js +1 -0
- package/dist/esm/components/Dashboard/TableComponent.d.ts.map +1 -1
- package/dist/esm/components/Dashboard/TableComponent.js +5 -1
- package/dist/esm/components/QuillMultiSelectWithCombo.d.ts.map +1 -1
- package/dist/esm/components/QuillMultiSelectWithCombo.js +57 -7
- package/dist/esm/components/QuillSelect.d.ts.map +1 -1
- package/dist/esm/components/QuillSelect.js +58 -14
- package/dist/esm/components/QuillSelectWithCombo.js +6 -6
- package/dist/esm/components/ReportBuilder/AddColumnModal.d.ts +6 -16
- package/dist/esm/components/ReportBuilder/AddColumnModal.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/AddColumnModal.js +173 -76
- package/dist/esm/components/ReportBuilder/AddSortPopover.d.ts +1 -5
- package/dist/esm/components/ReportBuilder/AddSortPopover.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/AddSortPopover.js +2 -9
- package/dist/esm/components/ReportBuilder/DraggableColumns.d.ts +17 -0
- package/dist/esm/components/ReportBuilder/DraggableColumns.d.ts.map +1 -0
- package/dist/esm/components/ReportBuilder/DraggableColumns.js +46 -0
- package/dist/esm/components/ReportBuilder/DraggableItem.d.ts +17 -0
- package/dist/esm/components/ReportBuilder/DraggableItem.d.ts.map +1 -0
- package/dist/esm/components/ReportBuilder/DraggableItem.js +14 -0
- package/dist/esm/components/ReportBuilder/FilterModal.d.ts +6 -12
- package/dist/esm/components/ReportBuilder/FilterModal.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/FilterModal.js +29 -20
- package/dist/esm/components/ReportBuilder/FilterStack.d.ts +8 -17
- package/dist/esm/components/ReportBuilder/FilterStack.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/FilterStack.js +21 -87
- package/dist/esm/components/ReportBuilder/convert.js +6 -6
- package/dist/esm/components/ReportBuilder/ui.d.ts +8 -9
- package/dist/esm/components/ReportBuilder/ui.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/ui.js +33 -11
- package/dist/esm/components/ReportBuilder/util.d.ts +2 -5
- package/dist/esm/components/ReportBuilder/util.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/util.js +1 -1
- package/dist/esm/components/UiComponents.d.ts +3 -2
- package/dist/esm/components/UiComponents.d.ts.map +1 -1
- package/dist/esm/components/UiComponents.js +13 -13
- package/dist/esm/hooks/useAskQuill.d.ts +1 -1
- package/dist/esm/hooks/useAskQuill.d.ts.map +1 -1
- package/dist/esm/hooks/useAskQuill.js +14 -12
- package/dist/esm/hooks/useDashboard.d.ts +5 -3
- package/dist/esm/hooks/useDashboard.d.ts.map +1 -1
- package/dist/esm/hooks/useDashboard.js +8 -6
- package/dist/esm/hooks/useOnClickOutside.d.ts +1 -0
- package/dist/esm/hooks/useOnClickOutside.d.ts.map +1 -1
- package/dist/esm/hooks/useOnClickOutside.js +31 -0
- package/dist/esm/internals/ReportBuilder/PivotForm.d.ts +2 -1
- package/dist/esm/internals/ReportBuilder/PivotForm.d.ts.map +1 -1
- package/dist/esm/internals/ReportBuilder/PivotForm.js +23 -16
- package/dist/esm/internals/ReportBuilder/PivotModal.d.ts +7 -5
- package/dist/esm/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
- package/dist/esm/internals/ReportBuilder/PivotModal.js +101 -49
- package/dist/esm/models/Client.d.ts +4 -0
- package/dist/esm/models/Client.d.ts.map +1 -1
- package/dist/esm/models/Dashboard.d.ts +1 -0
- package/dist/esm/models/Dashboard.d.ts.map +1 -1
- package/dist/esm/models/Report.d.ts +2 -0
- package/dist/esm/models/Report.d.ts.map +1 -1
- package/dist/esm/models/ReportBuilder.d.ts +46 -0
- package/dist/esm/models/ReportBuilder.d.ts.map +1 -0
- package/dist/esm/models/ReportBuilder.js +16 -0
- package/dist/esm/models/Tables.d.ts +5 -5
- package/dist/esm/models/Tables.d.ts.map +1 -1
- package/dist/esm/utils/astFilterProcessing.d.ts +4 -0
- package/dist/esm/utils/astFilterProcessing.d.ts.map +1 -1
- package/dist/esm/utils/astFilterProcessing.js +300 -97
- package/dist/esm/utils/astProcessing.d.ts +14 -4
- package/dist/esm/utils/astProcessing.d.ts.map +1 -1
- package/dist/esm/utils/astProcessing.js +38 -5
- package/dist/esm/utils/dashboard.d.ts.map +1 -1
- package/dist/esm/utils/dashboard.js +18 -3
- package/dist/esm/utils/dataFetcher.d.ts.map +1 -1
- package/dist/esm/utils/dataFetcher.js +4 -3
- package/dist/esm/utils/filterProcessing.d.ts +2 -11
- package/dist/esm/utils/filterProcessing.d.ts.map +1 -1
- package/dist/esm/utils/filterProcessing.js +4 -15
- package/dist/esm/utils/pivotConstructor.d.ts +2 -1
- package/dist/esm/utils/pivotConstructor.d.ts.map +1 -1
- package/dist/esm/utils/pivotConstructor.js +4 -2
- package/dist/esm/utils/pivotProcessing.d.ts +17 -7
- package/dist/esm/utils/pivotProcessing.d.ts.map +1 -1
- package/dist/esm/utils/pivotProcessing.js +58 -49
- package/dist/esm/utils/queryConstructor.d.ts.map +1 -1
- package/dist/esm/utils/queryConstructor.js +15 -2
- package/dist/esm/utils/report.d.ts +12 -9
- package/dist/esm/utils/report.d.ts.map +1 -1
- package/dist/esm/utils/report.js +116 -46
- package/dist/esm/utils/reportBuilder.d.ts +88 -0
- package/dist/esm/utils/reportBuilder.d.ts.map +1 -0
- package/dist/esm/utils/reportBuilder.js +386 -0
- package/dist/esm/utils/schema.d.ts +7 -0
- package/dist/esm/utils/schema.d.ts.map +1 -1
- package/dist/esm/utils/schema.js +34 -1
- package/dist/esm/utils/tableProcessing.d.ts +59 -29
- package/dist/esm/utils/tableProcessing.d.ts.map +1 -1
- package/dist/esm/utils/tableProcessing.js +71 -86
- package/dist/esm/utils/ui.d.ts +2 -0
- package/dist/esm/utils/ui.d.ts.map +1 -0
- package/dist/esm/utils/ui.js +14 -0
- 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
|
|
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 {
|
|
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
|
|
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
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
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 [
|
|
124
|
-
|
|
125
|
-
|
|
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 [
|
|
136
|
-
|
|
137
|
-
const
|
|
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
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
168
|
-
|
|
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
|
-
|
|
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 && !
|
|
244
|
+
else if (!pivot && !limit) {
|
|
178
245
|
return 'Please add a limit.';
|
|
179
246
|
}
|
|
180
|
-
}, [client,
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
|
|
186
|
-
|
|
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
|
-
|
|
189
|
-
|
|
330
|
+
setColumns(newColumns);
|
|
331
|
+
if (updateStateStack) {
|
|
332
|
+
setStateStack((prevStack) => [
|
|
333
|
+
...prevStack,
|
|
334
|
+
{ ...reportBuilderState, columns: newColumns },
|
|
335
|
+
]);
|
|
190
336
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
-
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
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
|
-
(
|
|
215
|
-
|
|
216
|
-
|
|
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
|
-
|
|
222
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
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
|
-
|
|
396
|
-
|
|
397
|
-
|
|
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
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
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
|
-
|
|
539
|
-
|
|
540
|
-
|
|
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
|
|
640
|
-
|
|
641
|
-
|
|
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
|
-
|
|
664
|
-
|
|
494
|
+
if (state.columns !== undefined) {
|
|
495
|
+
handleColumnsChange(state.columns, false, false);
|
|
665
496
|
}
|
|
666
|
-
|
|
667
|
-
|
|
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
|
-
|
|
701
|
-
|
|
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
|
-
|
|
717
|
-
|
|
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
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
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
|
-
|
|
904
|
-
|
|
515
|
+
if (fetchData) {
|
|
516
|
+
fetchDataFromReportBuilderState({ ...reportBuilderState, ...state }, !!state.filterStack, !!state.tables);
|
|
905
517
|
}
|
|
906
|
-
setOpenPopover(null);
|
|
907
518
|
};
|
|
908
|
-
const
|
|
909
|
-
if (
|
|
519
|
+
const handleUndo = () => {
|
|
520
|
+
if (stateStack.length <= 1) {
|
|
910
521
|
return;
|
|
911
522
|
}
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
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
|
|
939
|
-
|
|
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
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
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
|
|
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
|
-
|
|
544
|
+
if (!client || reportBuilderLoading) {
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
setReportBuilderLoading(true);
|
|
1054
548
|
reportBuilderInfo = await (0, report_1.fetchReportBuilderDataFromAST)({
|
|
1055
|
-
baseAst,
|
|
1056
|
-
|
|
1057
|
-
schema: curSchema ?? schemaData.schemaWithCustomFields,
|
|
549
|
+
baseAst: ast,
|
|
550
|
+
schema,
|
|
1058
551
|
client,
|
|
1059
552
|
tenants,
|
|
1060
|
-
pivot:
|
|
1061
|
-
previousFormData: formData,
|
|
1062
|
-
currentTable,
|
|
553
|
+
pivot: pivot ?? undefined,
|
|
1063
554
|
previousRelevant: {
|
|
1064
|
-
|
|
555
|
+
uniqueStringsByTable: unfilteredUniqueValues,
|
|
1065
556
|
dateRanges: dateRanges ?? {},
|
|
557
|
+
uniqueStringsByColumn: requiresNewFilteredUniqueValues
|
|
558
|
+
? {}
|
|
559
|
+
: columnUniqueValues,
|
|
1066
560
|
},
|
|
1067
|
-
|
|
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
|
-
|
|
576
|
+
setReportBuilderLoading(false);
|
|
1082
577
|
return { error: true, message: err.message, rows: [] };
|
|
1083
578
|
}
|
|
1084
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
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
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
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
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
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
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
setErrorMessage(
|
|
1223
|
-
|
|
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
|
-
|
|
1227
|
-
|
|
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
|
-
|
|
709
|
+
setReportBuilderLoading(true);
|
|
1239
710
|
setAskAILoading(true);
|
|
1240
711
|
setErrorMessage('');
|
|
1241
|
-
astInfo = await (0, astProcessing_1.fetchAndProcessASTFromPrompt)(
|
|
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
|
-
|
|
730
|
+
setReportBuilderLoading(false);
|
|
1251
731
|
setAskAILoading(false);
|
|
1252
732
|
return;
|
|
1253
733
|
}
|
|
1254
734
|
// check if pivot works with ReportBuilder constraints
|
|
1255
|
-
if (
|
|
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
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
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
|
|
1283
|
-
|
|
1284
|
-
|
|
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
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
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
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
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
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
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 (
|
|
1363
|
-
|
|
837
|
+
if (page > previousPage) {
|
|
838
|
+
setPreviousPage(page);
|
|
1364
839
|
}
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
840
|
+
};
|
|
841
|
+
const onSortChange = (newSort, isDelete) => {
|
|
842
|
+
if (!newSort.field) {
|
|
843
|
+
return;
|
|
1368
844
|
}
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
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
|
-
|
|
1376
|
-
|
|
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
|
|
1381
|
-
if (
|
|
1382
|
-
|
|
1383
|
-
|
|
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
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
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
|
|
1392
|
-
|
|
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
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
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
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
}
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
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
|
-
|
|
1456
|
-
|
|
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
|
-
|
|
1462
|
-
|
|
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
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
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
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
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
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
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)(
|
|
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:
|
|
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
|
-
|
|
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
|
-
},
|
|
1517
|
-
|
|
1518
|
-
|
|
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,
|
|
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:
|
|
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:
|
|
1579
|
-
|
|
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
|
-
|
|
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:
|
|
1583
|
-
|
|
1584
|
-
|
|
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
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
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'
|
|
1049
|
+
updatePivot(value, 'rowField');
|
|
1649
1050
|
}, setPivotColumnField: (value) => {
|
|
1650
|
-
const prev = pivotColumnField;
|
|
1651
1051
|
setPivotColumnField(value);
|
|
1652
|
-
updatePivot(value, 'columnField'
|
|
1052
|
+
updatePivot(value, 'columnField');
|
|
1653
1053
|
}, setPivotAggregations: (value) => {
|
|
1654
|
-
const prev = pivotAggregations;
|
|
1655
1054
|
setPivotAggregations(value);
|
|
1656
|
-
updatePivot(value, 'aggregations'
|
|
1055
|
+
updatePivot(value, 'aggregations');
|
|
1657
1056
|
}, onDelete: () => {
|
|
1658
|
-
|
|
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 ?? [],
|
|
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`) })),
|
|
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:
|
|
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:
|
|
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
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
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:
|
|
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
|
-
|
|
1798
|
-
|
|
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
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
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
|
-
|
|
1837
|
-
|
|
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,
|
|
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
|
|
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%' } })),
|
|
1860
|
-
const tempReportColumns =
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
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
|
-
...
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
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 =
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
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
|
-
...
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
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:
|
|
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
|