@quillsql/react 2.11.15 → 2.11.17
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 +117 -42
- package/dist/cjs/Chart.d.ts.map +1 -1
- package/dist/cjs/Chart.js +44 -18
- package/dist/cjs/ChartBuilder.d.ts +195 -28
- package/dist/cjs/ChartBuilder.d.ts.map +1 -1
- package/dist/cjs/ChartBuilder.js +124 -63
- package/dist/cjs/ChartEditor.d.ts +114 -18
- package/dist/cjs/ChartEditor.d.ts.map +1 -1
- package/dist/cjs/ChartEditor.js +47 -15
- package/dist/cjs/Dashboard.d.ts +148 -90
- package/dist/cjs/Dashboard.d.ts.map +1 -1
- package/dist/cjs/Dashboard.js +46 -152
- package/dist/cjs/DateRangePicker/QuillDateRangePicker.d.ts +21 -1
- package/dist/cjs/DateRangePicker/QuillDateRangePicker.d.ts.map +1 -1
- package/dist/cjs/DateRangePicker/QuillDateRangePicker.js +5 -2
- package/dist/cjs/DateRangePicker/dateRangePickerUtils.js +1 -1
- package/dist/cjs/QuillProvider.d.ts +105 -2
- package/dist/cjs/QuillProvider.d.ts.map +1 -1
- package/dist/cjs/QuillProvider.js +59 -0
- package/dist/cjs/ReportBuilder.d.ts +188 -34
- package/dist/cjs/ReportBuilder.d.ts.map +1 -1
- package/dist/cjs/ReportBuilder.js +551 -426
- package/dist/cjs/SQLEditor.d.ts +158 -29
- package/dist/cjs/SQLEditor.d.ts.map +1 -1
- package/dist/cjs/SQLEditor.js +52 -32
- package/dist/cjs/Table.d.ts +119 -15
- package/dist/cjs/Table.d.ts.map +1 -1
- package/dist/cjs/Table.js +37 -6
- package/dist/cjs/TableChart.d.ts.map +1 -1
- package/dist/cjs/TableChart.js +0 -194
- package/dist/cjs/{BarList.d.ts → components/Chart/BarList.d.ts} +1 -1
- package/dist/cjs/components/Chart/BarList.d.ts.map +1 -0
- package/dist/cjs/{BarList.js → components/Chart/BarList.js} +1 -1
- package/dist/cjs/components/Chart/LineChart.d.ts +2 -3
- package/dist/cjs/components/Chart/LineChart.d.ts.map +1 -1
- package/dist/cjs/components/Chart/LineChart.js +3 -3
- package/dist/cjs/components/Chart/PieChart.d.ts.map +1 -0
- package/dist/cjs/{PieChart.js → components/Chart/PieChart.js} +1 -1
- package/dist/cjs/components/Dashboard/ChartComponent.d.ts +2 -1
- package/dist/cjs/components/Dashboard/ChartComponent.d.ts.map +1 -1
- package/dist/cjs/components/Dashboard/ChartComponent.js +6 -7
- package/dist/cjs/components/Dashboard/DashboardFilter.d.ts +22 -0
- package/dist/cjs/components/Dashboard/DashboardFilter.d.ts.map +1 -0
- package/dist/cjs/components/Dashboard/DashboardFilter.js +75 -0
- package/dist/cjs/components/Dashboard/DataLoader.d.ts +1 -1
- package/dist/cjs/components/Dashboard/DataLoader.d.ts.map +1 -1
- package/dist/cjs/components/Dashboard/DataLoader.js +1 -1
- package/dist/cjs/components/Dashboard/MetricComponent.d.ts +2 -12
- package/dist/cjs/components/Dashboard/MetricComponent.d.ts.map +1 -1
- package/dist/cjs/components/Dashboard/MetricComponent.js +39 -17
- package/dist/cjs/components/Dashboard/TableComponent.d.ts +2 -1
- package/dist/cjs/components/Dashboard/TableComponent.d.ts.map +1 -1
- package/dist/cjs/components/Dashboard/TableComponent.js +6 -9
- package/dist/cjs/components/QuillSelect.d.ts +4 -1
- package/dist/cjs/components/QuillSelect.d.ts.map +1 -1
- package/dist/cjs/components/QuillSelect.js +13 -8
- package/dist/cjs/components/QuillTable.d.ts +16 -2
- package/dist/cjs/components/QuillTable.d.ts.map +1 -1
- package/dist/cjs/components/QuillTable.js +4 -4
- package/dist/cjs/components/ReportBuilder/AddColumnPopover.d.ts +30 -1
- package/dist/cjs/components/ReportBuilder/AddColumnPopover.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/AddColumnPopover.js +33 -14
- package/dist/cjs/components/ReportBuilder/AddLimitPopover.d.ts +25 -2
- package/dist/cjs/components/ReportBuilder/AddLimitPopover.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/AddLimitPopover.js +19 -19
- package/dist/cjs/components/ReportBuilder/AddSortPopover.d.ts +22 -2
- package/dist/cjs/components/ReportBuilder/AddSortPopover.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/AddSortPopover.js +18 -20
- package/dist/cjs/components/ReportBuilder/bigDateMap.js +1 -1
- package/dist/cjs/components/ReportBuilder/convert.d.ts +2 -1
- package/dist/cjs/components/ReportBuilder/convert.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/convert.js +40 -20
- package/dist/cjs/components/ReportBuilder/pivot.d.ts +2 -1
- package/dist/cjs/components/ReportBuilder/pivot.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/ui.d.ts +83 -19
- package/dist/cjs/components/ReportBuilder/ui.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/ui.js +68 -121
- package/dist/cjs/components/ReportBuilder/util.d.ts +3 -1
- package/dist/cjs/components/ReportBuilder/util.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/util.js +34 -8
- package/dist/cjs/components/UiComponents.d.ts +98 -97
- package/dist/cjs/components/UiComponents.d.ts.map +1 -1
- package/dist/cjs/components/UiComponents.js +132 -112
- package/dist/cjs/hooks/index.d.ts +1 -0
- package/dist/cjs/hooks/index.d.ts.map +1 -1
- package/dist/cjs/hooks/index.js +3 -1
- package/dist/cjs/hooks/useTheme.d.ts +7 -0
- package/dist/cjs/hooks/useTheme.d.ts.map +1 -0
- package/dist/cjs/hooks/useTheme.js +12 -0
- package/dist/cjs/index.d.ts +10 -2
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/internals/ReportBuilder/PivotList.d.ts.map +1 -1
- package/dist/cjs/internals/ReportBuilder/PivotList.js +10 -10
- package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts +29 -14
- package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
- package/dist/cjs/internals/ReportBuilder/PivotModal.js +73 -49
- package/dist/cjs/utils/dataFetcher.d.ts.map +1 -1
- package/dist/cjs/utils/dataFetcher.js +2 -0
- package/dist/cjs/utils/width.d.ts +12 -0
- package/dist/cjs/utils/width.d.ts.map +1 -0
- package/dist/cjs/utils/width.js +25 -0
- package/dist/esm/Chart.d.ts +117 -42
- package/dist/esm/Chart.d.ts.map +1 -1
- package/dist/esm/Chart.js +45 -19
- package/dist/esm/ChartBuilder.d.ts +195 -28
- package/dist/esm/ChartBuilder.d.ts.map +1 -1
- package/dist/esm/ChartBuilder.js +124 -63
- package/dist/esm/ChartEditor.d.ts +114 -18
- package/dist/esm/ChartEditor.d.ts.map +1 -1
- package/dist/esm/ChartEditor.js +51 -19
- package/dist/esm/Dashboard.d.ts +148 -90
- package/dist/esm/Dashboard.d.ts.map +1 -1
- package/dist/esm/Dashboard.js +49 -153
- package/dist/esm/DateRangePicker/QuillDateRangePicker.d.ts +21 -1
- package/dist/esm/DateRangePicker/QuillDateRangePicker.d.ts.map +1 -1
- package/dist/esm/DateRangePicker/QuillDateRangePicker.js +6 -3
- package/dist/esm/DateRangePicker/dateRangePickerUtils.js +1 -1
- package/dist/esm/QuillProvider.d.ts +105 -2
- package/dist/esm/QuillProvider.d.ts.map +1 -1
- package/dist/esm/QuillProvider.js +59 -0
- package/dist/esm/ReportBuilder.d.ts +188 -34
- package/dist/esm/ReportBuilder.d.ts.map +1 -1
- package/dist/esm/ReportBuilder.js +553 -428
- package/dist/esm/SQLEditor.d.ts +158 -29
- package/dist/esm/SQLEditor.d.ts.map +1 -1
- package/dist/esm/SQLEditor.js +53 -33
- package/dist/esm/Table.d.ts +119 -15
- package/dist/esm/Table.d.ts.map +1 -1
- package/dist/esm/Table.js +38 -7
- package/dist/esm/TableChart.d.ts.map +1 -1
- package/dist/esm/TableChart.js +0 -194
- package/dist/esm/{BarList.d.ts → components/Chart/BarList.d.ts} +1 -1
- package/dist/esm/components/Chart/BarList.d.ts.map +1 -0
- package/dist/esm/{BarList.js → components/Chart/BarList.js} +1 -1
- package/dist/esm/components/Chart/LineChart.d.ts +2 -3
- package/dist/esm/components/Chart/LineChart.d.ts.map +1 -1
- package/dist/esm/components/Chart/LineChart.js +3 -3
- package/dist/esm/components/Chart/PieChart.d.ts.map +1 -0
- package/dist/esm/{PieChart.js → components/Chart/PieChart.js} +1 -1
- package/dist/esm/components/Dashboard/ChartComponent.d.ts +2 -1
- package/dist/esm/components/Dashboard/ChartComponent.d.ts.map +1 -1
- package/dist/esm/components/Dashboard/ChartComponent.js +5 -6
- package/dist/esm/components/Dashboard/DashboardFilter.d.ts +22 -0
- package/dist/esm/components/Dashboard/DashboardFilter.d.ts.map +1 -0
- package/dist/esm/components/Dashboard/DashboardFilter.js +71 -0
- package/dist/esm/components/Dashboard/DataLoader.d.ts +1 -1
- package/dist/esm/components/Dashboard/DataLoader.d.ts.map +1 -1
- package/dist/esm/components/Dashboard/DataLoader.js +1 -1
- package/dist/esm/components/Dashboard/MetricComponent.d.ts +2 -12
- package/dist/esm/components/Dashboard/MetricComponent.d.ts.map +1 -1
- package/dist/esm/components/Dashboard/MetricComponent.js +39 -17
- package/dist/esm/components/Dashboard/TableComponent.d.ts +2 -1
- package/dist/esm/components/Dashboard/TableComponent.d.ts.map +1 -1
- package/dist/esm/components/Dashboard/TableComponent.js +6 -9
- package/dist/esm/components/QuillSelect.d.ts +4 -1
- package/dist/esm/components/QuillSelect.d.ts.map +1 -1
- package/dist/esm/components/QuillSelect.js +14 -9
- package/dist/esm/components/QuillTable.d.ts +16 -2
- package/dist/esm/components/QuillTable.d.ts.map +1 -1
- package/dist/esm/components/QuillTable.js +4 -4
- package/dist/esm/components/ReportBuilder/AddColumnPopover.d.ts +30 -1
- package/dist/esm/components/ReportBuilder/AddColumnPopover.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/AddColumnPopover.js +34 -15
- package/dist/esm/components/ReportBuilder/AddLimitPopover.d.ts +25 -2
- package/dist/esm/components/ReportBuilder/AddLimitPopover.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/AddLimitPopover.js +20 -20
- package/dist/esm/components/ReportBuilder/AddSortPopover.d.ts +22 -2
- package/dist/esm/components/ReportBuilder/AddSortPopover.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/AddSortPopover.js +20 -22
- package/dist/esm/components/ReportBuilder/bigDateMap.js +1 -1
- package/dist/esm/components/ReportBuilder/convert.d.ts +2 -1
- package/dist/esm/components/ReportBuilder/convert.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/convert.js +33 -13
- package/dist/esm/components/ReportBuilder/pivot.d.ts +2 -1
- package/dist/esm/components/ReportBuilder/pivot.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/ui.d.ts +83 -19
- package/dist/esm/components/ReportBuilder/ui.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/ui.js +67 -119
- package/dist/esm/components/ReportBuilder/util.d.ts +3 -1
- package/dist/esm/components/ReportBuilder/util.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/util.js +31 -7
- package/dist/esm/components/UiComponents.d.ts +98 -97
- package/dist/esm/components/UiComponents.d.ts.map +1 -1
- package/dist/esm/components/UiComponents.js +125 -110
- package/dist/esm/hooks/index.d.ts +1 -0
- package/dist/esm/hooks/index.d.ts.map +1 -1
- package/dist/esm/hooks/index.js +1 -0
- package/dist/esm/hooks/useTheme.d.ts +7 -0
- package/dist/esm/hooks/useTheme.d.ts.map +1 -0
- package/dist/esm/hooks/useTheme.js +10 -0
- package/dist/esm/index.d.ts +10 -2
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/internals/ReportBuilder/PivotList.d.ts.map +1 -1
- package/dist/esm/internals/ReportBuilder/PivotList.js +10 -10
- package/dist/esm/internals/ReportBuilder/PivotModal.d.ts +29 -14
- package/dist/esm/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
- package/dist/esm/internals/ReportBuilder/PivotModal.js +73 -49
- package/dist/esm/utils/dataFetcher.d.ts.map +1 -1
- package/dist/esm/utils/dataFetcher.js +2 -0
- package/dist/esm/utils/width.d.ts +12 -0
- package/dist/esm/utils/width.d.ts.map +1 -0
- package/dist/esm/utils/width.js +21 -0
- package/package.json +1 -1
- package/dist/cjs/BarList.d.ts.map +0 -1
- package/dist/cjs/PieChart.d.ts.map +0 -1
- package/dist/esm/BarList.d.ts.map +0 -1
- package/dist/esm/PieChart.d.ts.map +0 -1
- /package/dist/cjs/{PieChart.d.ts → components/Chart/PieChart.d.ts} +0 -0
- /package/dist/esm/{PieChart.d.ts → components/Chart/PieChart.d.ts} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/* eslint-disable no-unused-vars */
|
|
2
3
|
import { useContext, useEffect, useRef, useState, } from 'react';
|
|
3
|
-
import { MemoizedButton, MemoizedCheckbox, MemoizedHeader, MemoizedLabel, MemoizedPopover,
|
|
4
|
+
import { DEFAULT_TAB_OPTIONS, MemoizedButton, MemoizedCheckbox, MemoizedDeleteButton, MemoizedHeader, MemoizedLabel, MemoizedSecondaryButton, MemoizedText, MemoizedPopover, QuillTableComponent, QuillTabs, MemoizedModal, } from './components/UiComponents';
|
|
4
5
|
import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors, } from '@dnd-kit/core';
|
|
5
6
|
import { arrayMove, SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy, useSortable, } from '@dnd-kit/sortable';
|
|
6
7
|
import { CSS as DND_CSS } from '@dnd-kit/utilities';
|
|
@@ -8,7 +9,8 @@ import { getQuarter } from 'date-fns';
|
|
|
8
9
|
import { ClientContext, ThemeContext } from './Context';
|
|
9
10
|
import { getTableAliases, getTableNames, isDateishColumnType, isNumericColumnType, isTextColumnType, } from './components/ReportBuilder/ast';
|
|
10
11
|
import { ChartBuilderWithModal } from './ChartBuilder';
|
|
11
|
-
import {
|
|
12
|
+
import { QuillTextInput } from './components/UiComponents';
|
|
13
|
+
import { QuillSidebar, CustomContainer, QuillSelectColumn, QuillDraggableColumn, QuillSidebarHeading, QuillFilterPopover, QuillSortPopover, TagWrapper, EditPopover, AddFilterPopover, QuillLimitPopover, } from './components/ReportBuilder/ui';
|
|
12
14
|
import { generateCurrentPeriodPostgres, generateEqualsPostgres, generateLastNPeriodsPostgres, generatePreviousPeriodPostgres, } from './components/ReportBuilder/postgres';
|
|
13
15
|
import { convertBigQuery, convertGroupBy, convertRemoveSimpleParentheses, convertStringComparison, convertWildcardColumns, } from './components/ReportBuilder/convert';
|
|
14
16
|
import { deepCopy, formatDateComparisonNode, getDateFilterInfo, getInTheCurrentIntervalSentence, getInTheLastIntervalSentence, getInThePreviousIntervalSentence, getPostgresBasicType, isColumnComparison, isDateTruncEquals, isInTheLastInterval, isNodeEmptyCollection, isTheCurrentInterval, isThePreviousInterval, isTopLevelBoolean, showNodeAsRow, tryConvertDateEquality, removeNonSelectedTableReferences, } from './components/ReportBuilder/util';
|
|
@@ -19,10 +21,10 @@ import AddColumnPopover from './components/ReportBuilder/AddColumnPopover';
|
|
|
19
21
|
import { AddSortPopover, SortSentence, } from './components/ReportBuilder/AddSortPopover';
|
|
20
22
|
import { PivotModal, generatePivotTable, } from './internals/ReportBuilder/PivotModal';
|
|
21
23
|
import { PivotCard } from './internals/ReportBuilder/PivotList';
|
|
22
|
-
import QuillTable from './components/QuillTable';
|
|
23
|
-
import { QuillSelectComponent } from './components/QuillSelect';
|
|
24
24
|
import { snakeCaseToTitleCase } from './utils/textProcessing';
|
|
25
25
|
import { AddLimitPopover, LimitSentence, } from './components/ReportBuilder/AddLimitPopover';
|
|
26
|
+
import { updateFirstChildWidth } from './utils/width';
|
|
27
|
+
import { QuillSelectComponent } from './components/QuillSelect';
|
|
26
28
|
/**
|
|
27
29
|
* Quill Report Builder
|
|
28
30
|
*
|
|
@@ -30,8 +32,31 @@ import { AddLimitPopover, LimitSentence, } from './components/ReportBuilder/AddL
|
|
|
30
32
|
* then edit them on the fly. Once users have constructed a query they like,
|
|
31
33
|
* they can click a button and add that report to their dashboard or export it
|
|
32
34
|
* as a CSV.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```js
|
|
38
|
+
* // Usage without custom components
|
|
39
|
+
* <ReportBuilder />
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```js
|
|
44
|
+
* // You can also pass your own components
|
|
45
|
+
* <ReportBuilder
|
|
46
|
+
* initialTableName="transactions"
|
|
47
|
+
* TableComponent={MyTable}
|
|
48
|
+
* SelectComponent={MySelect}
|
|
49
|
+
* ButtonComponent={MyButton}
|
|
50
|
+
* PopoverComponent={MyPopover}
|
|
51
|
+
* TextInputComponent={MyTextInput}
|
|
52
|
+
* containerStyle={{ backgroundColor: 'white', padding: '10px' }}
|
|
53
|
+
* />
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* ### Report Builder API
|
|
57
|
+
* @see https://docs.quillsql.com/components/report-builder
|
|
33
58
|
*/
|
|
34
|
-
export default function ReportBuilder({ initialTableName = '',
|
|
59
|
+
export default function ReportBuilder({ initialTableName = '', onSubmitChartBuilder = () => void null, destinationDashboard = undefined, organizationName = '', ButtonComponent = MemoizedButton, SecondaryButtonComponent = MemoizedSecondaryButton, DeleteButtonComponent = MemoizedDeleteButton, ModalComponent = MemoizedModal, TextInputComponent = QuillTextInput, SelectComponent = QuillSelectComponent, TableComponent = QuillTableComponent, PopoverComponent = MemoizedPopover, TabsComponent = QuillTabs, CheckboxComponent = MemoizedCheckbox, SidebarComponent = QuillSidebar, ContainerComponent = CustomContainer, SelectColumnComponent = QuillSelectColumn, DraggableColumnComponent = QuillDraggableColumn, SidebarHeadingComponent = QuillSidebarHeading, FilterPopoverComponent = QuillFilterPopover, SortPopoverComponent = QuillSortPopover, LimitPopoverComponent = QuillLimitPopover, LabelComponent = MemoizedLabel, HeaderComponent = MemoizedHeader, TextComponent = MemoizedText, isAdminEnabled = false, isAIEnabled = true, containerStyle, }) {
|
|
35
60
|
const [aiPrompt, setAiPrompt] = useState('');
|
|
36
61
|
const [errorMessage, setErrorMessage] = useState('');
|
|
37
62
|
const [baseAst, setBaseAst] = useState(null);
|
|
@@ -44,6 +69,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
44
69
|
const [activePath, setActivePath] = useState(null);
|
|
45
70
|
const [openPopover, setOpenPopover] = useState(null);
|
|
46
71
|
const [loading, setLoading] = useState(false);
|
|
72
|
+
const [loadingSchema, setLoadingSchema] = useState(false);
|
|
47
73
|
const [isChartBuilderOpen, setIsChartBuilderOpen] = useState(false);
|
|
48
74
|
const [isPending, setIsPending] = useState(false);
|
|
49
75
|
const [isCopying, setIsCopying] = useState(false);
|
|
@@ -63,6 +89,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
63
89
|
const [initialLoad, setInitialLoad] = useState(true);
|
|
64
90
|
const [currentTable, setCurrentTable] = useState(initialTableName || '');
|
|
65
91
|
const parentRef = useRef(null);
|
|
92
|
+
const askAIContainerRef = useRef(null);
|
|
93
|
+
const askAILoadingContainerRef = useRef(null);
|
|
94
|
+
const [askAIInputWidth, setAskAIInputWidth] = useState(200);
|
|
95
|
+
const [askAILoadingContainerWidth, setAskAILoadingContainerWidth] = useState(200);
|
|
66
96
|
const [theme] = useContext(ThemeContext);
|
|
67
97
|
const [pivotRowField, setPivotRowField] = useState(undefined);
|
|
68
98
|
const [pivotColumnField, setPivotColumnField] = useState(undefined);
|
|
@@ -70,6 +100,19 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
70
100
|
const [pivotAggregation, setPivotAggregation] = useState(undefined);
|
|
71
101
|
// eslint-disable-next-line no-unused-vars
|
|
72
102
|
const [client, _setClient] = useContext(ClientContext);
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
// Since the TextInput component takes a required numeric width parameter,
|
|
105
|
+
// we dynamically calculate the width of this component here.
|
|
106
|
+
function handleResize() {
|
|
107
|
+
updateFirstChildWidth(askAIContainerRef, setAskAIInputWidth, { gap: 12 });
|
|
108
|
+
updateFirstChildWidth(askAILoadingContainerRef, setAskAILoadingContainerWidth, { gap: 12 });
|
|
109
|
+
}
|
|
110
|
+
handleResize();
|
|
111
|
+
window.addEventListener('resize', handleResize);
|
|
112
|
+
return () => {
|
|
113
|
+
window.removeEventListener('resize', handleResize);
|
|
114
|
+
};
|
|
115
|
+
}, [baseAst, loading]);
|
|
73
116
|
const enforceOrderOnColumns = (columnNames) => {
|
|
74
117
|
if (pivot) {
|
|
75
118
|
const rowName = pivot.rowField;
|
|
@@ -105,9 +148,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
105
148
|
setAiPrompt('');
|
|
106
149
|
setBaseAst(null);
|
|
107
150
|
setFormData(null);
|
|
108
|
-
setOrderedColumnNames([]);
|
|
109
151
|
setSelectedColumns([]);
|
|
110
152
|
setSchemaTables([]);
|
|
153
|
+
setOrderedColumnNames([]);
|
|
111
154
|
setActiveQuery('');
|
|
112
155
|
setActiveEditItem(null);
|
|
113
156
|
setActivePath(null);
|
|
@@ -118,6 +161,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
118
161
|
setFields([]);
|
|
119
162
|
setTopLevelBinaryOperator('AND');
|
|
120
163
|
setEditPopoverKey(null);
|
|
164
|
+
setErrorMessage('');
|
|
121
165
|
// setUniqueValues({});
|
|
122
166
|
setPivot(null);
|
|
123
167
|
setPivotData(null);
|
|
@@ -217,7 +261,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
217
261
|
const result = [];
|
|
218
262
|
const table = tables[0];
|
|
219
263
|
const { valueField, rowField, columnField } = pivot;
|
|
220
|
-
if (columnField &&
|
|
264
|
+
if (columnField &&
|
|
265
|
+
uniqueValues[table] &&
|
|
266
|
+
uniqueValues[table][columnField]) {
|
|
221
267
|
result.push(...Object.keys(uniqueValues[table][columnField]));
|
|
222
268
|
}
|
|
223
269
|
result.push(valueField, rowField);
|
|
@@ -255,8 +301,29 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
255
301
|
}
|
|
256
302
|
};
|
|
257
303
|
useEffect(() => {
|
|
304
|
+
const loadTable = async (tables) => {
|
|
305
|
+
if (!tables)
|
|
306
|
+
return;
|
|
307
|
+
setLoading(true);
|
|
308
|
+
await getDistinctValues(initialTableName, tables);
|
|
309
|
+
const columnsForTable = tables
|
|
310
|
+
.find((t) => t.name === initialTableName)
|
|
311
|
+
?.columns.map((c) => c.name)
|
|
312
|
+
.sort((a, b) => {
|
|
313
|
+
const aIsId = a.endsWith('.id') || a.endsWith('_id') || a.endsWith('Id');
|
|
314
|
+
const bIsId = b.endsWith('.id') || b.endsWith('_id') || b.endsWith('Id');
|
|
315
|
+
if (aIsId && !bIsId)
|
|
316
|
+
return 1;
|
|
317
|
+
if (bIsId && !aIsId)
|
|
318
|
+
return -1;
|
|
319
|
+
return 0;
|
|
320
|
+
});
|
|
321
|
+
await handleAsk(`get ${columnsForTable} from ${initialTableName}`);
|
|
322
|
+
setInitialLoad(false);
|
|
323
|
+
};
|
|
258
324
|
const fetchSchema = async () => {
|
|
259
325
|
try {
|
|
326
|
+
setLoadingSchema(true);
|
|
260
327
|
const response = await fetch(`${client.queryEndpoint}`, {
|
|
261
328
|
method: 'POST',
|
|
262
329
|
headers: {
|
|
@@ -279,8 +346,8 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
279
346
|
setOrderedColumnNames((tables ?? []).flatMap((table) => table.columns
|
|
280
347
|
.map((c) => `${table.name}.${c.name}`)
|
|
281
348
|
.sort((a, b) => {
|
|
282
|
-
const aIsId = a.endsWith('.id') || a.endsWith('_id');
|
|
283
|
-
const bIsId = b.endsWith('.id') || b.endsWith('_id');
|
|
349
|
+
const aIsId = a.endsWith('.id') || a.endsWith('_id') || a.endsWith('Id');
|
|
350
|
+
const bIsId = b.endsWith('.id') || b.endsWith('_id') || b.endsWith('Id');
|
|
284
351
|
if (aIsId && !bIsId)
|
|
285
352
|
return 1;
|
|
286
353
|
if (bIsId && !aIsId)
|
|
@@ -288,14 +355,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
288
355
|
return 0;
|
|
289
356
|
})));
|
|
290
357
|
if (initialTableName && initialLoad) {
|
|
291
|
-
|
|
292
|
-
setLoading(true);
|
|
293
|
-
await getDistinctValues(initialTableName, tables);
|
|
294
|
-
const columnsForTable = tables
|
|
295
|
-
.find((t) => t.name === initialTableName)
|
|
296
|
-
?.columns.map((c) => c.name);
|
|
297
|
-
await handleAsk(`get ${columnsForTable} from ${initialTableName}`);
|
|
358
|
+
await loadTable(tables);
|
|
298
359
|
}
|
|
360
|
+
setLoadingSchema(false);
|
|
299
361
|
}
|
|
300
362
|
catch (error) {
|
|
301
363
|
console.error(error);
|
|
@@ -304,7 +366,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
304
366
|
if (schemaTables.length === 0) {
|
|
305
367
|
fetchSchema();
|
|
306
368
|
}
|
|
307
|
-
|
|
369
|
+
else if (initialLoad && initialTableName) {
|
|
370
|
+
loadTable(schemaTables);
|
|
371
|
+
}
|
|
372
|
+
}, [schemaTables, initialTableName]);
|
|
308
373
|
const updateFormData = (updates, { isDeletion = false, isInsertion = false, isReplaceSubtree = false, isAddVariant = false, isDeleteVariant = false, topLevelBinOp = 'OR', isCondition = undefined, }) => {
|
|
309
374
|
// Function to immutably update or delete nodes based on their path
|
|
310
375
|
// TODO: fix the following horible code
|
|
@@ -711,7 +776,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
711
776
|
// see onChange callback handleChange
|
|
712
777
|
// eslint-disable-next-line no-unused-vars
|
|
713
778
|
dateColumnPath, dateFilterType, intervalCount, intervalType, intervalPaths, } = getDateFilterInfo(node);
|
|
714
|
-
const isPlural = intervalCount
|
|
779
|
+
const isPlural = intervalCount !== 1 && dateFilterType !== 'in the current'
|
|
780
|
+
? 's'
|
|
781
|
+
: '';
|
|
715
782
|
// Pull off the string literal date for "equals" comparisons
|
|
716
783
|
const rawDateStringEquals = node.right?.value ??
|
|
717
784
|
node.right?.args?.value[1]?.column ??
|
|
@@ -721,50 +788,50 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
721
788
|
'node.right.args.value.1.column') ??
|
|
722
789
|
(node.right?.args?.value[1]?.value &&
|
|
723
790
|
'node.right.args.value.1.value');
|
|
724
|
-
return (_jsxs("div", { style: { display: 'flex', gap: 20 }, children: [_jsx(
|
|
725
|
-
const columnType = getColumnTypeByName(value);
|
|
791
|
+
return (_jsxs("div", { style: { display: 'flex', gap: 20 }, children: [_jsx(SelectComponent, { value: dateColumn, onChange: (event) => {
|
|
792
|
+
const columnType = getColumnTypeByName(event.target.value);
|
|
726
793
|
if (isDateishColumnType(columnType)) {
|
|
727
794
|
// handleChange(value, keyPrefix + dateColumnPath, "text");
|
|
728
|
-
handleOperatorChange('IN_THE_LAST', node, keyPrefix, value);
|
|
795
|
+
handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
|
|
729
796
|
}
|
|
730
797
|
else if (isNumericColumnType(columnType)) {
|
|
731
798
|
const newSubtree = deepCopy(defaultNumericComparison);
|
|
732
|
-
newSubtree.left.column = value;
|
|
799
|
+
newSubtree.left.column = event.target.value;
|
|
733
800
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
734
801
|
}
|
|
735
802
|
else {
|
|
736
803
|
const newSubtree = deepCopy(defaultEntry);
|
|
737
|
-
newSubtree.left.args.value[0].column = value;
|
|
804
|
+
newSubtree.left.args.value[0].column = event.target.value;
|
|
738
805
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
739
806
|
}
|
|
740
807
|
}, options: getAllPossibleColumns().map((column) => ({
|
|
741
808
|
label: snakeCaseToTitleCase(column.displayName),
|
|
742
809
|
value: column.name,
|
|
743
|
-
})) }), _jsx(
|
|
744
|
-
if (value === dateFilterType)
|
|
810
|
+
})) }), _jsx(SelectComponent, { value: dateFilterType, onChange: (event) => {
|
|
811
|
+
if (event.target.value === dateFilterType)
|
|
745
812
|
return null;
|
|
746
813
|
let newSubtree = {};
|
|
747
814
|
// TODO: implement one for each database type (eg. pg, snowflake, etc.)
|
|
748
|
-
if (value === 'in the last') {
|
|
815
|
+
if (event.target.value === 'in the last') {
|
|
749
816
|
newSubtree = generateLastNPeriodsPostgres({
|
|
750
817
|
dateField: dateColumn,
|
|
751
818
|
intervalPeriod: `${intervalCount ?? 1} ${intervalType}`,
|
|
752
819
|
});
|
|
753
820
|
}
|
|
754
|
-
else if (value === 'in the previous') {
|
|
821
|
+
else if (event.target.value === 'in the previous') {
|
|
755
822
|
newSubtree = generatePreviousPeriodPostgres({
|
|
756
823
|
dateField: dateColumn,
|
|
757
824
|
intervalPeriod: `${intervalCount ?? 1} ${intervalType}`,
|
|
758
825
|
currentPeriod: intervalType,
|
|
759
826
|
});
|
|
760
827
|
}
|
|
761
|
-
else if (value === 'in the current') {
|
|
828
|
+
else if (event.target.value === 'in the current') {
|
|
762
829
|
newSubtree = generateCurrentPeriodPostgres({
|
|
763
830
|
dateField: dateColumn,
|
|
764
831
|
currentPeriod: intervalType,
|
|
765
832
|
});
|
|
766
833
|
}
|
|
767
|
-
else if (value === 'equals') {
|
|
834
|
+
else if (event.target.value === 'equals') {
|
|
768
835
|
newSubtree = generateEqualsPostgres({
|
|
769
836
|
dateField: dateColumn,
|
|
770
837
|
currentPeriod: intervalType,
|
|
@@ -778,21 +845,25 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
778
845
|
{ label: 'in the previous', value: 'in the previous' },
|
|
779
846
|
{ label: 'in the current', value: 'in the current' },
|
|
780
847
|
{ label: 'equals', value: 'equals' },
|
|
781
|
-
] }), !['in the current', 'equals'].includes(dateFilterType) && (_jsx(
|
|
782
|
-
|
|
848
|
+
] }), !['in the current', 'equals'].includes(dateFilterType) && (_jsx(TextInputComponent, { id: "date_filter_interval_count", value: intervalCount?.toString() ?? '', width: 70, onChange: (e) => {
|
|
849
|
+
if (Number.isNaN(parseFloat(e.target.value || '0'))) {
|
|
850
|
+
alert('Please input a number.');
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
const isPluralNow = parseFloat(e.target.value || '0') !== 1 ? 's' : '';
|
|
783
854
|
intervalPaths.forEach((intervalPath) => handleChangeText([
|
|
784
855
|
{
|
|
785
|
-
value: `${e.target.value} ${intervalType}${isPluralNow}`,
|
|
856
|
+
value: `${e.target.value || 0} ${intervalType}${isPluralNow}`,
|
|
786
857
|
path: keyPrefix + intervalPath,
|
|
787
858
|
},
|
|
788
859
|
]));
|
|
789
|
-
} })), _jsx(
|
|
860
|
+
} })), _jsx(SelectComponent, { value: intervalType, onChange: (event) => {
|
|
790
861
|
if (intervalPaths.length === 1) {
|
|
791
862
|
handleChangeText([
|
|
792
863
|
{
|
|
793
864
|
value: intervalCount !== null
|
|
794
|
-
? `${intervalCount} ${value}${isPlural}`
|
|
795
|
-
: value,
|
|
865
|
+
? `${intervalCount} ${event.target.value}${isPlural}`
|
|
866
|
+
: event.target.value,
|
|
796
867
|
path: keyPrefix + intervalPaths[0],
|
|
797
868
|
},
|
|
798
869
|
]);
|
|
@@ -802,14 +873,14 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
802
873
|
if (dateFilterType === 'equals') {
|
|
803
874
|
newSubtree = generateEqualsPostgres({
|
|
804
875
|
dateField: dateColumn,
|
|
805
|
-
currentPeriod: value,
|
|
876
|
+
currentPeriod: event.target.value,
|
|
806
877
|
timestamp: rawDateStringEquals,
|
|
807
878
|
});
|
|
808
879
|
}
|
|
809
880
|
else {
|
|
810
881
|
newSubtree = generateCurrentPeriodPostgres({
|
|
811
882
|
dateField: dateColumn,
|
|
812
|
-
currentPeriod: value,
|
|
883
|
+
currentPeriod: event.target.value,
|
|
813
884
|
});
|
|
814
885
|
}
|
|
815
886
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
@@ -820,7 +891,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
820
891
|
{ label: `week${isPlural}`, value: 'week' },
|
|
821
892
|
{ label: `day${isPlural}`, value: 'day' },
|
|
822
893
|
{ label: `hour${isPlural}`, value: 'hour' },
|
|
823
|
-
] }), dateFilterType === 'equals' && (_jsx(
|
|
894
|
+
] }), dateFilterType === 'equals' && (_jsx(TextInputComponent, { id: "date_filter_equals_raw_date", value: rawDateStringEquals, width: 120, onChange: (e) => {
|
|
824
895
|
handleChangeText([
|
|
825
896
|
{
|
|
826
897
|
value: e.target.value,
|
|
@@ -835,44 +906,49 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
835
906
|
label: snakeCaseToTitleCase(column.displayName),
|
|
836
907
|
value: column.name,
|
|
837
908
|
}));
|
|
838
|
-
const plural = node.right.args.value[1].expr.value
|
|
909
|
+
const plural = node.right.args.value[1].expr.value !== 1 ? 's' : '';
|
|
839
910
|
return (_jsxs("div", { style: {
|
|
840
911
|
display: 'flex',
|
|
841
912
|
flexDirection: 'row',
|
|
842
913
|
alignItems: 'center',
|
|
843
914
|
gap: 20,
|
|
844
|
-
}, children: [_jsx(
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
handleOperatorChange(value, node, keyPrefix, dateColumn);
|
|
915
|
+
}, children: [_jsx(SelectComponent, { value: node.left.column, onChange: (event) => {
|
|
916
|
+
const columnType = getColumnTypeByName(event.target.value);
|
|
917
|
+
if (isDateishColumnType(columnType)) {
|
|
918
|
+
// handleChange(value, keyPrefix + dateColumnPath, "text");
|
|
919
|
+
handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
|
|
920
|
+
}
|
|
921
|
+
else if (isNumericColumnType(columnType)) {
|
|
922
|
+
const newSubtree = deepCopy(defaultNumericComparison);
|
|
923
|
+
newSubtree.left.column = event.target.value;
|
|
924
|
+
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
925
|
+
}
|
|
926
|
+
else {
|
|
927
|
+
const newSubtree = deepCopy(defaultEntry);
|
|
928
|
+
newSubtree.left.args.value[0].column = event.target.value;
|
|
929
|
+
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
930
|
+
}
|
|
931
|
+
}, options: options }), _jsx(SelectComponent, { value: 'IN_THE_LAST', onChange: (event) => {
|
|
932
|
+
handleOperatorChange(event.target.value, node, keyPrefix, dateColumn);
|
|
862
933
|
}, options: [
|
|
863
934
|
{ label: 'in the last', value: 'IN_THE_LAST' },
|
|
864
935
|
{ label: 'in the previous', value: 'IN_THE_PREVIOUS' },
|
|
865
936
|
{ label: 'in the current', value: 'IN_THE_CURRENT' },
|
|
937
|
+
{ label: 'is not null', value: 'IS NOT' },
|
|
938
|
+
{ label: 'is null', value: 'IS' },
|
|
866
939
|
// { label: 'equals', value: 'equals' },
|
|
867
|
-
] }), _jsx(
|
|
940
|
+
] }), _jsx(TextInputComponent, { id: 'date_window_interval_count', value: node.right.args.value[1].expr.value, width: 120, onChange: (e) => {
|
|
868
941
|
handleChange([
|
|
869
942
|
{
|
|
870
943
|
value: e.target.value,
|
|
871
944
|
path: keyPrefix + 'right.args.value||1.expr.value',
|
|
872
945
|
},
|
|
873
946
|
]);
|
|
874
|
-
} }), _jsx("div", { children: _jsx(
|
|
875
|
-
{
|
|
947
|
+
} }), _jsx("div", { children: _jsx(SelectComponent, { value: node.right.args.value[1].unit, onChange: (event) => handleChange([
|
|
948
|
+
{
|
|
949
|
+
value: event.target.value,
|
|
950
|
+
path: keyPrefix + 'right.args.value||1.unit',
|
|
951
|
+
},
|
|
876
952
|
]), options: [
|
|
877
953
|
{ label: `year${plural}`, value: '* 365 DAY' },
|
|
878
954
|
{ label: `month${plural}`, value: '* 30 DAY' },
|
|
@@ -891,33 +967,41 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
891
967
|
flexDirection: 'row',
|
|
892
968
|
alignItems: 'center',
|
|
893
969
|
gap: 20,
|
|
894
|
-
}, children: [_jsx(
|
|
895
|
-
const columnType = getColumnTypeByName(value);
|
|
970
|
+
}, children: [_jsx(SelectComponent, { value: node.left.column, onChange: (event) => {
|
|
971
|
+
const columnType = getColumnTypeByName(event.target.value);
|
|
896
972
|
if (isDateishColumnType(columnType)) {
|
|
897
973
|
// handleChange(value, keyPrefix + dateColumnPath, "text");
|
|
898
|
-
handleOperatorChange('IN_THE_LAST', node, keyPrefix, value);
|
|
974
|
+
handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
|
|
899
975
|
}
|
|
900
976
|
else if (isNumericColumnType(columnType)) {
|
|
901
977
|
const newSubtree = deepCopy(defaultNumericComparison);
|
|
902
|
-
newSubtree.left.column = value;
|
|
978
|
+
newSubtree.left.column = event.target.value;
|
|
903
979
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
904
980
|
}
|
|
905
981
|
else {
|
|
906
982
|
const newSubtree = deepCopy(defaultEntry);
|
|
907
|
-
newSubtree.left.args.value[0].column = value;
|
|
983
|
+
newSubtree.left.args.value[0].column = event.target.value;
|
|
908
984
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
909
985
|
}
|
|
910
|
-
}, options: options }), _jsx(
|
|
911
|
-
handleOperatorChange(value, node, keyPrefix, node.left.column);
|
|
986
|
+
}, options: options }), _jsx(SelectComponent, { value: 'IN_THE_CURRENT', onChange: (event) => {
|
|
987
|
+
handleOperatorChange(event.target.value, node, keyPrefix, node.left.column);
|
|
912
988
|
}, options: [
|
|
913
989
|
{ label: 'in the last', value: 'IN_THE_LAST' },
|
|
914
990
|
{ label: 'in the previous', value: 'IN_THE_PREVIOUS' },
|
|
915
991
|
{ label: 'in the current', value: 'IN_THE_CURRENT' },
|
|
992
|
+
{ label: 'is not null', value: 'IS NOT' },
|
|
993
|
+
{ label: 'is null', value: 'IS' },
|
|
916
994
|
// { label: 'equals', value: 'equals' },
|
|
917
|
-
] }), _jsx(
|
|
995
|
+
] }), _jsx(SelectComponent, { value: node.left.args.value[1].column, onChange: (event) => {
|
|
918
996
|
handleChange([
|
|
919
|
-
{
|
|
920
|
-
|
|
997
|
+
{
|
|
998
|
+
value: event.target.value,
|
|
999
|
+
path: 'right.args.value||1.column',
|
|
1000
|
+
},
|
|
1001
|
+
{
|
|
1002
|
+
value: event.target.value,
|
|
1003
|
+
path: 'left.args.value||1.column',
|
|
1004
|
+
},
|
|
921
1005
|
]);
|
|
922
1006
|
}, options: [
|
|
923
1007
|
{ label: `year`, value: 'YEAR' },
|
|
@@ -936,30 +1020,32 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
936
1020
|
flexDirection: 'row',
|
|
937
1021
|
alignItems: 'center',
|
|
938
1022
|
gap: 20,
|
|
939
|
-
}, children: [_jsx(
|
|
940
|
-
const columnType = getColumnTypeByName(value);
|
|
1023
|
+
}, children: [_jsx(SelectComponent, { value: node.left.column, onChange: (event) => {
|
|
1024
|
+
const columnType = getColumnTypeByName(event.target.value);
|
|
941
1025
|
if (isDateishColumnType(columnType)) {
|
|
942
1026
|
// handleChange(value, keyPrefix + dateColumnPath, "text");
|
|
943
|
-
handleOperatorChange('IN_THE_LAST', node, keyPrefix, value);
|
|
1027
|
+
handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
|
|
944
1028
|
}
|
|
945
1029
|
else if (isNumericColumnType(columnType)) {
|
|
946
1030
|
const newSubtree = deepCopy(defaultNumericComparison);
|
|
947
|
-
newSubtree.left.column = value;
|
|
1031
|
+
newSubtree.left.column = event.target.value;
|
|
948
1032
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
949
1033
|
}
|
|
950
1034
|
else {
|
|
951
1035
|
const newSubtree = deepCopy(defaultEntry);
|
|
952
|
-
newSubtree.left.args.value[0].column = value;
|
|
1036
|
+
newSubtree.left.args.value[0].column = event.target.value;
|
|
953
1037
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
954
1038
|
}
|
|
955
|
-
},
|
|
956
|
-
handleOperatorChange(value, node, keyPrefix, node.left.column);
|
|
1039
|
+
}, options: options }), _jsx(SelectComponent, { value: 'IN_THE_PREVIOUS', onChange: (event) => {
|
|
1040
|
+
handleOperatorChange(event.target.value, node, keyPrefix, node.left.column);
|
|
957
1041
|
}, options: [
|
|
958
1042
|
{ label: 'in the last', value: 'IN_THE_LAST' },
|
|
959
1043
|
{ label: 'in the previous', value: 'IN_THE_PREVIOUS' },
|
|
960
1044
|
{ label: 'in the current', value: 'IN_THE_CURRENT' },
|
|
1045
|
+
{ label: 'is not null', value: 'IS NOT' },
|
|
1046
|
+
{ label: 'is null', value: 'IS' },
|
|
961
1047
|
// { label: 'equals', value: 'equals' },
|
|
962
|
-
] }), _jsx(
|
|
1048
|
+
] }), _jsx(SelectComponent, { value: node.left.args.value[1].column, onChange: (event) => {
|
|
963
1049
|
const dayConversion = {
|
|
964
1050
|
YEAR: 365,
|
|
965
1051
|
QUARTER: 90,
|
|
@@ -968,15 +1054,15 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
968
1054
|
};
|
|
969
1055
|
handleChange([
|
|
970
1056
|
{
|
|
971
|
-
value,
|
|
1057
|
+
value: event.target.value,
|
|
972
1058
|
path: 'left.args.value||1.column',
|
|
973
1059
|
},
|
|
974
1060
|
{
|
|
975
|
-
value,
|
|
1061
|
+
value: event.target.value,
|
|
976
1062
|
path: 'right.args.value||1.column',
|
|
977
1063
|
},
|
|
978
1064
|
{
|
|
979
|
-
value: dayConversion[value] || 30,
|
|
1065
|
+
value: dayConversion[event.target.value] || 30,
|
|
980
1066
|
path: 'right.args.value||0.args.value||1.expr.value',
|
|
981
1067
|
},
|
|
982
1068
|
]);
|
|
@@ -1001,7 +1087,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1001
1087
|
const tables = getTableNames(baseAst);
|
|
1002
1088
|
const table = tables.length === 1 ? tables[0] : initialTableName;
|
|
1003
1089
|
const columnType = column?.fieldType;
|
|
1004
|
-
|
|
1090
|
+
let operatorOptions = [
|
|
1005
1091
|
...(isNumericColumnType(columnType)
|
|
1006
1092
|
? [
|
|
1007
1093
|
{ label: 'equal to', value: '=' },
|
|
@@ -1016,10 +1102,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1016
1102
|
: []),
|
|
1017
1103
|
...(isTextColumnType(columnType)
|
|
1018
1104
|
? [
|
|
1019
|
-
{ label: 'is', value: 'LIKE' },
|
|
1020
|
-
{ label: 'is not', value: 'NOT LIKE' },
|
|
1021
|
-
{ label: 'is
|
|
1022
|
-
{ label: 'is not
|
|
1105
|
+
{ label: 'is exactly', value: 'LIKE' },
|
|
1106
|
+
{ label: 'is not exactly', value: 'NOT LIKE' },
|
|
1107
|
+
{ label: 'is', value: 'IN' },
|
|
1108
|
+
{ label: 'is not', value: 'NOT IN' },
|
|
1023
1109
|
{ label: 'is not null', value: 'IS NOT' },
|
|
1024
1110
|
{ label: 'is null', value: 'IS' },
|
|
1025
1111
|
]
|
|
@@ -1038,6 +1124,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1038
1124
|
]
|
|
1039
1125
|
: []),
|
|
1040
1126
|
];
|
|
1127
|
+
if (client.databaseType === 'BigQuery' &&
|
|
1128
|
+
isDateishColumnType(columnType)) {
|
|
1129
|
+
operatorOptions = operatorOptions.filter((option) => option.value !== 'equals');
|
|
1130
|
+
}
|
|
1041
1131
|
return (_jsxs("div", { style: {
|
|
1042
1132
|
display: 'flex',
|
|
1043
1133
|
gap: 12,
|
|
@@ -1047,45 +1137,48 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1047
1137
|
}, children: [_jsxs("div", { style: {
|
|
1048
1138
|
display: 'flex',
|
|
1049
1139
|
gap: 20,
|
|
1050
|
-
// justifyContent: "space-between",
|
|
1051
1140
|
flexDirection: showNodeAsRow(node, formData)
|
|
1052
1141
|
? 'row'
|
|
1053
1142
|
: 'column',
|
|
1054
1143
|
width: '100%',
|
|
1055
|
-
}, children: [_jsx(
|
|
1056
|
-
const columnType = getColumnTypeByName(value);
|
|
1144
|
+
}, children: [_jsx(SelectComponent, { value: leftChildValue, onChange: (event) => {
|
|
1145
|
+
const columnType = getColumnTypeByName(event.target.value);
|
|
1057
1146
|
if (isDateishColumnType(columnType)) {
|
|
1058
|
-
handleOperatorChange('IN_THE_LAST', node, keyPrefix, value);
|
|
1147
|
+
handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
|
|
1059
1148
|
}
|
|
1060
1149
|
else if (isNumericColumnType(columnType)) {
|
|
1061
1150
|
const newSubtree = deepCopy(defaultNumericComparison);
|
|
1062
|
-
newSubtree.left.column = value;
|
|
1151
|
+
newSubtree.left.column = event.target.value;
|
|
1063
1152
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
1064
1153
|
}
|
|
1065
1154
|
else {
|
|
1066
1155
|
const newSubtree = deepCopy(defaultEntry);
|
|
1067
|
-
newSubtree.left.args.value[0].column = value;
|
|
1156
|
+
newSubtree.left.args.value[0].column = event.target.value;
|
|
1068
1157
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
1069
1158
|
}
|
|
1070
|
-
}, options: options }), operatorOptions.length > 0 && (_jsx(
|
|
1071
|
-
handleOperatorChange(value, node, keyPrefix, leftChildValue);
|
|
1072
|
-
},
|
|
1159
|
+
}, options: options }), operatorOptions.length > 0 && (_jsx(SelectComponent, { value: node.operator, onChange: (event) => {
|
|
1160
|
+
handleOperatorChange(event.target.value, node, keyPrefix, leftChildValue);
|
|
1161
|
+
}, options: operatorOptions })), node.right &&
|
|
1073
1162
|
node.right.type !== 'expr_list' &&
|
|
1074
1163
|
renderNode(node.right, keyPrefix + 'right.')] }, keyPrefix), node.right && node.right.type === 'expr_list' && (_jsx("div", { style: {
|
|
1075
1164
|
display: 'grid',
|
|
1076
1165
|
gridTemplateColumns: 'repeat(2, 1fr)',
|
|
1077
1166
|
gap: 12,
|
|
1078
|
-
}, children:
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1167
|
+
}, children: uniqueValues[table] &&
|
|
1168
|
+
Object.keys(uniqueValues[table][leftChildValue] ?? {}).map((key) => (_jsxs("label", { style: { display: 'flex', gap: 4 }, children: [_jsx(CheckboxComponent, { isChecked: uniqueValues[table][leftChildValue][key], onChange: (event) => {
|
|
1169
|
+
const newValues = deepCopy(uniqueValues);
|
|
1170
|
+
newValues[table][leftChildValue][key] = event.target.checked;
|
|
1171
|
+
setUniqueValues(newValues);
|
|
1172
|
+
if (event.target.checked) {
|
|
1173
|
+
handleInsertVariant(keyPrefix + 'right.' + 'value', key);
|
|
1174
|
+
}
|
|
1175
|
+
else {
|
|
1176
|
+
handleDeleteVariant(keyPrefix + 'right.' + 'value', key);
|
|
1177
|
+
}
|
|
1178
|
+
} }), _jsx("span", { style: {
|
|
1179
|
+
fontFamily: theme.fontFamily,
|
|
1180
|
+
margin: 'auto 0',
|
|
1181
|
+
}, children: key })] }, key))) }, keyPrefix + 'right.'))] }));
|
|
1089
1182
|
}
|
|
1090
1183
|
else {
|
|
1091
1184
|
const columnName = node.left.column;
|
|
@@ -1097,9 +1190,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1097
1190
|
justifyContent: 'space-between',
|
|
1098
1191
|
flexDirection: showNodeAsRow(node, formData) ? 'row' : 'column',
|
|
1099
1192
|
width: '100%',
|
|
1100
|
-
}, children: [node.left && renderNode(node.left, keyPrefix + 'left.'), _jsx(
|
|
1101
|
-
handleOperatorChange(value, node, keyPrefix);
|
|
1102
|
-
},
|
|
1193
|
+
}, children: [node.left && renderNode(node.left, keyPrefix + 'left.'), _jsx(SelectComponent, { value: node.operator, onChange: (event) => {
|
|
1194
|
+
handleOperatorChange(event.target.value, node, keyPrefix);
|
|
1195
|
+
}, options: [
|
|
1103
1196
|
// { label: `and`, value: "AND" },
|
|
1104
1197
|
// { label: `or`, value: "OR" },
|
|
1105
1198
|
...(isNumericColumnType(columnType)
|
|
@@ -1116,10 +1209,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1116
1209
|
: []),
|
|
1117
1210
|
...(isTextColumnType(columnType)
|
|
1118
1211
|
? [
|
|
1119
|
-
{ label: 'is', value: 'LIKE' },
|
|
1120
|
-
{ label: 'is not', value: 'NOT LIKE' },
|
|
1121
|
-
{ label: 'is
|
|
1122
|
-
{ label: 'is not
|
|
1212
|
+
{ label: 'is exactly', value: 'LIKE' },
|
|
1213
|
+
{ label: 'is not exactly', value: 'NOT LIKE' },
|
|
1214
|
+
{ label: 'is', value: 'IN' },
|
|
1215
|
+
{ label: 'is not', value: 'NOT IN' },
|
|
1123
1216
|
{ label: 'is not null', value: 'IS NOT' },
|
|
1124
1217
|
{ label: 'is null', value: 'IS' },
|
|
1125
1218
|
]
|
|
@@ -1142,45 +1235,41 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1142
1235
|
label: snakeCaseToTitleCase(column.displayName),
|
|
1143
1236
|
value: column.name,
|
|
1144
1237
|
}));
|
|
1145
|
-
return (_jsx(
|
|
1146
|
-
handleChange([
|
|
1238
|
+
return (_jsx(SelectComponent, { value: node.column ?? options[0]?.value, onChange: (event) => {
|
|
1239
|
+
handleChange([
|
|
1240
|
+
{ value: event.target.value, path: keyPrefix + 'column' },
|
|
1241
|
+
]);
|
|
1147
1242
|
}, options: options }));
|
|
1148
1243
|
}
|
|
1149
1244
|
case 'expr_list': {
|
|
1150
1245
|
const len = node.value.length;
|
|
1151
1246
|
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'row', gap: 12 }, children: [node.value.map((elem, index) => {
|
|
1152
1247
|
if (elem.value) {
|
|
1153
|
-
return (_jsx(
|
|
1248
|
+
return (_jsx(TextInputComponent, { id: `expr_list_${index}`, width: 200, value: elem.value, onChange: (e) => handleChange([
|
|
1154
1249
|
{
|
|
1155
|
-
value:
|
|
1156
|
-
? parseFloat(e.target.value)
|
|
1157
|
-
: e.target.value,
|
|
1250
|
+
value: e.target.value,
|
|
1158
1251
|
path: keyPrefix + `value.${index}.`,
|
|
1159
1252
|
},
|
|
1160
1253
|
]) }, `input_${index}`));
|
|
1161
1254
|
}
|
|
1162
1255
|
return renderNode(elem, keyPrefix + `value.${index}.`);
|
|
1163
|
-
}), len > 1 && (_jsx(
|
|
1256
|
+
}), len > 1 && (_jsx(SecondaryButtonComponent, { label: '-', onClick: () => handleDeleteVariant(keyPrefix + 'value') })), _jsx(SecondaryButtonComponent, { onClick: () => handleInsertVariant(keyPrefix + 'value'), label: '+' })] }, keyPrefix));
|
|
1164
1257
|
}
|
|
1165
1258
|
case 'double_quote_string':
|
|
1166
1259
|
case 'single_quote_string':
|
|
1167
|
-
return (_jsx(
|
|
1260
|
+
return (_jsx(TextInputComponent, { id: 'quoted_string', value: node.value.replaceAll('%', ''), width: 120, onChange: (e) => handleChange([
|
|
1168
1261
|
{
|
|
1169
|
-
value:
|
|
1170
|
-
? parseFloat(e.target.value)
|
|
1171
|
-
: e.target.value,
|
|
1262
|
+
value: e.target.value,
|
|
1172
1263
|
path: keyPrefix + 'value',
|
|
1173
1264
|
},
|
|
1174
1265
|
]) }));
|
|
1175
1266
|
case 'null':
|
|
1176
1267
|
return _jsx("div", {});
|
|
1177
1268
|
case 'number':
|
|
1178
|
-
return (_jsx(
|
|
1269
|
+
return (_jsx(TextInputComponent, { id: "quill_number_input", value: node.value, width: 120, onChange: (e) => {
|
|
1179
1270
|
handleChange([
|
|
1180
1271
|
{
|
|
1181
|
-
value:
|
|
1182
|
-
? parseFloat(e.target.value)
|
|
1183
|
-
: e.target.value,
|
|
1272
|
+
value: e.target.value,
|
|
1184
1273
|
path: keyPrefix + 'value',
|
|
1185
1274
|
},
|
|
1186
1275
|
]);
|
|
@@ -1207,6 +1296,22 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1207
1296
|
return null;
|
|
1208
1297
|
}
|
|
1209
1298
|
};
|
|
1299
|
+
const isValidPivot = (fields) => {
|
|
1300
|
+
let validPivot = true;
|
|
1301
|
+
if (pivot.rowField &&
|
|
1302
|
+
!fields.find((field) => field.name === pivot.rowField)) {
|
|
1303
|
+
validPivot = false;
|
|
1304
|
+
}
|
|
1305
|
+
if (pivot.valueField &&
|
|
1306
|
+
!fields.find((field) => field.name === pivot.valueField)) {
|
|
1307
|
+
validPivot = false;
|
|
1308
|
+
}
|
|
1309
|
+
if (pivot.columnField &&
|
|
1310
|
+
!fields.find((field) => field.name === pivot.columnField)) {
|
|
1311
|
+
validPivot = false;
|
|
1312
|
+
}
|
|
1313
|
+
return validPivot;
|
|
1314
|
+
};
|
|
1210
1315
|
const renderSentence = (formData, node, keyPrefix = '',
|
|
1211
1316
|
// @depreciated TODO: remove next update
|
|
1212
1317
|
// eslint-disable-next-line no-unused-vars
|
|
@@ -1234,13 +1339,13 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1234
1339
|
const OPS = {
|
|
1235
1340
|
AND: 'and',
|
|
1236
1341
|
OR: 'or',
|
|
1237
|
-
LIKE: 'is',
|
|
1342
|
+
LIKE: 'is exactly',
|
|
1238
1343
|
BETWEEN: 'is between',
|
|
1239
|
-
IN: 'is
|
|
1240
|
-
'NOT IN': 'is not
|
|
1241
|
-
'NOT LIKE': 'is not',
|
|
1242
|
-
'!=': 'is not',
|
|
1243
|
-
'=': 'is',
|
|
1344
|
+
IN: 'is',
|
|
1345
|
+
'NOT IN': 'is not',
|
|
1346
|
+
'NOT LIKE': 'is not exactly',
|
|
1347
|
+
'!=': 'is not exactly',
|
|
1348
|
+
'=': 'is exactly',
|
|
1244
1349
|
'<': 'is less than',
|
|
1245
1350
|
'>': 'is greater than',
|
|
1246
1351
|
'<=': 'is less than or equal to',
|
|
@@ -1248,25 +1353,16 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1248
1353
|
'<>': 'is not',
|
|
1249
1354
|
'-': 'minus',
|
|
1250
1355
|
'IS NOT': 'is not',
|
|
1251
|
-
IS: 'is
|
|
1356
|
+
IS: 'is',
|
|
1252
1357
|
};
|
|
1253
1358
|
switch (node.type) {
|
|
1254
1359
|
case 'binary_expr':
|
|
1255
|
-
return (_jsx(TagWrapper, { keyPrefix: keyPrefix, formData: formData, activeEditItem: activeEditItem, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setCheckboxes: setCheckboxes, handleReplaceSubtree: handleReplaceSubtree, FilterPopover:
|
|
1256
|
-
display: 'flex',
|
|
1257
|
-
gap: 3,
|
|
1258
|
-
flexDirection: isRow ? 'row' : 'column',
|
|
1259
|
-
padding: '1px',
|
|
1260
|
-
border: isCard ? '1px solid black' : 'none',
|
|
1261
|
-
whiteSpace: 'nowrap',
|
|
1262
|
-
overflow: 'hidden',
|
|
1263
|
-
textOverflow: 'ellipsis',
|
|
1264
|
-
}, children: dateComparisonPartialMatch ??
|
|
1360
|
+
return (_jsx(TagWrapper, { keyPrefix: keyPrefix, formData: formData, activeEditItem: activeEditItem, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setCheckboxes: setCheckboxes, handleReplaceSubtree: handleReplaceSubtree, FilterPopover: FilterPopoverComponent, setActivePath: setActivePath, setOpenPopover: setOpenPopover, setIsPending: setIsPending, clearCheckboxes: clearCheckboxes, fetchSqlQuery: fetchSqlQuery, handleDelete: handleDelete, editPopoverKey: editPopoverKey, isCard: isCard, isRow: isRow, getByKey: getByKey, EditPopover: EditPopover, Button: ButtonComponent, renderNode: renderNode, children: dateComparisonPartialMatch ??
|
|
1265
1361
|
dateEqualityPartialMatch ??
|
|
1266
1362
|
isInTheCurrentIntervalSentence ??
|
|
1267
1363
|
isInTheLastIntervalSentence ??
|
|
1268
1364
|
isInThePreviousIntervalSentence ?? (_jsxs(_Fragment, { children: [node.left &&
|
|
1269
|
-
renderSentence(formData, node.left, keyPrefix + 'left.', false, false, isRow), isRow ? (' ' + OPS[node.operator] + ' ') : isTopLevel || topLevelBinaryOperator === 'OR' ? (_jsx(TopLevelBooleanSwitch, { node: node, keyPrefix: keyPrefix, handleOperatorChange: handleOperatorChange, Select:
|
|
1365
|
+
renderSentence(formData, node.left, keyPrefix + 'left.', false, false, isRow), isRow ? (' ' + OPS[node.operator] + ' ') : isTopLevel || topLevelBinaryOperator === 'OR' ? (_jsx(TopLevelBooleanSwitch, { node: node, keyPrefix: keyPrefix, handleOperatorChange: handleOperatorChange, Select: SelectComponent })) : null, node.right &&
|
|
1270
1366
|
renderSentence(formData, node.right, keyPrefix + 'right.', false, false, isRow)] })) }));
|
|
1271
1367
|
case 'column_ref':
|
|
1272
1368
|
return snakeCaseToTitleCase(node.column);
|
|
@@ -1301,6 +1397,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1301
1397
|
if (node.args.value.length < 1)
|
|
1302
1398
|
return null;
|
|
1303
1399
|
if (node.args.value[0].value) {
|
|
1400
|
+
if (node.args.value[0].type === 'single_quote_string') {
|
|
1401
|
+
return node.args.value[0].value.replaceAll('%', '');
|
|
1402
|
+
}
|
|
1304
1403
|
return snakeCaseToTitleCase(node.args.value[0].value.replaceAll('%', ''));
|
|
1305
1404
|
}
|
|
1306
1405
|
if (node.args.value[0].column)
|
|
@@ -1348,9 +1447,11 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1348
1447
|
}))
|
|
1349
1448
|
.sort((a, b) => {
|
|
1350
1449
|
const aIsId = a.name.toLowerCase() === 'id' ||
|
|
1351
|
-
a.name.toLowerCase().endsWith('_id')
|
|
1450
|
+
a.name.toLowerCase().endsWith('_id') ||
|
|
1451
|
+
a.name.endsWith('Id');
|
|
1352
1452
|
const bIsId = b.name.toLowerCase() === 'id' ||
|
|
1353
|
-
b.name.toLowerCase().endsWith('_id')
|
|
1453
|
+
b.name.toLowerCase().endsWith('_id') ||
|
|
1454
|
+
b.name.endsWith('Id');
|
|
1354
1455
|
if (aIsId && !bIsId)
|
|
1355
1456
|
return 1;
|
|
1356
1457
|
if (bIsId && !aIsId)
|
|
@@ -1367,7 +1468,8 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1367
1468
|
return false;
|
|
1368
1469
|
const allColumns = orderedColumnNames.filter((row) => {
|
|
1369
1470
|
const [table, _] = row.split('.');
|
|
1370
|
-
|
|
1471
|
+
const selectedTable = selectedColumns[0].split('.')[0];
|
|
1472
|
+
return selectedTable === table;
|
|
1371
1473
|
});
|
|
1372
1474
|
return selectedColumns.length === allColumns.length;
|
|
1373
1475
|
};
|
|
@@ -1386,12 +1488,12 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1386
1488
|
fontSize: 18,
|
|
1387
1489
|
margin: 0,
|
|
1388
1490
|
textAlign: 'left',
|
|
1389
|
-
}, children: "Add condition" }), _jsx(
|
|
1491
|
+
}, children: "Add condition" }), _jsx(TabsComponent, { value: topLevelBinaryOperator, options: DEFAULT_TAB_OPTIONS, onChange: (event) => setTopLevelBinaryOperator(event.target.value) }), activeEditItem && renderNode(activeEditItem), _jsx("div", { style: {
|
|
1390
1492
|
display: 'flex',
|
|
1391
1493
|
flexDirection: 'row',
|
|
1392
1494
|
gap: 8,
|
|
1393
1495
|
justifyContent: 'end',
|
|
1394
|
-
}, children: _jsx(
|
|
1496
|
+
}, children: _jsx(ButtonComponent, { onClick: onSave, label: 'Add condition' }) })] }));
|
|
1395
1497
|
};
|
|
1396
1498
|
const fetchUponChange = async (baseAst, newFormData) => {
|
|
1397
1499
|
// if newFormData is null still use it
|
|
@@ -1410,26 +1512,24 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1410
1512
|
orgId: client.customerId,
|
|
1411
1513
|
}),
|
|
1412
1514
|
});
|
|
1515
|
+
const tables = getTableNames(baseAst);
|
|
1516
|
+
const table = tables.length >= 1 ? tables[0] : initialTableName;
|
|
1517
|
+
if (table !== currentTable) {
|
|
1518
|
+
await getDistinctValues(table);
|
|
1519
|
+
setCurrentTable(table);
|
|
1520
|
+
}
|
|
1413
1521
|
const data2 = await res2.json();
|
|
1414
1522
|
if (data2.rows && data2.rows.length) {
|
|
1415
1523
|
const tables = getTableNames(baseAst);
|
|
1416
|
-
const table = tables.length >= 1 ? tables[0] : initialTableName;
|
|
1417
|
-
if (table !== currentTable) {
|
|
1418
|
-
getDistinctValues(table);
|
|
1419
|
-
setCurrentTable(table);
|
|
1420
|
-
}
|
|
1421
|
-
const sortedFields = data2.fields.sort((a, b) => {
|
|
1422
|
-
const aIsId = a.name.toLowerCase() === 'id' ||
|
|
1423
|
-
a.name.toLowerCase().endsWith('_id');
|
|
1424
|
-
const bIsId = b.name.toLowerCase() === 'id' ||
|
|
1425
|
-
b.name.toLowerCase().endsWith('_id');
|
|
1426
|
-
if (aIsId && !bIsId)
|
|
1427
|
-
return 1;
|
|
1428
|
-
if (bIsId && !aIsId)
|
|
1429
|
-
return -1;
|
|
1430
|
-
return 0;
|
|
1431
|
-
});
|
|
1432
1524
|
if (pivot) {
|
|
1525
|
+
// check if any of the pivot fields aren't in the data2.fields array
|
|
1526
|
+
if (!isValidPivot(data2.fields)) {
|
|
1527
|
+
setPivot(null);
|
|
1528
|
+
setPivotData(null);
|
|
1529
|
+
setRows(data2.rows);
|
|
1530
|
+
setFields(data2.fields);
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1433
1533
|
// Do all of this to make sure we have the right unique columns when applying a pivot
|
|
1434
1534
|
let uniqueFormatted = {};
|
|
1435
1535
|
const uniqueRecords = Array.from(new Set(data2.rows.map((row) => row[pivot.columnField]))).reduce((acc, curr) => {
|
|
@@ -1654,11 +1754,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1654
1754
|
newAst = convertRemoveSimpleParentheses(newAst);
|
|
1655
1755
|
const table = getTableNames(newAst)[0] ?? initialTableName;
|
|
1656
1756
|
const tableAlias = getTableAliases(newAst)[0] ?? initialTableName;
|
|
1657
|
-
newAst = removeNonSelectedTableReferences(newAst, tableAlias ?? table);
|
|
1757
|
+
newAst = removeNonSelectedTableReferences(newAst, tableAlias ?? table, getAllPossibleColumns().map((col) => col.name));
|
|
1658
1758
|
// newAst = convertDateComparison(newAst); // TODO
|
|
1659
|
-
ast = newAst; // so we fetch data for newAst later.
|
|
1660
1759
|
if (table !== currentTable) {
|
|
1661
|
-
getDistinctValues(table);
|
|
1760
|
+
await getDistinctValues(table);
|
|
1662
1761
|
setCurrentTable(table);
|
|
1663
1762
|
}
|
|
1664
1763
|
setPivotRowField(groupByPivot?.rowField);
|
|
@@ -1676,6 +1775,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1676
1775
|
}));
|
|
1677
1776
|
if (groupByPivot) {
|
|
1678
1777
|
setBaseAst(deepCopy({ ...newAst, orderby: null, limit: null }));
|
|
1778
|
+
newAst = deepCopy({ ...newAst, orderby: null, limit: null });
|
|
1679
1779
|
}
|
|
1680
1780
|
else {
|
|
1681
1781
|
setBaseAst(deepCopy({ ...newAst }));
|
|
@@ -1685,6 +1785,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1685
1785
|
// @ts-ignore
|
|
1686
1786
|
newAst?.where ? newAst?.where?.operator : 'AND');
|
|
1687
1787
|
}
|
|
1788
|
+
ast = newAst; // so we fetch data for newAst later.
|
|
1688
1789
|
const res2 = await fetch('https://quill-344421.uc.r.appspot.com/patterns', {
|
|
1689
1790
|
method: 'POST',
|
|
1690
1791
|
headers: {
|
|
@@ -1765,11 +1866,11 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1765
1866
|
fetchSqlQuery(newAst);
|
|
1766
1867
|
};
|
|
1767
1868
|
function TopLevelBooleanSwitch({ node, keyPrefix, handleOperatorChange, }) {
|
|
1768
|
-
return (_jsx("div", { style: { width: 'fit-content' }, children: _jsx(
|
|
1869
|
+
return (_jsx("div", { style: { width: 'fit-content' }, children: _jsx(TabsComponent, { value: node.operator, options: DEFAULT_TAB_OPTIONS, onChange: (event) => {
|
|
1769
1870
|
if (loading) {
|
|
1770
1871
|
return;
|
|
1771
1872
|
}
|
|
1772
|
-
handleOperatorChange(value, node, keyPrefix);
|
|
1873
|
+
handleOperatorChange(event.target.value, node, keyPrefix);
|
|
1773
1874
|
} }) }));
|
|
1774
1875
|
}
|
|
1775
1876
|
const DraggableItem = ({ id, label, onDelete }) => {
|
|
@@ -1778,9 +1879,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1778
1879
|
transform: DND_CSS.Transform.toString(transform),
|
|
1779
1880
|
transition,
|
|
1780
1881
|
};
|
|
1781
|
-
return (_jsx("div", { style: { ...style }, ref: setNodeRef, children: _jsx(
|
|
1882
|
+
return (_jsx("div", { style: { ...style }, ref: setNodeRef, children: _jsx(DraggableColumnComponent, { label: snakeCaseToTitleCase(label), onDelete: onDelete, DragHandle: (props) => (_jsx("div", { style: {
|
|
1782
1883
|
cursor: 'grab',
|
|
1783
|
-
}, ...attributes, ...listeners, children: _jsx(
|
|
1884
|
+
}, ...attributes, ...listeners, children: _jsx(props.dragIcon, {}) })) }) }));
|
|
1784
1885
|
};
|
|
1785
1886
|
function DraggableColumns() {
|
|
1786
1887
|
const sensors = useSensors(useSensor(PointerSensor), useSensor(KeyboardSensor, {
|
|
@@ -1790,8 +1891,8 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1790
1891
|
function handleDragEnd(event) {
|
|
1791
1892
|
const { active, over } = event;
|
|
1792
1893
|
if (active.id !== over.id) {
|
|
1793
|
-
const oldIndex = orderedColumnNames.findIndex((c) => c.endsWith(active.id));
|
|
1794
|
-
const newIndex = orderedColumnNames.findIndex((c) => c.endsWith(over.id));
|
|
1894
|
+
const oldIndex = orderedColumnNames.findIndex((c) => c.endsWith(`${currentTable}.${active.id}`));
|
|
1895
|
+
const newIndex = orderedColumnNames.findIndex((c) => c.endsWith(`${currentTable}.${over.id}`));
|
|
1795
1896
|
const newOrder = arrayMove(orderedColumnNames, oldIndex, newIndex);
|
|
1796
1897
|
setOrderedColumnNames(newOrder);
|
|
1797
1898
|
const orderedSelectedColumns = [];
|
|
@@ -1846,23 +1947,27 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1846
1947
|
flexDirection: 'row',
|
|
1847
1948
|
height: '100%',
|
|
1848
1949
|
...containerStyle,
|
|
1849
|
-
}, ref: parentRef, children: [_jsxs(
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1950
|
+
}, ref: parentRef, children: [_jsxs(SidebarComponent, { children: [_jsx(SidebarHeadingComponent, { label: "Columns" }), _jsx("div", { style: { height: 4, width: '100%' } }), _jsx(DraggableColumns, {}), _jsx(SecondaryButtonComponent, { onClick: () => {
|
|
1951
|
+
if (loadingSchema)
|
|
1952
|
+
return;
|
|
1953
|
+
if (!openPopover) {
|
|
1954
|
+
setOpenPopover('AddColumnPopover');
|
|
1955
|
+
}
|
|
1956
|
+
}, label: 'Select columns' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddColumnPopover', setIsOpen: (isOpen) => {
|
|
1957
|
+
if (!isOpen) {
|
|
1958
|
+
setIsPending(false);
|
|
1959
|
+
setActiveEditItem(null);
|
|
1960
|
+
setActivePath(null);
|
|
1961
|
+
setOpenPopover(null);
|
|
1962
|
+
}
|
|
1963
|
+
}, popoverTitle: "Select columns", popoverChildren: _jsx(AddColumnPopover, { onSave: () => {
|
|
1859
1964
|
setActiveEditItem(null);
|
|
1860
1965
|
setActivePath(null);
|
|
1861
1966
|
setOpenPopover(null);
|
|
1862
1967
|
}, orderedColumnNames: orderedColumnNames, setOrderedColumnNames: setOrderedColumnNames, selectedColumns: selectedColumns, setSelectedColumns: setSelectedColumns, isSelectedAllColumns: isSelectedAllColumns, clearAllState: clearAllState, nameToColumn: nameToColumn, baseAst: baseAst, setBaseAst: (newAst) => {
|
|
1863
1968
|
setBaseAst(newAst);
|
|
1864
1969
|
fetchSqlQuery(newAst);
|
|
1865
|
-
}, pivot: pivot, initialTableName: initialTableName, defaultAST: defaultAST, defaultTable: defaultTable, setPivot: setPivot, TextInput:
|
|
1970
|
+
}, pivot: pivot, initialTableName: initialTableName, defaultAST: defaultAST, defaultTable: defaultTable, setPivot: setPivot, TextInput: TextInputComponent, SelectColumn: SelectColumnComponent, SecondaryButton: SecondaryButtonComponent, Button: ButtonComponent }) }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeadingComponent, { label: "Filters" }), _jsx("div", { style: { height: 4, width: '100%' } }), formData && (_jsx("div", { style: {
|
|
1866
1971
|
display: 'flex',
|
|
1867
1972
|
flexDirection: 'column',
|
|
1868
1973
|
gap: 8,
|
|
@@ -1872,37 +1977,41 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1872
1977
|
flexDirection: 'column',
|
|
1873
1978
|
gap: 2.5,
|
|
1874
1979
|
alignItems: 'flex-start',
|
|
1875
|
-
}, children: [_jsx(
|
|
1876
|
-
|
|
1877
|
-
|
|
1980
|
+
}, children: [_jsx(SecondaryButtonComponent, { onClick: () => {
|
|
1981
|
+
if (!selectedColumns ||
|
|
1982
|
+
selectedColumns.length === 0 ||
|
|
1983
|
+
loading) {
|
|
1984
|
+
return;
|
|
1985
|
+
}
|
|
1986
|
+
if (!openPopover) {
|
|
1987
|
+
const value = orderedColumnNames[0];
|
|
1988
|
+
const [_table, column] = value.split('.');
|
|
1989
|
+
const columnType = getColumnTypeByName(column);
|
|
1990
|
+
if (isNumericColumnType(columnType)) {
|
|
1991
|
+
const newSubtree = deepCopy(defaultNumericComparison);
|
|
1992
|
+
newSubtree.left.column = column;
|
|
1993
|
+
setActiveEditItem(newSubtree);
|
|
1878
1994
|
}
|
|
1879
|
-
|
|
1880
|
-
const
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
if (isNumericColumnType(columnType)) {
|
|
1884
|
-
const newSubtree = deepCopy(defaultNumericComparison);
|
|
1885
|
-
newSubtree.left.column = column;
|
|
1886
|
-
setActiveEditItem(newSubtree);
|
|
1887
|
-
}
|
|
1888
|
-
else {
|
|
1889
|
-
const newSubtree = deepCopy(defaultEntry);
|
|
1890
|
-
newSubtree.left.args.value[0].column = column;
|
|
1891
|
-
setActiveEditItem(newSubtree);
|
|
1892
|
-
}
|
|
1893
|
-
setOpenPopover('AddFilterPopover');
|
|
1894
|
-
setActivePath('');
|
|
1895
|
-
setIsPending(true);
|
|
1995
|
+
else {
|
|
1996
|
+
const newSubtree = deepCopy(defaultEntry);
|
|
1997
|
+
newSubtree.left.args.value[0].column = column;
|
|
1998
|
+
setActiveEditItem(newSubtree);
|
|
1896
1999
|
}
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
2000
|
+
setOpenPopover('AddFilterPopover');
|
|
2001
|
+
setActivePath('');
|
|
2002
|
+
setIsPending(true);
|
|
2003
|
+
}
|
|
2004
|
+
}, label: 'Add filter' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddFilterPopover', setIsOpen: (isOpen) => {
|
|
2005
|
+
if (!isOpen) {
|
|
2006
|
+
setIsPending(false);
|
|
2007
|
+
setActivePath(null);
|
|
2008
|
+
setOpenPopover(null);
|
|
2009
|
+
clearCheckboxes();
|
|
2010
|
+
setTimeout(() => {
|
|
2011
|
+
setActiveEditItem(null);
|
|
2012
|
+
}, 300);
|
|
2013
|
+
}
|
|
2014
|
+
}, popoverTitle: 'Add filter', popoverChildren: _jsx(AddFilterPopover, { onSave: () => {
|
|
1906
2015
|
if (isNodeEmptyCollection(activeEditItem)) {
|
|
1907
2016
|
setIsPending(false);
|
|
1908
2017
|
setActivePath(null);
|
|
@@ -1922,44 +2031,46 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1922
2031
|
setActiveEditItem(null);
|
|
1923
2032
|
}, 300);
|
|
1924
2033
|
}
|
|
1925
|
-
}, Button:
|
|
2034
|
+
}, Button: ButtonComponent, renderNode: renderNode, activeEditItem: activeEditItem }) }), baseAst?.where &&
|
|
1926
2035
|
false && ( // temp removed the AddConditionPopover
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
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
|
-
|
|
2036
|
+
_jsxs(_Fragment, { children: [_jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2037
|
+
if (!openPopover) {
|
|
2038
|
+
setActiveEditItem(deepCopy(defaultEntry));
|
|
2039
|
+
setOpenPopover('AddConditionPopover');
|
|
2040
|
+
setActivePath('');
|
|
2041
|
+
setIsPending(true);
|
|
2042
|
+
}
|
|
2043
|
+
}, label: "Add condition" }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddConditionPopover', setIsOpen: (isOpen) => {
|
|
2044
|
+
if (!isOpen) {
|
|
2045
|
+
setIsPending(false);
|
|
2046
|
+
setTimeout(() => {
|
|
2047
|
+
setActiveEditItem(null);
|
|
2048
|
+
}, 300);
|
|
2049
|
+
setActivePath(null);
|
|
2050
|
+
setOpenPopover(null);
|
|
2051
|
+
clearCheckboxes();
|
|
2052
|
+
}
|
|
2053
|
+
}, popoverTitle: "Add condition", popoverChildren: _jsx(AddConditionPopover, { onSave: () => {
|
|
2054
|
+
if (isNodeEmptyCollection(activeEditItem)) {
|
|
2055
|
+
setIsPending(false);
|
|
2056
|
+
setTimeout(() => {
|
|
2057
|
+
setActiveEditItem(null);
|
|
2058
|
+
}, 300);
|
|
2059
|
+
setActivePath(null);
|
|
2060
|
+
setOpenPopover(null);
|
|
2061
|
+
clearCheckboxes();
|
|
2062
|
+
}
|
|
2063
|
+
else {
|
|
2064
|
+
setIsPending(false);
|
|
2065
|
+
handleInsertion(activeEditItem, topLevelBinaryOperator, true);
|
|
2066
|
+
setTimeout(() => {
|
|
2067
|
+
setActiveEditItem(null);
|
|
2068
|
+
}, 300);
|
|
2069
|
+
setActivePath(null);
|
|
2070
|
+
setOpenPopover(null);
|
|
2071
|
+
clearCheckboxes();
|
|
2072
|
+
}
|
|
2073
|
+
} }) })] }))] }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeadingComponent, { label: "Pivot" }), _jsx("div", { style: { height: 4, width: '100%' } }), _jsx(PivotModal, { pivotRowField: pivotRowField, setPivotRowField: setPivotRowField, pivotColumnField: pivotColumnField, setPivotColumnField: setPivotColumnField, pivotValueField: pivotValueField, setPivotValueField: setPivotValueField, pivotAggregation: pivotAggregation, setPivotAggregation: setPivotAggregation, createdPivots: createdPivots, setCreatedPivots: setCreatedPivots, recommendedPivots: recommendedPivots, setRecommendedPivots: setRecommendedPivots, popUpTitle: pivotPopUpTitle, setPopUpTitle: setPivotPopUpTitle, selectedTable: initialTableName, SelectComponent: SelectComponent, ButtonComponent: ButtonComponent, PopoverComponent: PopoverComponent, TextComponent: TextComponent, isOpen: showPivotPopover, setIsOpen: setShowPivotPopover, showUpdatePivot: isEdittingPivot, setShowUpdatePivot: setIsEdittingPivot, parentRef: parentRef, data: rows, columns: processColumnsForChartBuilder(Object.keys(rows[0] ?? {})), triggerButtonText: 'Add pivot', selectedPivotIndex: selectedPivotIndex, setSelectedPivotIndex: setSelectedPivotIndex, removePivot: () => {
|
|
1963
2074
|
setPivot(null);
|
|
1964
2075
|
setPivotData(null);
|
|
1965
2076
|
},
|
|
@@ -1973,7 +2084,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1973
2084
|
setPivot(pivot);
|
|
1974
2085
|
const pivotedData = generatePivotTable(pivot, rows, [null, null, null], false);
|
|
1975
2086
|
setPivotData(pivotedData || []);
|
|
1976
|
-
}, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent:
|
|
2087
|
+
}, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent: LabelComponent, HeaderComponent: HeaderComponent, dateRange: [null, null, null], recommendPivotCount: 3, SecondaryButtonComponent: SecondaryButtonComponent }), pivot && (_jsx(PivotCard, { pivotTable: {
|
|
1977
2088
|
pivot: pivot,
|
|
1978
2089
|
rows: pivotData?.rows || [],
|
|
1979
2090
|
columns: pivotData?.columns || [],
|
|
@@ -1985,11 +2096,11 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1985
2096
|
setPivotValueField(pivot?.valueField);
|
|
1986
2097
|
setPivotAggregation(pivot?.aggregationType);
|
|
1987
2098
|
setPivotPopUpTitle('Edit Pivot');
|
|
1988
|
-
}, selectedPivotIndex: -1, onEditPivot: () => { }, ButtonComponent:
|
|
2099
|
+
}, selectedPivotIndex: -1, onEditPivot: () => { }, ButtonComponent: ButtonComponent, HeaderComponent: HeaderComponent, showEdit: false, onClose: () => {
|
|
1989
2100
|
setPivot(null);
|
|
1990
2101
|
setPivotData(null);
|
|
1991
2102
|
setBaseAst(deepCopy(baseAst)); // trigger refetch
|
|
1992
|
-
}, minHeight: 180, LabelComponent:
|
|
2103
|
+
}, minHeight: 180, LabelComponent: LabelComponent, TextComponent: TextComponent })), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeadingComponent, { label: "Sort" }), _jsx("div", { style: { height: 4, width: '100%' } }), pivot && pivot.sort && (_jsx("div", { style: {
|
|
1993
2104
|
display: 'flex',
|
|
1994
2105
|
flexDirection: 'column',
|
|
1995
2106
|
gap: 8,
|
|
@@ -1997,7 +2108,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1997
2108
|
}, children: _jsx(SortSentence, { sortData: {
|
|
1998
2109
|
type: pivot.sortDirection,
|
|
1999
2110
|
expr: { type: 'column_ref', column: pivot.rowField },
|
|
2000
|
-
}, columns: selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover:
|
|
2111
|
+
}, columns: selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setActivePath: setActivePath, setOpenPopover: setOpenPopover, SortPopover: SortPopoverComponent, EditPopover: AddSortPopover, handleDelete: () => {
|
|
2001
2112
|
setPivot({ ...pivot, sort: false });
|
|
2002
2113
|
setBaseAst(deepCopy(baseAst));
|
|
2003
2114
|
if (!pivot) {
|
|
@@ -2010,7 +2121,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2010
2121
|
if (!pivot) {
|
|
2011
2122
|
fetchSqlQuery(baseAst);
|
|
2012
2123
|
}
|
|
2013
|
-
} }, `sort-sentence-pivot`) })), baseAst && baseAst.orderby && (_jsx("div", { style: {
|
|
2124
|
+
}, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent }, `sort-sentence-pivot`) })), baseAst && baseAst.orderby && (_jsx("div", { style: {
|
|
2014
2125
|
display: 'flex',
|
|
2015
2126
|
flexDirection: 'column',
|
|
2016
2127
|
gap: 8,
|
|
@@ -2037,31 +2148,33 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2037
2148
|
if (!pivot) {
|
|
2038
2149
|
fetchSqlQuery(newAst);
|
|
2039
2150
|
}
|
|
2040
|
-
}, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover:
|
|
2151
|
+
}, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setActivePath: setActivePath, setOpenPopover: setOpenPopover, SortPopover: SortPopoverComponent, EditPopover: AddSortPopover, handleDelete: () => {
|
|
2041
2152
|
const newAst = { ...baseAst };
|
|
2042
2153
|
newAst.orderby.splice(id, 1);
|
|
2043
2154
|
setBaseAst(deepCopy(newAst));
|
|
2044
2155
|
if (!pivot) {
|
|
2045
2156
|
fetchSqlQuery(newAst);
|
|
2046
2157
|
}
|
|
2047
|
-
} }, `sort-sentence-${id}`))) })), _jsx(
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2158
|
+
}, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent }, `sort-sentence-${id}`))) })), _jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2159
|
+
if (!selectedColumns || selectedColumns.length === 0) {
|
|
2160
|
+
return;
|
|
2161
|
+
}
|
|
2162
|
+
if (!openPopover) {
|
|
2163
|
+
setOpenPopover('AddSortPopover');
|
|
2164
|
+
}
|
|
2165
|
+
}, label: "Add sort" }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddSortPopover', setIsOpen: (isOpen) => {
|
|
2166
|
+
if (!isOpen) {
|
|
2167
|
+
setIsPending(false);
|
|
2168
|
+
setActiveEditItem(null);
|
|
2169
|
+
setActivePath(null);
|
|
2170
|
+
setOpenPopover(null);
|
|
2171
|
+
}
|
|
2172
|
+
}, popoverTitle: "Sort by", popoverChildren: _jsx(AddSortPopover, { columns: selectedColumns, Select: SelectComponent, Button: ButtonComponent, onSave: () => { } }) }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeadingComponent, { label: "Limit" }), _jsx("div", { style: { height: 4, width: '100%' } }), baseAst && baseAst.limit ? (_jsx("div", { style: {
|
|
2060
2173
|
display: 'flex',
|
|
2061
2174
|
flexDirection: 'column',
|
|
2062
2175
|
gap: 8,
|
|
2063
2176
|
marginBottom: 12,
|
|
2064
|
-
}, children: _jsx(LimitSentence, { limit: baseAst.limit, setOpenPopover: setOpenPopover, LimitPopover:
|
|
2177
|
+
}, children: _jsx(LimitSentence, { limit: baseAst.limit, setOpenPopover: setOpenPopover, LimitPopover: LimitPopoverComponent, EditPopover: AddLimitPopover, handleDelete: () => {
|
|
2065
2178
|
const newAst = { ...baseAst };
|
|
2066
2179
|
newAst.limit = null;
|
|
2067
2180
|
setBaseAst(deepCopy(newAst));
|
|
@@ -2080,27 +2193,29 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2080
2193
|
setOpenPopover(null);
|
|
2081
2194
|
setBaseAst(deepCopy(newAst));
|
|
2082
2195
|
fetchSqlQuery(newAst);
|
|
2083
|
-
}
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2196
|
+
}, TextInput: TextInputComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent }) })) : (_jsxs(_Fragment, { children: [_jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2197
|
+
if (!openPopover) {
|
|
2198
|
+
setOpenPopover('AddLimitPopover');
|
|
2199
|
+
}
|
|
2200
|
+
}, label: 'Add limit' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddLimitPopover', setIsOpen: (isOpen) => {
|
|
2201
|
+
if (!isOpen) {
|
|
2202
|
+
setIsPending(false);
|
|
2203
|
+
setActiveEditItem(null);
|
|
2204
|
+
setActivePath(null);
|
|
2205
|
+
setOpenPopover(null);
|
|
2206
|
+
}
|
|
2207
|
+
}, popoverTitle: "Limit", popoverChildren: _jsx(TextInputComponent, { id: "loading_input_limit", value: '0', width: 120, onChange: () => { } }) })] }))] }), _jsxs(ContainerComponent, { children: [isAIEnabled && (_jsxs("form", { ref: askAILoadingContainerRef, onSubmit: (event) => {
|
|
2093
2208
|
event.preventDefault();
|
|
2094
2209
|
}, style: {
|
|
2095
2210
|
display: 'flex',
|
|
2096
2211
|
flexDirection: 'row',
|
|
2097
2212
|
gap: 12,
|
|
2098
2213
|
padding: 1,
|
|
2099
|
-
}, children: [_jsx(
|
|
2214
|
+
}, children: [_jsx(TextInputComponent, { id: "ask_ai_loading_bar", placeholder: baseAst ? 'Ask a follow-up question...' : 'Ask a question...', width: askAILoadingContainerWidth, value: aiPrompt, onChange: () => { } }), _jsx(ButtonComponent, { onClick: () => { }, label: "Ask AI" }), baseAst && (_jsx(SecondaryButtonComponent, { onClick: clearAllState, label: "New report" }))] })), _jsxs(_Fragment, { children: [_jsx(TableComponent, { isLoading: true, rows: [], columns: [] }), _jsxs("div", { style: {
|
|
2100
2215
|
display: 'flex',
|
|
2101
2216
|
flexDirection: 'row',
|
|
2102
2217
|
gap: '12px',
|
|
2103
|
-
}, children: [_jsx("div", { style: { width: '100%' } }), _jsx(
|
|
2218
|
+
}, children: [_jsx("div", { style: { width: '100%' } }), _jsx(SecondaryButtonComponent, { onClick: () => copyToClipboard(activeQuery), label: isCopying ? '✅ Copied' : 'Copy SQL' }), _jsx(ButtonComponent, { label: 'Add to dashboard', onClick: () => { } })] })] })] }), _jsx("style", { children: `body{margin:0;}` })] }));
|
|
2104
2219
|
}
|
|
2105
2220
|
return (_jsxs("div", { ref: parentRef, style: {
|
|
2106
2221
|
display: 'flex',
|
|
@@ -2109,26 +2224,28 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2109
2224
|
overflowY: 'auto',
|
|
2110
2225
|
boxSizing: 'border-box',
|
|
2111
2226
|
...containerStyle,
|
|
2112
|
-
}, children: [_jsxs(
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2227
|
+
}, children: [_jsxs(SidebarComponent, { children: [_jsx(SidebarHeadingComponent, { label: "Columns" }), _jsx("div", { style: { height: 4, width: '100%' } }), _jsx(DraggableColumns, {}), _jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2228
|
+
if (!openPopover) {
|
|
2229
|
+
setOpenPopover('AddColumnPopover');
|
|
2230
|
+
}
|
|
2231
|
+
}, label: "Select columns" }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddColumnPopover', setIsOpen: (isOpen) => {
|
|
2232
|
+
if (!isOpen) {
|
|
2233
|
+
// delay onClose callback so onClick no-ops
|
|
2234
|
+
setTimeout(() => {
|
|
2235
|
+
setIsPending(false);
|
|
2236
|
+
setActiveEditItem(null);
|
|
2237
|
+
setActivePath(null);
|
|
2238
|
+
setOpenPopover(null);
|
|
2239
|
+
}, 100);
|
|
2240
|
+
}
|
|
2241
|
+
}, popoverTitle: "Select columns", popoverChildren: _jsx(AddColumnPopover, { onSave: () => {
|
|
2125
2242
|
setActiveEditItem(null);
|
|
2126
2243
|
setActivePath(null);
|
|
2127
2244
|
setOpenPopover(null);
|
|
2128
2245
|
}, orderedColumnNames: orderedColumnNames, setOrderedColumnNames: setOrderedColumnNames, selectedColumns: selectedColumns, setSelectedColumns: setSelectedColumns, isSelectedAllColumns: isSelectedAllColumns, clearAllState: clearAllState, nameToColumn: nameToColumn, baseAst: baseAst, setBaseAst: (ast) => {
|
|
2129
2246
|
setBaseAst(ast);
|
|
2130
2247
|
fetchSqlQuery(ast);
|
|
2131
|
-
}, pivot: pivot, initialTableName: initialTableName, defaultAST: defaultAST, defaultTable: defaultTable, setPivot: setPivot, TextInput:
|
|
2248
|
+
}, pivot: pivot, initialTableName: initialTableName, defaultAST: defaultAST, defaultTable: defaultTable, setPivot: setPivot, TextInput: TextInputComponent, SelectColumn: SelectColumnComponent, SecondaryButton: SecondaryButtonComponent, Button: ButtonComponent }) }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeadingComponent, { label: "Filters" }), _jsx("div", { style: { height: 4, width: '100%' } }), formData && (_jsx("div", { style: {
|
|
2132
2249
|
display: 'flex',
|
|
2133
2250
|
flexDirection: 'column',
|
|
2134
2251
|
gap: 8,
|
|
@@ -2138,50 +2255,42 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2138
2255
|
flexDirection: 'column',
|
|
2139
2256
|
gap: 2.5,
|
|
2140
2257
|
alignItems: 'flex-start',
|
|
2141
|
-
}, children: [_jsx(
|
|
2142
|
-
|
|
2143
|
-
|
|
2258
|
+
}, children: [_jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2259
|
+
if (!selectedColumns || selectedColumns.length === 0 || loading) {
|
|
2260
|
+
return;
|
|
2261
|
+
}
|
|
2262
|
+
if (!openPopover) {
|
|
2263
|
+
const value = orderedColumnNames[0];
|
|
2264
|
+
const [_table, column] = value.split('.');
|
|
2265
|
+
const columnType = getColumnTypeByName(column);
|
|
2266
|
+
if (isNumericColumnType(columnType)) {
|
|
2267
|
+
const newSubtree = deepCopy(defaultNumericComparison);
|
|
2268
|
+
newSubtree.left.column = column;
|
|
2269
|
+
setActiveEditItem(newSubtree);
|
|
2144
2270
|
}
|
|
2145
|
-
|
|
2146
|
-
const
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
if (isNumericColumnType(columnType)) {
|
|
2150
|
-
const newSubtree = deepCopy(defaultNumericComparison);
|
|
2151
|
-
newSubtree.left.column = column;
|
|
2152
|
-
setActiveEditItem(newSubtree);
|
|
2153
|
-
}
|
|
2154
|
-
else {
|
|
2155
|
-
const newSubtree = deepCopy(defaultEntry);
|
|
2156
|
-
newSubtree.left.args.value[0].column = column;
|
|
2157
|
-
setActiveEditItem(newSubtree);
|
|
2158
|
-
}
|
|
2159
|
-
setOpenPopover('AddFilterPopover');
|
|
2160
|
-
setActivePath('');
|
|
2161
|
-
setIsPending(true);
|
|
2271
|
+
else {
|
|
2272
|
+
const newSubtree = deepCopy(defaultEntry);
|
|
2273
|
+
newSubtree.left.args.value[0].column = column;
|
|
2274
|
+
setActiveEditItem(newSubtree);
|
|
2162
2275
|
}
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
}, 200);
|
|
2172
|
-
}, children: _jsx(AddFilterPopover, { onSave: () => {
|
|
2173
|
-
if (isNodeEmptyCollection(activeEditItem)) {
|
|
2276
|
+
setOpenPopover('AddFilterPopover');
|
|
2277
|
+
setActivePath('');
|
|
2278
|
+
setIsPending(true);
|
|
2279
|
+
}
|
|
2280
|
+
}, label: 'Add filter' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddFilterPopover', setIsOpen: (isOpen) => {
|
|
2281
|
+
if (!isOpen) {
|
|
2282
|
+
// delay onClose callback so onClick no-ops
|
|
2283
|
+
setTimeout(() => {
|
|
2174
2284
|
setIsPending(false);
|
|
2175
2285
|
setActivePath(null);
|
|
2176
2286
|
setOpenPopover(null);
|
|
2177
2287
|
clearCheckboxes();
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2288
|
+
setActiveEditItem(null);
|
|
2289
|
+
}, 200);
|
|
2290
|
+
}
|
|
2291
|
+
}, popoverTitle: "Add filter", popoverChildren: _jsx(AddFilterPopover, { onSave: () => {
|
|
2292
|
+
if (isNodeEmptyCollection(activeEditItem)) {
|
|
2183
2293
|
setIsPending(false);
|
|
2184
|
-
handleInsertion(activeEditItem, 'AND', false);
|
|
2185
2294
|
setActivePath(null);
|
|
2186
2295
|
setOpenPopover(null);
|
|
2187
2296
|
clearCheckboxes();
|
|
@@ -2189,45 +2298,57 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2189
2298
|
setActiveEditItem(null);
|
|
2190
2299
|
}, 300);
|
|
2191
2300
|
}
|
|
2192
|
-
|
|
2193
|
-
false && ( // temp removed the AddConditionPopover
|
|
2194
|
-
_jsx(Popover, { isOpen: openPopover === 'AddConditionPopover', trigger: _jsx(SecondaryButton, { onClick: () => {
|
|
2195
|
-
if (!openPopover) {
|
|
2196
|
-
setActiveEditItem(deepCopy(defaultEntry));
|
|
2197
|
-
setOpenPopover('AddConditionPopover');
|
|
2198
|
-
setActivePath('');
|
|
2199
|
-
setIsPending(true);
|
|
2200
|
-
}
|
|
2201
|
-
}, label: 'Add condition' }), onClose: () => {
|
|
2202
|
-
// delay onClose callback so onClick no-ops
|
|
2203
|
-
setTimeout(() => {
|
|
2204
|
-
setIsPending(false);
|
|
2205
|
-
setActiveEditItem(null);
|
|
2206
|
-
setActivePath(null);
|
|
2207
|
-
setOpenPopover(null);
|
|
2208
|
-
clearCheckboxes();
|
|
2209
|
-
}, 200);
|
|
2210
|
-
}, children: _jsx(AddConditionPopover, { onSave: () => {
|
|
2211
|
-
if (isNodeEmptyCollection(activeEditItem)) {
|
|
2301
|
+
else {
|
|
2212
2302
|
setIsPending(false);
|
|
2213
|
-
|
|
2214
|
-
setActiveEditItem(null);
|
|
2215
|
-
}, 300);
|
|
2303
|
+
handleInsertion(activeEditItem, 'AND', false);
|
|
2216
2304
|
setActivePath(null);
|
|
2217
2305
|
setOpenPopover(null);
|
|
2218
2306
|
clearCheckboxes();
|
|
2219
|
-
}
|
|
2220
|
-
else {
|
|
2221
|
-
setIsPending(false);
|
|
2222
|
-
handleInsertion(activeEditItem, topLevelBinaryOperator, true);
|
|
2223
2307
|
setTimeout(() => {
|
|
2224
2308
|
setActiveEditItem(null);
|
|
2225
2309
|
}, 300);
|
|
2226
|
-
setActivePath(null);
|
|
2227
|
-
setOpenPopover(null);
|
|
2228
|
-
clearCheckboxes();
|
|
2229
2310
|
}
|
|
2230
|
-
}
|
|
2311
|
+
}, Button: ButtonComponent, renderNode: renderNode, activeEditItem: activeEditItem }) }), baseAst?.where &&
|
|
2312
|
+
false && ( // temp removed the AddConditionPopover
|
|
2313
|
+
_jsxs(_Fragment, { children: [_jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2314
|
+
if (!openPopover) {
|
|
2315
|
+
setActiveEditItem(deepCopy(defaultEntry));
|
|
2316
|
+
setOpenPopover('AddConditionPopover');
|
|
2317
|
+
setActivePath('');
|
|
2318
|
+
setIsPending(true);
|
|
2319
|
+
}
|
|
2320
|
+
}, label: 'Add condition' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddConditionPopover', setIsOpen: (isOpen) => {
|
|
2321
|
+
if (!isOpen) {
|
|
2322
|
+
// delay onClose callback so onClick no-ops
|
|
2323
|
+
setTimeout(() => {
|
|
2324
|
+
setIsPending(false);
|
|
2325
|
+
setActiveEditItem(null);
|
|
2326
|
+
setActivePath(null);
|
|
2327
|
+
setOpenPopover(null);
|
|
2328
|
+
clearCheckboxes();
|
|
2329
|
+
}, 200);
|
|
2330
|
+
}
|
|
2331
|
+
}, popoverChildren: _jsx(AddConditionPopover, { onSave: () => {
|
|
2332
|
+
if (isNodeEmptyCollection(activeEditItem)) {
|
|
2333
|
+
setIsPending(false);
|
|
2334
|
+
setTimeout(() => {
|
|
2335
|
+
setActiveEditItem(null);
|
|
2336
|
+
}, 300);
|
|
2337
|
+
setActivePath(null);
|
|
2338
|
+
setOpenPopover(null);
|
|
2339
|
+
clearCheckboxes();
|
|
2340
|
+
}
|
|
2341
|
+
else {
|
|
2342
|
+
setIsPending(false);
|
|
2343
|
+
handleInsertion(activeEditItem, topLevelBinaryOperator, true);
|
|
2344
|
+
setTimeout(() => {
|
|
2345
|
+
setActiveEditItem(null);
|
|
2346
|
+
}, 300);
|
|
2347
|
+
setActivePath(null);
|
|
2348
|
+
setOpenPopover(null);
|
|
2349
|
+
clearCheckboxes();
|
|
2350
|
+
}
|
|
2351
|
+
} }) })] }))] }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeadingComponent, { label: "Pivot" }), _jsx("div", { style: { height: 4, width: '100%' } }), _jsx(PivotModal, { pivotRowField: pivotRowField, setPivotRowField: setPivotRowField, pivotColumnField: pivotColumnField, setPivotColumnField: setPivotColumnField, pivotValueField: pivotValueField, setPivotValueField: setPivotValueField, pivotAggregation: pivotAggregation, setPivotAggregation: setPivotAggregation, createdPivots: createdPivots, setCreatedPivots: setCreatedPivots, recommendedPivots: recommendedPivots, setRecommendedPivots: setRecommendedPivots, popUpTitle: pivotPopUpTitle, setPopUpTitle: setPivotPopUpTitle, selectedTable: initialTableName, SelectComponent: SelectComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, PopoverComponent: PopoverComponent, TextComponent: TextComponent, isOpen: showPivotPopover, setIsOpen: setShowPivotPopover, showUpdatePivot: isEdittingPivot, setShowUpdatePivot: setIsEdittingPivot, parentRef: parentRef, data: rows, columns: processColumnsForChartBuilder(Object.keys(rows[0] ?? {})), triggerButtonText: 'Add pivot', selectedPivotIndex: selectedPivotIndex, setSelectedPivotIndex: setSelectedPivotIndex, removePivot: () => {
|
|
2231
2352
|
setPivot(null);
|
|
2232
2353
|
setPivotData(null);
|
|
2233
2354
|
}, selectPivot: (pivot) => {
|
|
@@ -2243,7 +2364,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2243
2364
|
setPivot(pivot);
|
|
2244
2365
|
const pivotedData = generatePivotTable(pivot, rows, [null, null, null], false);
|
|
2245
2366
|
setPivotData(pivotedData || []);
|
|
2246
|
-
}, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent:
|
|
2367
|
+
}, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent: LabelComponent, HeaderComponent: HeaderComponent, dateRange: [null, null, null], recommendPivotCount: 3 }), pivot && (_jsx(PivotCard, { pivotTable: {
|
|
2247
2368
|
pivot: pivot,
|
|
2248
2369
|
rows: pivotData?.rows || [],
|
|
2249
2370
|
columns: pivotData?.columns || [],
|
|
@@ -2255,11 +2376,11 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2255
2376
|
setPivotValueField(pivot?.valueField);
|
|
2256
2377
|
setPivotAggregation(pivot?.aggregationType);
|
|
2257
2378
|
setPivotPopUpTitle('Edit Pivot');
|
|
2258
|
-
}, selectedPivotIndex: -1, onEditPivot: () => { }, ButtonComponent:
|
|
2379
|
+
}, selectedPivotIndex: -1, onEditPivot: () => { }, ButtonComponent: ButtonComponent, HeaderComponent: HeaderComponent, showEdit: false, onClose: () => {
|
|
2259
2380
|
setPivot(null);
|
|
2260
2381
|
setPivotData(null);
|
|
2261
2382
|
setBaseAst(deepCopy(baseAst));
|
|
2262
|
-
}, minHeight: 180, LabelComponent:
|
|
2383
|
+
}, minHeight: 180, LabelComponent: LabelComponent, TextComponent: TextComponent })), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeadingComponent, { label: "Sort" }), _jsx("div", { style: { height: 4, width: '100%' } }), pivot && pivot.sort && (_jsx("div", { style: {
|
|
2263
2384
|
display: 'flex',
|
|
2264
2385
|
flexDirection: 'column',
|
|
2265
2386
|
gap: 8,
|
|
@@ -2267,7 +2388,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2267
2388
|
}, children: _jsx(SortSentence, { sortData: {
|
|
2268
2389
|
type: pivot.sortDirection,
|
|
2269
2390
|
expr: { type: 'column_ref', column: pivot.rowField },
|
|
2270
|
-
}, columns: pivot ? [`.${pivot.rowField}`] : selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover:
|
|
2391
|
+
}, columns: pivot ? [`.${pivot.rowField}`] : selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setActivePath: setActivePath, setOpenPopover: setOpenPopover, SortPopover: SortPopoverComponent, EditPopover: AddSortPopover, handleDelete: () => {
|
|
2271
2392
|
if (pivot) {
|
|
2272
2393
|
setPivot({ ...pivot, sort: false });
|
|
2273
2394
|
const pivotedData = generatePivotTable({ ...pivot, sort: false }, rows, [null, null, null], false);
|
|
@@ -2286,12 +2407,12 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2286
2407
|
setOpenPopover(null);
|
|
2287
2408
|
setBaseAst(deepCopy(baseAst));
|
|
2288
2409
|
fetchSqlQuery(deepCopy(baseAst));
|
|
2289
|
-
} }, `sort-sentence-pivot`) })), baseAst && baseAst.orderby && (_jsx("div", { style: {
|
|
2410
|
+
}, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent }, `sort-sentence-pivot`) })), baseAst && baseAst.orderby && (_jsx("div", { style: {
|
|
2290
2411
|
display: 'flex',
|
|
2291
2412
|
flexDirection: 'column',
|
|
2292
2413
|
gap: 8,
|
|
2293
2414
|
marginBottom: 12,
|
|
2294
|
-
}, children: baseAst.orderby.map((sortData, id) => (_jsx(SortSentence, { sortData: sortData, columns: selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover:
|
|
2415
|
+
}, children: baseAst.orderby.map((sortData, id) => (_jsx(SortSentence, { sortData: sortData, columns: selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setActivePath: setActivePath, setOpenPopover: setOpenPopover, SortPopover: SortPopoverComponent, EditPopover: AddSortPopover, handleDelete: () => {
|
|
2295
2416
|
if (pivot) {
|
|
2296
2417
|
setPivot({ ...pivot, sort: false });
|
|
2297
2418
|
return;
|
|
@@ -2328,19 +2449,21 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2328
2449
|
setOpenPopover(null);
|
|
2329
2450
|
setBaseAst(deepCopy(newAst));
|
|
2330
2451
|
fetchSqlQuery(deepCopy(newAst));
|
|
2331
|
-
} }, `sort-sentence-${id}`))) })), _jsx(
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2452
|
+
}, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent }, `sort-sentence-${id}`))) })), _jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2453
|
+
if (!selectedColumns || selectedColumns.length === 0) {
|
|
2454
|
+
return;
|
|
2455
|
+
}
|
|
2456
|
+
if (!openPopover) {
|
|
2457
|
+
setOpenPopover('AddSortPopover');
|
|
2458
|
+
}
|
|
2459
|
+
}, label: 'Add sort' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddSortPopover', setIsOpen: (isOpen) => {
|
|
2460
|
+
if (!isOpen) {
|
|
2461
|
+
setIsPending(false);
|
|
2462
|
+
setActiveEditItem(null);
|
|
2463
|
+
setActivePath(null);
|
|
2464
|
+
setOpenPopover(null);
|
|
2465
|
+
}
|
|
2466
|
+
}, popoverTitle: "Sort by", popoverChildren: _jsx(AddSortPopover, { columns: pivot ? [`.${pivot.rowField}`] : selectedColumns, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, onSave: (column, direction) => {
|
|
2344
2467
|
if (column === '')
|
|
2345
2468
|
return;
|
|
2346
2469
|
if (pivot) {
|
|
@@ -2364,12 +2487,12 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2364
2487
|
setOpenPopover(null);
|
|
2365
2488
|
setBaseAst(deepCopy(newAst));
|
|
2366
2489
|
fetchSqlQuery(deepCopy(newAst));
|
|
2367
|
-
} }) }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(
|
|
2490
|
+
} }) }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeadingComponent, { label: "Limit" }), _jsx("div", { style: { height: 4, width: '100%' } }), baseAst && baseAst.limit ? (_jsx("div", { style: {
|
|
2368
2491
|
display: 'flex',
|
|
2369
2492
|
flexDirection: 'column',
|
|
2370
2493
|
gap: 8,
|
|
2371
2494
|
marginBottom: 12,
|
|
2372
|
-
}, children: _jsx(LimitSentence, { limit: baseAst.limit, setOpenPopover: setOpenPopover, LimitPopover:
|
|
2495
|
+
}, children: _jsx(LimitSentence, { limit: baseAst.limit, setOpenPopover: setOpenPopover, LimitPopover: LimitPopoverComponent, EditPopover: AddLimitPopover, handleDelete: () => {
|
|
2373
2496
|
const newAst = { ...baseAst };
|
|
2374
2497
|
newAst.limit = null;
|
|
2375
2498
|
setBaseAst(deepCopy(newAst));
|
|
@@ -2388,36 +2511,38 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2388
2511
|
setOpenPopover(null);
|
|
2389
2512
|
setBaseAst(deepCopy(newAst));
|
|
2390
2513
|
fetchSqlQuery(deepCopy(newAst));
|
|
2391
|
-
}
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2514
|
+
}, TextInput: TextInputComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent }) })) : (_jsxs(_Fragment, { children: [_jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2515
|
+
if (!selectedColumns || selectedColumns.length === 0) {
|
|
2516
|
+
return;
|
|
2517
|
+
}
|
|
2518
|
+
if (!baseAst) {
|
|
2519
|
+
return;
|
|
2520
|
+
}
|
|
2521
|
+
if (!openPopover) {
|
|
2522
|
+
setOpenPopover('AddLimitPopover');
|
|
2523
|
+
}
|
|
2524
|
+
}, label: 'Add limit' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddLimitPopover', setIsOpen: (isOpen) => {
|
|
2525
|
+
if (!isOpen) {
|
|
2526
|
+
setIsPending(false);
|
|
2527
|
+
setActiveEditItem(null);
|
|
2528
|
+
setActivePath(null);
|
|
2529
|
+
setOpenPopover(null);
|
|
2530
|
+
}
|
|
2531
|
+
}, popoverTitle: "Limit", popoverChildren: _jsx(AddLimitPopover, { TextInput: TextInputComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, onSave: (limit) => {
|
|
2532
|
+
const newAst = { ...baseAst };
|
|
2533
|
+
newAst.limit = {
|
|
2534
|
+
seperator: '',
|
|
2535
|
+
value: [
|
|
2536
|
+
{
|
|
2537
|
+
type: 'number',
|
|
2538
|
+
value: Number(limit),
|
|
2539
|
+
},
|
|
2540
|
+
],
|
|
2541
|
+
};
|
|
2542
|
+
setOpenPopover(null);
|
|
2543
|
+
setBaseAst(deepCopy(newAst));
|
|
2544
|
+
fetchSqlQuery(deepCopy(newAst));
|
|
2545
|
+
} }) })] }))] }), _jsxs(ContainerComponent, { children: [isAIEnabled && (_jsxs("form", { ref: askAIContainerRef, onSubmit: (event) => {
|
|
2421
2546
|
event.preventDefault();
|
|
2422
2547
|
handleAsk();
|
|
2423
2548
|
}, style: {
|
|
@@ -2425,14 +2550,14 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2425
2550
|
flexDirection: 'row',
|
|
2426
2551
|
gap: 12,
|
|
2427
2552
|
padding: 1,
|
|
2428
|
-
}, children: [_jsx(
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2553
|
+
}, children: [_jsx(TextInputComponent, { id: "ask_ai_input_bar", value: aiPrompt, width: askAIInputWidth, onChange: (e) => setAiPrompt(e.target.value), placeholder: baseAst ? 'Ask a follow-up question...' : 'Ask a question...' }), _jsx(ButtonComponent, { onClick: handleAsk, label: 'Ask AI' }), baseAst && (_jsx(SecondaryButtonComponent, { label: 'New report', onClick: clearAllState }))] })), baseAst && (_jsx(TableComponent, { isLoading: loading && errorMessage.length === 0, rows: applyFormatting({
|
|
2554
|
+
rows: pivotData?.rows || rows,
|
|
2555
|
+
fields: pivotData?.fields || fields,
|
|
2556
|
+
}, baseAst?.columns ?? []), columns: pivot
|
|
2557
|
+
? pivotData?.columns || emptyPivotColumns()
|
|
2558
|
+
: enforceOrderOnColumns(Object.keys(rows[0] ?? {})).map((c) => {
|
|
2559
|
+
return { label: snakeCaseToTitleCase(c), field: c };
|
|
2560
|
+
}) })), _jsxs("div", { style: {
|
|
2436
2561
|
display: 'flex',
|
|
2437
2562
|
flexDirection: 'row',
|
|
2438
2563
|
gap: '12px',
|
|
@@ -2441,7 +2566,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2441
2566
|
fontSize: 14,
|
|
2442
2567
|
padding: '12px',
|
|
2443
2568
|
whiteSpace: 'nowrap',
|
|
2444
|
-
}, children: errorMessage })), _jsx("div", { style: { width: '100%' } }), baseAst && (_jsxs(_Fragment, { children: [_jsx(
|
|
2569
|
+
}, children: errorMessage })), _jsx("div", { style: { width: '100%' } }), baseAst && (_jsxs(_Fragment, { children: [_jsx(SecondaryButtonComponent, { label: isCopying ? '✅ Copied' : 'Copy SQL', onClick: () => copyToClipboard(activeQuery) }), _jsx(ButtonComponent, { onClick: () => {
|
|
2445
2570
|
setIsChartBuilderOpen(true);
|
|
2446
|
-
}, label: 'Add to dashboard' })] }))] })] }), _jsx("style", { children: `body{margin:0;}` }), _jsx(ChartBuilderWithModal, { rows:
|
|
2571
|
+
}, label: 'Add to dashboard' })] }))] })] }), _jsx("style", { children: `body{margin:0;}` }), _jsx(ChartBuilderWithModal, { rows: rows, columns: processColumnsForChartBuilder(Object.keys(rows[0] ?? {})), fields: fields, pivot: pivot, query: activeQuery, showTableFormatOptions: isAdminEnabled, showDateFieldOptions: isAdminEnabled, showAccessControlOptions: isAdminEnabled, title: "Add to dashboard", isOpen: isChartBuilderOpen, setIsOpen: setIsChartBuilderOpen, onAddToDashboardComplete: onSubmitChartBuilder, destinationDashboard: destinationDashboard, organizationName: organizationName, pivotData: pivotData, SelectComponent: SelectComponent, TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, HeaderComponent: HeaderComponent, LabelComponent: LabelComponent, TextComponent: TextComponent, ModalComponent: ModalComponent, PopoverComponent: PopoverComponent, DeleteButtonComponent: DeleteButtonComponent })] }));
|
|
2447
2572
|
}
|