@quillsql/react 2.11.16 → 2.11.18
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 +109 -42
- package/dist/cjs/Chart.d.ts.map +1 -1
- package/dist/cjs/Chart.js +44 -18
- package/dist/cjs/ChartBuilder.d.ts +204 -30
- package/dist/cjs/ChartBuilder.d.ts.map +1 -1
- package/dist/cjs/ChartBuilder.js +124 -63
- package/dist/cjs/ChartEditor.d.ts +123 -19
- package/dist/cjs/ChartEditor.d.ts.map +1 -1
- package/dist/cjs/ChartEditor.js +47 -15
- package/dist/cjs/Dashboard.d.ts +148 -91
- package/dist/cjs/Dashboard.d.ts.map +1 -1
- package/dist/cjs/Dashboard.js +51 -159
- 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 +194 -42
- package/dist/cjs/ReportBuilder.d.ts.map +1 -1
- package/dist/cjs/ReportBuilder.js +563 -416
- package/dist/cjs/SQLEditor.d.ts +160 -23
- package/dist/cjs/SQLEditor.d.ts.map +1 -1
- package/dist/cjs/SQLEditor.js +36 -30
- 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/QuillCard.d.ts +2 -7
- package/dist/cjs/components/QuillCard.d.ts.map +1 -1
- package/dist/cjs/components/QuillCard.js +15 -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 +9 -3
- package/dist/cjs/components/ReportBuilder/AddColumnPopover.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/AddColumnPopover.js +10 -6
- package/dist/cjs/components/ReportBuilder/AddLimitPopover.d.ts +13 -1
- package/dist/cjs/components/ReportBuilder/AddLimitPopover.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/AddLimitPopover.js +5 -15
- package/dist/cjs/components/ReportBuilder/AddSortPopover.d.ts +21 -1
- package/dist/cjs/components/ReportBuilder/AddSortPopover.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/AddSortPopover.js +15 -17
- package/dist/cjs/components/ReportBuilder/bigDateMap.js +1 -1
- package/dist/cjs/components/ReportBuilder/convert.d.ts +3 -1
- package/dist/cjs/components/ReportBuilder/convert.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/convert.js +60 -21
- package/dist/cjs/components/ReportBuilder/operators.d.ts +15 -10
- package/dist/cjs/components/ReportBuilder/operators.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/operators.js +23 -10
- 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 +82 -18
- package/dist/cjs/components/ReportBuilder/ui.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/ui.js +55 -103
- package/dist/cjs/components/ReportBuilder/util.d.ts +10 -4
- package/dist/cjs/components/ReportBuilder/util.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/util.js +124 -71
- package/dist/cjs/components/UiComponents.d.ts +81 -87
- package/dist/cjs/components/UiComponents.d.ts.map +1 -1
- package/dist/cjs/components/UiComponents.js +76 -103
- 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 +5 -2
- package/dist/cjs/internals/ReportBuilder/PivotList.d.ts.map +1 -1
- package/dist/cjs/internals/ReportBuilder/PivotList.js +21 -21
- package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts +30 -14
- package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
- package/dist/cjs/internals/ReportBuilder/PivotModal.js +77 -52
- package/dist/cjs/utils/dataFetcher.d.ts.map +1 -1
- package/dist/cjs/utils/dataFetcher.js +2 -0
- package/dist/cjs/utils/parserBigQuery.d.ts +6 -0
- package/dist/cjs/utils/parserBigQuery.d.ts.map +1 -0
- package/dist/cjs/utils/parserBigQuery.js +60 -0
- package/dist/cjs/utils/parserPostgres.d.ts +3 -0
- package/dist/cjs/utils/parserPostgres.d.ts.map +1 -0
- package/dist/cjs/utils/parserPostgres.js +42 -0
- package/dist/esm/Chart.d.ts +109 -42
- package/dist/esm/Chart.d.ts.map +1 -1
- package/dist/esm/Chart.js +45 -19
- package/dist/esm/ChartBuilder.d.ts +204 -30
- package/dist/esm/ChartBuilder.d.ts.map +1 -1
- package/dist/esm/ChartBuilder.js +124 -63
- package/dist/esm/ChartEditor.d.ts +123 -19
- package/dist/esm/ChartEditor.d.ts.map +1 -1
- package/dist/esm/ChartEditor.js +51 -19
- package/dist/esm/Dashboard.d.ts +148 -91
- package/dist/esm/Dashboard.d.ts.map +1 -1
- package/dist/esm/Dashboard.js +54 -160
- 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 +194 -42
- package/dist/esm/ReportBuilder.d.ts.map +1 -1
- package/dist/esm/ReportBuilder.js +566 -419
- package/dist/esm/SQLEditor.d.ts +160 -23
- package/dist/esm/SQLEditor.d.ts.map +1 -1
- package/dist/esm/SQLEditor.js +36 -30
- 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/QuillCard.d.ts +2 -7
- package/dist/esm/components/QuillCard.d.ts.map +1 -1
- package/dist/esm/components/QuillCard.js +15 -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 +9 -3
- package/dist/esm/components/ReportBuilder/AddColumnPopover.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/AddColumnPopover.js +10 -6
- package/dist/esm/components/ReportBuilder/AddLimitPopover.d.ts +13 -1
- package/dist/esm/components/ReportBuilder/AddLimitPopover.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/AddLimitPopover.js +5 -15
- package/dist/esm/components/ReportBuilder/AddSortPopover.d.ts +21 -1
- package/dist/esm/components/ReportBuilder/AddSortPopover.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/AddSortPopover.js +17 -19
- package/dist/esm/components/ReportBuilder/bigDateMap.js +1 -1
- package/dist/esm/components/ReportBuilder/convert.d.ts +3 -1
- package/dist/esm/components/ReportBuilder/convert.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/convert.js +51 -13
- package/dist/esm/components/ReportBuilder/operators.d.ts +15 -10
- package/dist/esm/components/ReportBuilder/operators.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/operators.js +23 -10
- 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 +82 -18
- package/dist/esm/components/ReportBuilder/ui.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/ui.js +53 -101
- package/dist/esm/components/ReportBuilder/util.d.ts +10 -4
- package/dist/esm/components/ReportBuilder/util.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/util.js +114 -67
- package/dist/esm/components/UiComponents.d.ts +81 -87
- package/dist/esm/components/UiComponents.d.ts.map +1 -1
- package/dist/esm/components/UiComponents.js +71 -102
- 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 +5 -2
- package/dist/esm/internals/ReportBuilder/PivotList.d.ts.map +1 -1
- package/dist/esm/internals/ReportBuilder/PivotList.js +21 -21
- package/dist/esm/internals/ReportBuilder/PivotModal.d.ts +30 -14
- package/dist/esm/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
- package/dist/esm/internals/ReportBuilder/PivotModal.js +77 -52
- package/dist/esm/utils/dataFetcher.d.ts.map +1 -1
- package/dist/esm/utils/dataFetcher.js +2 -0
- package/dist/esm/utils/parserBigQuery.d.ts +6 -0
- package/dist/esm/utils/parserBigQuery.d.ts.map +1 -0
- package/dist/esm/utils/parserBigQuery.js +52 -0
- package/dist/esm/utils/parserPostgres.d.ts +3 -0
- package/dist/esm/utils/parserPostgres.d.ts.map +1 -0
- package/dist/esm/utils/parserPostgres.js +37 -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, MemoizedDeleteButton, 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';
|
|
@@ -9,10 +10,10 @@ import { ClientContext, ThemeContext } from './Context';
|
|
|
9
10
|
import { getTableAliases, getTableNames, isDateishColumnType, isNumericColumnType, isTextColumnType, } from './components/ReportBuilder/ast';
|
|
10
11
|
import { ChartBuilderWithModal } from './ChartBuilder';
|
|
11
12
|
import { QuillTextInput } from './components/UiComponents';
|
|
12
|
-
import {
|
|
13
|
+
import { QuillSidebar, CustomContainer, QuillSelectColumn, QuillDraggableColumn, QuillSidebarHeading, QuillFilterPopover, QuillSortPopover, TagWrapper, EditPopover, AddFilterPopover, QuillLimitPopover, } from './components/ReportBuilder/ui';
|
|
13
14
|
import { generateCurrentPeriodPostgres, generateEqualsPostgres, generateLastNPeriodsPostgres, generatePreviousPeriodPostgres, } from './components/ReportBuilder/postgres';
|
|
14
15
|
import { convertBigQuery, convertGroupBy, convertRemoveSimpleParentheses, convertStringComparison, convertWildcardColumns, } from './components/ReportBuilder/convert';
|
|
15
|
-
import { deepCopy, formatDateComparisonNode, getDateFilterInfo,
|
|
16
|
+
import { deepCopy, formatDateComparisonNode, getDateFilterInfo, getPostgresBasicType, isColumnComparison, isDateTruncEquals, isInTheLastInterval, isNodeEmptyCollection, isTheCurrentInterval, isThePreviousInterval, isTopLevelBoolean, showNodeAsRow, tryConvertDateEquality, removeNonSelectedTableReferences, getCustomSentence, isEquals, } from './components/ReportBuilder/util';
|
|
16
17
|
import { getDefaultOperatorSubtrees, OPERATOR_GROUPS, } from './components/ReportBuilder/operators';
|
|
17
18
|
import { hashCode } from './utils/crypto';
|
|
18
19
|
import { DATE_FMT, DAY_OF_WEEK, defaultAST, defaultColumn, defaultEntry, defaultNumericComparison, defaultTable, defaultVariant, MONTH_OF_YEAR, } from './components/ReportBuilder/constants';
|
|
@@ -20,11 +21,11 @@ import AddColumnPopover from './components/ReportBuilder/AddColumnPopover';
|
|
|
20
21
|
import { AddSortPopover, SortSentence, } from './components/ReportBuilder/AddSortPopover';
|
|
21
22
|
import { PivotModal, generatePivotTable, } from './internals/ReportBuilder/PivotModal';
|
|
22
23
|
import { PivotCard } from './internals/ReportBuilder/PivotList';
|
|
23
|
-
import QuillTable from './components/QuillTable';
|
|
24
|
-
import { QuillSelectComponent } from './components/QuillSelect';
|
|
25
24
|
import { snakeCaseToTitleCase } from './utils/textProcessing';
|
|
26
25
|
import { AddLimitPopover, LimitSentence, } from './components/ReportBuilder/AddLimitPopover';
|
|
27
26
|
import { updateFirstChildWidth } from './utils/width';
|
|
27
|
+
import { QuillSelectComponent } from './components/QuillSelect';
|
|
28
|
+
import { QuillCard } from './components/QuillCard';
|
|
28
29
|
/**
|
|
29
30
|
* Quill Report Builder
|
|
30
31
|
*
|
|
@@ -32,14 +33,38 @@ import { updateFirstChildWidth } from './utils/width';
|
|
|
32
33
|
* then edit them on the fly. Once users have constructed a query they like,
|
|
33
34
|
* they can click a button and add that report to their dashboard or export it
|
|
34
35
|
* as a CSV.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```js
|
|
39
|
+
* // Usage without custom components
|
|
40
|
+
* <ReportBuilder />
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```js
|
|
45
|
+
* // You can also pass your own components
|
|
46
|
+
* <ReportBuilder
|
|
47
|
+
* initialTableName="transactions"
|
|
48
|
+
* TableComponent={MyTable}
|
|
49
|
+
* SelectComponent={MySelect}
|
|
50
|
+
* ButtonComponent={MyButton}
|
|
51
|
+
* PopoverComponent={MyPopover}
|
|
52
|
+
* TextInputComponent={MyTextInput}
|
|
53
|
+
* containerStyle={{ backgroundColor: 'white', padding: '10px' }}
|
|
54
|
+
* />
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* ### Report Builder API
|
|
58
|
+
* @see https://docs.quillsql.com/components/report-builder
|
|
35
59
|
*/
|
|
36
|
-
export default function ReportBuilder({ initialTableName = '',
|
|
60
|
+
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, CardComponent = QuillCard, LabelComponent = MemoizedLabel, HeaderComponent = MemoizedHeader, TextComponent = MemoizedText, isAdminEnabled = false, isAIEnabled = true, containerStyle, }) {
|
|
37
61
|
const [aiPrompt, setAiPrompt] = useState('');
|
|
38
62
|
const [errorMessage, setErrorMessage] = useState('');
|
|
39
63
|
const [baseAst, setBaseAst] = useState(null);
|
|
40
64
|
const [formData, setFormData] = useState(null);
|
|
41
65
|
const [orderedColumnNames, setOrderedColumnNames] = useState([]);
|
|
42
66
|
const [selectedColumns, setSelectedColumns] = useState([]);
|
|
67
|
+
const [selectedOrderedColumns, setSelectedOrderedColumns] = useState([]);
|
|
43
68
|
const [schemaTables, setSchemaTables] = useState([]);
|
|
44
69
|
const [activeQuery, setActiveQuery] = useState('');
|
|
45
70
|
const [activeEditItem, setActiveEditItem] = useState(null);
|
|
@@ -99,7 +124,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
99
124
|
.sort(sortFn)
|
|
100
125
|
.filter((c) => columnsInPivot.includes(c));
|
|
101
126
|
}
|
|
102
|
-
|
|
127
|
+
// make the columnNames match the order of the selectedOrderedColumns
|
|
128
|
+
return columnNames.sort((a, b) => selectedOrderedColumns.indexOf(a) - selectedOrderedColumns.indexOf(b));
|
|
129
|
+
// return columnNames;
|
|
103
130
|
};
|
|
104
131
|
/**
|
|
105
132
|
* Transforms an array of column names into an array of columnInfo objects
|
|
@@ -125,9 +152,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
125
152
|
setAiPrompt('');
|
|
126
153
|
setBaseAst(null);
|
|
127
154
|
setFormData(null);
|
|
128
|
-
setOrderedColumnNames([]);
|
|
129
155
|
setSelectedColumns([]);
|
|
130
156
|
setSchemaTables([]);
|
|
157
|
+
setOrderedColumnNames([]);
|
|
131
158
|
setActiveQuery('');
|
|
132
159
|
setActiveEditItem(null);
|
|
133
160
|
setActivePath(null);
|
|
@@ -138,6 +165,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
138
165
|
setFields([]);
|
|
139
166
|
setTopLevelBinaryOperator('AND');
|
|
140
167
|
setEditPopoverKey(null);
|
|
168
|
+
setErrorMessage('');
|
|
141
169
|
// setUniqueValues({});
|
|
142
170
|
setPivot(null);
|
|
143
171
|
setPivotData(null);
|
|
@@ -202,23 +230,28 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
202
230
|
}
|
|
203
231
|
setUniqueValues(newValues);
|
|
204
232
|
};
|
|
205
|
-
const fetchSqlQuery = async (ast, formData) => {
|
|
206
|
-
|
|
233
|
+
const fetchSqlQuery = async (ast, formData, fetchData = true) => {
|
|
234
|
+
if (fetchData) {
|
|
235
|
+
setLoading(true);
|
|
236
|
+
}
|
|
207
237
|
setErrorMessage('');
|
|
208
238
|
try {
|
|
239
|
+
const where = formData ? formData : ast?.where || null;
|
|
209
240
|
const response = await fetch(`https://quill-344421.uc.r.appspot.com/sqlify`, {
|
|
210
241
|
method: 'POST',
|
|
211
242
|
headers: {
|
|
212
243
|
'Content-Type': 'application/json',
|
|
213
244
|
},
|
|
214
245
|
body: JSON.stringify({
|
|
215
|
-
ast: { ...ast, where
|
|
246
|
+
ast: { ...ast, where },
|
|
216
247
|
publicKey: client.publicKey,
|
|
217
248
|
}),
|
|
218
249
|
});
|
|
219
250
|
const data = await response.json();
|
|
220
251
|
setActiveQuery(data.query);
|
|
221
|
-
|
|
252
|
+
if (fetchData) {
|
|
253
|
+
fetchUponChange(ast, formData);
|
|
254
|
+
}
|
|
222
255
|
}
|
|
223
256
|
catch (error) {
|
|
224
257
|
setLoading(false);
|
|
@@ -237,7 +270,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
237
270
|
const result = [];
|
|
238
271
|
const table = tables[0];
|
|
239
272
|
const { valueField, rowField, columnField } = pivot;
|
|
240
|
-
if (columnField &&
|
|
273
|
+
if (columnField &&
|
|
274
|
+
uniqueValues[table] &&
|
|
275
|
+
uniqueValues[table][columnField]) {
|
|
241
276
|
result.push(...Object.keys(uniqueValues[table][columnField]));
|
|
242
277
|
}
|
|
243
278
|
result.push(valueField, rowField);
|
|
@@ -275,6 +310,32 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
275
310
|
}
|
|
276
311
|
};
|
|
277
312
|
useEffect(() => {
|
|
313
|
+
const loadTable = async (tables) => {
|
|
314
|
+
if (!tables)
|
|
315
|
+
return;
|
|
316
|
+
setLoading(true);
|
|
317
|
+
await getDistinctValues(initialTableName, tables);
|
|
318
|
+
const columnsForTable = tables
|
|
319
|
+
.find((t) => t.name === initialTableName)
|
|
320
|
+
?.columns.map((c) => c.name)
|
|
321
|
+
.sort((a, b) => {
|
|
322
|
+
const aIsId = a.endsWith('.id') ||
|
|
323
|
+
a.endsWith('_id') ||
|
|
324
|
+
a.endsWith('Id') ||
|
|
325
|
+
a === 'id';
|
|
326
|
+
const bIsId = b.endsWith('.id') ||
|
|
327
|
+
b.endsWith('_id') ||
|
|
328
|
+
b.endsWith('Id') ||
|
|
329
|
+
b === 'id';
|
|
330
|
+
if (aIsId && !bIsId)
|
|
331
|
+
return 1;
|
|
332
|
+
if (bIsId && !aIsId)
|
|
333
|
+
return -1;
|
|
334
|
+
return 0;
|
|
335
|
+
});
|
|
336
|
+
await handleAsk(`get ${columnsForTable} from ${initialTableName}`);
|
|
337
|
+
setInitialLoad(false);
|
|
338
|
+
};
|
|
278
339
|
const fetchSchema = async () => {
|
|
279
340
|
try {
|
|
280
341
|
setLoadingSchema(true);
|
|
@@ -300,8 +361,14 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
300
361
|
setOrderedColumnNames((tables ?? []).flatMap((table) => table.columns
|
|
301
362
|
.map((c) => `${table.name}.${c.name}`)
|
|
302
363
|
.sort((a, b) => {
|
|
303
|
-
const aIsId = a.endsWith('.id') ||
|
|
304
|
-
|
|
364
|
+
const aIsId = a.endsWith('.id') ||
|
|
365
|
+
a.endsWith('_id') ||
|
|
366
|
+
a.endsWith('Id') ||
|
|
367
|
+
a === 'id';
|
|
368
|
+
const bIsId = b.endsWith('.id') ||
|
|
369
|
+
b.endsWith('_id') ||
|
|
370
|
+
b.endsWith('Id') ||
|
|
371
|
+
b === 'id';
|
|
305
372
|
if (aIsId && !bIsId)
|
|
306
373
|
return 1;
|
|
307
374
|
if (bIsId && !aIsId)
|
|
@@ -309,13 +376,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
309
376
|
return 0;
|
|
310
377
|
})));
|
|
311
378
|
if (initialTableName && initialLoad) {
|
|
312
|
-
|
|
313
|
-
setLoading(true);
|
|
314
|
-
await getDistinctValues(initialTableName, tables);
|
|
315
|
-
const columnsForTable = tables
|
|
316
|
-
.find((t) => t.name === initialTableName)
|
|
317
|
-
?.columns.map((c) => c.name);
|
|
318
|
-
await handleAsk(`get ${columnsForTable} from ${initialTableName}`);
|
|
379
|
+
await loadTable(tables);
|
|
319
380
|
}
|
|
320
381
|
setLoadingSchema(false);
|
|
321
382
|
}
|
|
@@ -325,8 +386,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
325
386
|
};
|
|
326
387
|
if (schemaTables.length === 0) {
|
|
327
388
|
fetchSchema();
|
|
389
|
+
setInitialLoad(false);
|
|
328
390
|
}
|
|
329
|
-
}, [schemaTables]);
|
|
391
|
+
}, [schemaTables, initialTableName]);
|
|
330
392
|
const updateFormData = (updates, { isDeletion = false, isInsertion = false, isReplaceSubtree = false, isAddVariant = false, isDeleteVariant = false, topLevelBinOp = 'OR', isCondition = undefined, }) => {
|
|
331
393
|
// Function to immutably update or delete nodes based on their path
|
|
332
394
|
// TODO: fix the following horible code
|
|
@@ -733,7 +795,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
733
795
|
// see onChange callback handleChange
|
|
734
796
|
// eslint-disable-next-line no-unused-vars
|
|
735
797
|
dateColumnPath, dateFilterType, intervalCount, intervalType, intervalPaths, } = getDateFilterInfo(node);
|
|
736
|
-
const isPlural = intervalCount !== 1
|
|
798
|
+
const isPlural = intervalCount !== 1 && dateFilterType !== 'in the current'
|
|
799
|
+
? 's'
|
|
800
|
+
: '';
|
|
737
801
|
// Pull off the string literal date for "equals" comparisons
|
|
738
802
|
const rawDateStringEquals = node.right?.value ??
|
|
739
803
|
node.right?.args?.value[1]?.column ??
|
|
@@ -743,50 +807,50 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
743
807
|
'node.right.args.value.1.column') ??
|
|
744
808
|
(node.right?.args?.value[1]?.value &&
|
|
745
809
|
'node.right.args.value.1.value');
|
|
746
|
-
return (_jsxs("div", { style: { display: 'flex', gap: 20 }, children: [_jsx(
|
|
747
|
-
const columnType = getColumnTypeByName(value);
|
|
810
|
+
return (_jsxs("div", { style: { display: 'flex', gap: 20 }, children: [_jsx(SelectComponent, { value: dateColumn, onChange: (event) => {
|
|
811
|
+
const columnType = getColumnTypeByName(event.target.value);
|
|
748
812
|
if (isDateishColumnType(columnType)) {
|
|
749
813
|
// handleChange(value, keyPrefix + dateColumnPath, "text");
|
|
750
|
-
handleOperatorChange('IN_THE_LAST', node, keyPrefix, value);
|
|
814
|
+
handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
|
|
751
815
|
}
|
|
752
816
|
else if (isNumericColumnType(columnType)) {
|
|
753
817
|
const newSubtree = deepCopy(defaultNumericComparison);
|
|
754
|
-
newSubtree.left.column = value;
|
|
818
|
+
newSubtree.left.column = event.target.value;
|
|
755
819
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
756
820
|
}
|
|
757
821
|
else {
|
|
758
822
|
const newSubtree = deepCopy(defaultEntry);
|
|
759
|
-
newSubtree.left.args.value[0].column = value;
|
|
823
|
+
newSubtree.left.args.value[0].column = event.target.value;
|
|
760
824
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
761
825
|
}
|
|
762
826
|
}, options: getAllPossibleColumns().map((column) => ({
|
|
763
827
|
label: snakeCaseToTitleCase(column.displayName),
|
|
764
828
|
value: column.name,
|
|
765
|
-
})) }), _jsx(
|
|
766
|
-
if (value === dateFilterType)
|
|
829
|
+
})) }), _jsx(SelectComponent, { value: dateFilterType, onChange: (event) => {
|
|
830
|
+
if (event.target.value === dateFilterType)
|
|
767
831
|
return null;
|
|
768
832
|
let newSubtree = {};
|
|
769
833
|
// TODO: implement one for each database type (eg. pg, snowflake, etc.)
|
|
770
|
-
if (value === 'in the last') {
|
|
834
|
+
if (event.target.value === 'in the last') {
|
|
771
835
|
newSubtree = generateLastNPeriodsPostgres({
|
|
772
836
|
dateField: dateColumn,
|
|
773
837
|
intervalPeriod: `${intervalCount ?? 1} ${intervalType}`,
|
|
774
838
|
});
|
|
775
839
|
}
|
|
776
|
-
else if (value === 'in the previous') {
|
|
840
|
+
else if (event.target.value === 'in the previous') {
|
|
777
841
|
newSubtree = generatePreviousPeriodPostgres({
|
|
778
842
|
dateField: dateColumn,
|
|
779
843
|
intervalPeriod: `${intervalCount ?? 1} ${intervalType}`,
|
|
780
844
|
currentPeriod: intervalType,
|
|
781
845
|
});
|
|
782
846
|
}
|
|
783
|
-
else if (value === 'in the current') {
|
|
847
|
+
else if (event.target.value === 'in the current') {
|
|
784
848
|
newSubtree = generateCurrentPeriodPostgres({
|
|
785
849
|
dateField: dateColumn,
|
|
786
850
|
currentPeriod: intervalType,
|
|
787
851
|
});
|
|
788
852
|
}
|
|
789
|
-
else if (value === 'equals') {
|
|
853
|
+
else if (event.target.value === 'equals') {
|
|
790
854
|
newSubtree = generateEqualsPostgres({
|
|
791
855
|
dateField: dateColumn,
|
|
792
856
|
currentPeriod: intervalType,
|
|
@@ -800,7 +864,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
800
864
|
{ label: 'in the previous', value: 'in the previous' },
|
|
801
865
|
{ label: 'in the current', value: 'in the current' },
|
|
802
866
|
{ label: 'equals', value: 'equals' },
|
|
803
|
-
] }), !['in the current', 'equals'].includes(dateFilterType) && (_jsx(
|
|
867
|
+
] }), !['in the current', 'equals'].includes(dateFilterType) && (_jsx(TextInputComponent, { id: "date_filter_interval_count", value: intervalCount?.toString() ?? '', width: 70, onChange: (e) => {
|
|
804
868
|
if (Number.isNaN(parseFloat(e.target.value || '0'))) {
|
|
805
869
|
alert('Please input a number.');
|
|
806
870
|
return;
|
|
@@ -812,13 +876,13 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
812
876
|
path: keyPrefix + intervalPath,
|
|
813
877
|
},
|
|
814
878
|
]));
|
|
815
|
-
} })), _jsx(
|
|
879
|
+
} })), _jsx(SelectComponent, { value: intervalType, onChange: (event) => {
|
|
816
880
|
if (intervalPaths.length === 1) {
|
|
817
881
|
handleChangeText([
|
|
818
882
|
{
|
|
819
883
|
value: intervalCount !== null
|
|
820
|
-
? `${intervalCount} ${value}${isPlural}`
|
|
821
|
-
: value,
|
|
884
|
+
? `${intervalCount} ${event.target.value}${isPlural}`
|
|
885
|
+
: event.target.value,
|
|
822
886
|
path: keyPrefix + intervalPaths[0],
|
|
823
887
|
},
|
|
824
888
|
]);
|
|
@@ -828,14 +892,14 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
828
892
|
if (dateFilterType === 'equals') {
|
|
829
893
|
newSubtree = generateEqualsPostgres({
|
|
830
894
|
dateField: dateColumn,
|
|
831
|
-
currentPeriod: value,
|
|
895
|
+
currentPeriod: event.target.value,
|
|
832
896
|
timestamp: rawDateStringEquals,
|
|
833
897
|
});
|
|
834
898
|
}
|
|
835
899
|
else {
|
|
836
900
|
newSubtree = generateCurrentPeriodPostgres({
|
|
837
901
|
dateField: dateColumn,
|
|
838
|
-
currentPeriod: value,
|
|
902
|
+
currentPeriod: event.target.value,
|
|
839
903
|
});
|
|
840
904
|
}
|
|
841
905
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
@@ -846,7 +910,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
846
910
|
{ label: `week${isPlural}`, value: 'week' },
|
|
847
911
|
{ label: `day${isPlural}`, value: 'day' },
|
|
848
912
|
{ label: `hour${isPlural}`, value: 'hour' },
|
|
849
|
-
] }), dateFilterType === 'equals' && (_jsx(
|
|
913
|
+
] }), dateFilterType === 'equals' && (_jsx(TextInputComponent, { id: "date_filter_equals_raw_date", value: rawDateStringEquals, width: 120, onChange: (e) => {
|
|
850
914
|
handleChangeText([
|
|
851
915
|
{
|
|
852
916
|
value: e.target.value,
|
|
@@ -867,40 +931,44 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
867
931
|
flexDirection: 'row',
|
|
868
932
|
alignItems: 'center',
|
|
869
933
|
gap: 20,
|
|
870
|
-
}, children: [_jsx(
|
|
871
|
-
const columnType = getColumnTypeByName(value);
|
|
934
|
+
}, children: [_jsx(SelectComponent, { value: node.left.column, onChange: (event) => {
|
|
935
|
+
const columnType = getColumnTypeByName(event.target.value);
|
|
872
936
|
if (isDateishColumnType(columnType)) {
|
|
873
937
|
// handleChange(value, keyPrefix + dateColumnPath, "text");
|
|
874
|
-
handleOperatorChange('IN_THE_LAST', node, keyPrefix, value);
|
|
938
|
+
handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
|
|
875
939
|
}
|
|
876
940
|
else if (isNumericColumnType(columnType)) {
|
|
877
941
|
const newSubtree = deepCopy(defaultNumericComparison);
|
|
878
|
-
newSubtree.left.column = value;
|
|
942
|
+
newSubtree.left.column = event.target.value;
|
|
879
943
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
880
944
|
}
|
|
881
945
|
else {
|
|
882
946
|
const newSubtree = deepCopy(defaultEntry);
|
|
883
|
-
newSubtree.left.args.value[0].column = value;
|
|
947
|
+
newSubtree.left.args.value[0].column = event.target.value;
|
|
884
948
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
885
949
|
}
|
|
886
|
-
}, options: options }), _jsx(
|
|
887
|
-
handleOperatorChange(value, node, keyPrefix, dateColumn);
|
|
950
|
+
}, options: options }), _jsx(SelectComponent, { value: 'IN_THE_LAST', onChange: (event) => {
|
|
951
|
+
handleOperatorChange(event.target.value, node, keyPrefix, dateColumn);
|
|
888
952
|
}, options: [
|
|
889
953
|
{ label: 'in the last', value: 'IN_THE_LAST' },
|
|
890
954
|
{ label: 'in the previous', value: 'IN_THE_PREVIOUS' },
|
|
891
955
|
{ label: 'in the current', value: 'IN_THE_CURRENT' },
|
|
956
|
+
{ label: 'equals', value: 'EQUALS' },
|
|
892
957
|
{ label: 'is not null', value: 'IS NOT' },
|
|
893
958
|
{ label: 'is null', value: 'IS' },
|
|
894
959
|
// { label: 'equals', value: 'equals' },
|
|
895
|
-
] }), _jsx(
|
|
960
|
+
] }), _jsx(TextInputComponent, { id: 'date_window_interval_count', value: node.right.args.value[1].expr.value, width: 120, onChange: (e) => {
|
|
896
961
|
handleChange([
|
|
897
962
|
{
|
|
898
963
|
value: e.target.value,
|
|
899
964
|
path: keyPrefix + 'right.args.value||1.expr.value',
|
|
900
965
|
},
|
|
901
966
|
]);
|
|
902
|
-
} }), _jsx("div", { children: _jsx(
|
|
903
|
-
{
|
|
967
|
+
} }), _jsx("div", { children: _jsx(SelectComponent, { value: node.right.args.value[1].unit, onChange: (event) => handleChange([
|
|
968
|
+
{
|
|
969
|
+
value: event.target.value,
|
|
970
|
+
path: keyPrefix + 'right.args.value||1.unit',
|
|
971
|
+
},
|
|
904
972
|
]), options: [
|
|
905
973
|
{ label: `year${plural}`, value: '* 365 DAY' },
|
|
906
974
|
{ label: `month${plural}`, value: '* 30 DAY' },
|
|
@@ -919,35 +987,42 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
919
987
|
flexDirection: 'row',
|
|
920
988
|
alignItems: 'center',
|
|
921
989
|
gap: 20,
|
|
922
|
-
}, children: [_jsx(
|
|
923
|
-
const columnType = getColumnTypeByName(value);
|
|
990
|
+
}, children: [_jsx(SelectComponent, { value: node.left.column, onChange: (event) => {
|
|
991
|
+
const columnType = getColumnTypeByName(event.target.value);
|
|
924
992
|
if (isDateishColumnType(columnType)) {
|
|
925
993
|
// handleChange(value, keyPrefix + dateColumnPath, "text");
|
|
926
|
-
handleOperatorChange('IN_THE_LAST', node, keyPrefix, value);
|
|
994
|
+
handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
|
|
927
995
|
}
|
|
928
996
|
else if (isNumericColumnType(columnType)) {
|
|
929
997
|
const newSubtree = deepCopy(defaultNumericComparison);
|
|
930
|
-
newSubtree.left.column = value;
|
|
998
|
+
newSubtree.left.column = event.target.value;
|
|
931
999
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
932
1000
|
}
|
|
933
1001
|
else {
|
|
934
1002
|
const newSubtree = deepCopy(defaultEntry);
|
|
935
|
-
newSubtree.left.args.value[0].column = value;
|
|
1003
|
+
newSubtree.left.args.value[0].column = event.target.value;
|
|
936
1004
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
937
1005
|
}
|
|
938
|
-
}, options: options }), _jsx(
|
|
939
|
-
handleOperatorChange(value, node, keyPrefix, node.left.column);
|
|
1006
|
+
}, options: options }), _jsx(SelectComponent, { value: 'IN_THE_CURRENT', onChange: (event) => {
|
|
1007
|
+
handleOperatorChange(event.target.value, node, keyPrefix, node.left.column);
|
|
940
1008
|
}, options: [
|
|
941
1009
|
{ label: 'in the last', value: 'IN_THE_LAST' },
|
|
942
1010
|
{ label: 'in the previous', value: 'IN_THE_PREVIOUS' },
|
|
943
1011
|
{ label: 'in the current', value: 'IN_THE_CURRENT' },
|
|
1012
|
+
{ label: 'equals', value: 'EQUALS' },
|
|
944
1013
|
{ label: 'is not null', value: 'IS NOT' },
|
|
945
1014
|
{ label: 'is null', value: 'IS' },
|
|
946
1015
|
// { label: 'equals', value: 'equals' },
|
|
947
|
-
] }), _jsx(
|
|
1016
|
+
] }), _jsx(SelectComponent, { value: node.left.args.value[1].column, onChange: (event) => {
|
|
948
1017
|
handleChange([
|
|
949
|
-
{
|
|
950
|
-
|
|
1018
|
+
{
|
|
1019
|
+
value: event.target.value,
|
|
1020
|
+
path: 'right.args.value||1.column',
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
value: event.target.value,
|
|
1024
|
+
path: 'left.args.value||1.column',
|
|
1025
|
+
},
|
|
951
1026
|
]);
|
|
952
1027
|
}, options: [
|
|
953
1028
|
{ label: `year`, value: 'YEAR' },
|
|
@@ -966,32 +1041,33 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
966
1041
|
flexDirection: 'row',
|
|
967
1042
|
alignItems: 'center',
|
|
968
1043
|
gap: 20,
|
|
969
|
-
}, children: [_jsx(
|
|
970
|
-
const columnType = getColumnTypeByName(value);
|
|
1044
|
+
}, children: [_jsx(SelectComponent, { value: node.left.column, onChange: (event) => {
|
|
1045
|
+
const columnType = getColumnTypeByName(event.target.value);
|
|
971
1046
|
if (isDateishColumnType(columnType)) {
|
|
972
1047
|
// handleChange(value, keyPrefix + dateColumnPath, "text");
|
|
973
|
-
handleOperatorChange('IN_THE_LAST', node, keyPrefix, value);
|
|
1048
|
+
handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
|
|
974
1049
|
}
|
|
975
1050
|
else if (isNumericColumnType(columnType)) {
|
|
976
1051
|
const newSubtree = deepCopy(defaultNumericComparison);
|
|
977
|
-
newSubtree.left.column = value;
|
|
1052
|
+
newSubtree.left.column = event.target.value;
|
|
978
1053
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
979
1054
|
}
|
|
980
1055
|
else {
|
|
981
1056
|
const newSubtree = deepCopy(defaultEntry);
|
|
982
|
-
newSubtree.left.args.value[0].column = value;
|
|
1057
|
+
newSubtree.left.args.value[0].column = event.target.value;
|
|
983
1058
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
984
1059
|
}
|
|
985
|
-
}, options: options }), _jsx(
|
|
986
|
-
handleOperatorChange(value, node, keyPrefix, node.left.column);
|
|
1060
|
+
}, options: options }), _jsx(SelectComponent, { value: 'IN_THE_PREVIOUS', onChange: (event) => {
|
|
1061
|
+
handleOperatorChange(event.target.value, node, keyPrefix, node.left.column);
|
|
987
1062
|
}, options: [
|
|
988
1063
|
{ label: 'in the last', value: 'IN_THE_LAST' },
|
|
989
1064
|
{ label: 'in the previous', value: 'IN_THE_PREVIOUS' },
|
|
990
1065
|
{ label: 'in the current', value: 'IN_THE_CURRENT' },
|
|
1066
|
+
{ label: 'equals', value: 'EQUALS' },
|
|
991
1067
|
{ label: 'is not null', value: 'IS NOT' },
|
|
992
1068
|
{ label: 'is null', value: 'IS' },
|
|
993
1069
|
// { label: 'equals', value: 'equals' },
|
|
994
|
-
] }), _jsx(
|
|
1070
|
+
] }), _jsx(SelectComponent, { value: node.left.args.value[1].column, onChange: (event) => {
|
|
995
1071
|
const dayConversion = {
|
|
996
1072
|
YEAR: 365,
|
|
997
1073
|
QUARTER: 90,
|
|
@@ -1000,15 +1076,15 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1000
1076
|
};
|
|
1001
1077
|
handleChange([
|
|
1002
1078
|
{
|
|
1003
|
-
value,
|
|
1079
|
+
value: event.target.value,
|
|
1004
1080
|
path: 'left.args.value||1.column',
|
|
1005
1081
|
},
|
|
1006
1082
|
{
|
|
1007
|
-
value,
|
|
1083
|
+
value: event.target.value,
|
|
1008
1084
|
path: 'right.args.value||1.column',
|
|
1009
1085
|
},
|
|
1010
1086
|
{
|
|
1011
|
-
value: dayConversion[value] || 30,
|
|
1087
|
+
value: dayConversion[event.target.value] || 30,
|
|
1012
1088
|
path: 'right.args.value||0.args.value||1.expr.value',
|
|
1013
1089
|
},
|
|
1014
1090
|
]);
|
|
@@ -1019,6 +1095,65 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1019
1095
|
{ label: `week`, value: 'WEEK' },
|
|
1020
1096
|
] })] }));
|
|
1021
1097
|
}
|
|
1098
|
+
else if (isEquals(node, client.databaseType)) {
|
|
1099
|
+
const options = getAllPossibleColumns().map((column) => ({
|
|
1100
|
+
label: snakeCaseToTitleCase(column.displayName),
|
|
1101
|
+
value: column.name,
|
|
1102
|
+
}));
|
|
1103
|
+
return (_jsxs("div", { style: {
|
|
1104
|
+
display: 'flex',
|
|
1105
|
+
flexDirection: 'row',
|
|
1106
|
+
alignItems: 'center',
|
|
1107
|
+
gap: 20,
|
|
1108
|
+
}, children: [_jsx(SelectComponent, { value: node.left.column, onChange: (event) => {
|
|
1109
|
+
const columnType = getColumnTypeByName(event.target.value);
|
|
1110
|
+
if (isDateishColumnType(columnType)) {
|
|
1111
|
+
// handleChange(value, keyPrefix + dateColumnPath, "text");
|
|
1112
|
+
handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
|
|
1113
|
+
}
|
|
1114
|
+
else if (isNumericColumnType(columnType)) {
|
|
1115
|
+
const newSubtree = deepCopy(defaultNumericComparison);
|
|
1116
|
+
newSubtree.left.column = event.target.value;
|
|
1117
|
+
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
1118
|
+
}
|
|
1119
|
+
else {
|
|
1120
|
+
const newSubtree = deepCopy(defaultEntry);
|
|
1121
|
+
newSubtree.left.args.value[0].column = event.target.value;
|
|
1122
|
+
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
1123
|
+
}
|
|
1124
|
+
}, options: options }), _jsx(SelectComponent, { value: 'EQUALS', onChange: (event) => {
|
|
1125
|
+
handleOperatorChange(event.target.value, node, keyPrefix, node.left.column);
|
|
1126
|
+
}, options: [
|
|
1127
|
+
{ label: 'in the last', value: 'IN_THE_LAST' },
|
|
1128
|
+
{ label: 'in the previous', value: 'IN_THE_PREVIOUS' },
|
|
1129
|
+
{ label: 'in the current', value: 'IN_THE_CURRENT' },
|
|
1130
|
+
{ label: 'equals', value: 'EQUALS' },
|
|
1131
|
+
{ label: 'is not null', value: 'IS NOT' },
|
|
1132
|
+
{ label: 'is null', value: 'IS' },
|
|
1133
|
+
// { label: 'equals', value: 'equals' },
|
|
1134
|
+
] }), _jsx(SelectComponent, { value: node.right.args.value[1].column, onChange: (event) => {
|
|
1135
|
+
handleChange([
|
|
1136
|
+
{
|
|
1137
|
+
value: event.target.value,
|
|
1138
|
+
path: 'right.args.value||1.column',
|
|
1139
|
+
},
|
|
1140
|
+
{
|
|
1141
|
+
value: event.target.value,
|
|
1142
|
+
path: 'left.args.value||1.column',
|
|
1143
|
+
},
|
|
1144
|
+
]);
|
|
1145
|
+
}, options: [
|
|
1146
|
+
{ label: `year`, value: 'YEAR' },
|
|
1147
|
+
{ label: `quarter`, value: 'QUARTER' },
|
|
1148
|
+
{ label: `month`, value: 'MONTH' },
|
|
1149
|
+
{ label: `week`, value: 'WEEK' },
|
|
1150
|
+
] }), _jsx(TextInputComponent, { id: 'quoted_string', value: node.right.args.value[0].value, width: 120, onChange: (e) => handleChange([
|
|
1151
|
+
{
|
|
1152
|
+
value: e.target.value,
|
|
1153
|
+
path: 'right.args.value||0.value',
|
|
1154
|
+
},
|
|
1155
|
+
]) })] }));
|
|
1156
|
+
}
|
|
1022
1157
|
else if (isColumnComparison(node)) {
|
|
1023
1158
|
const options = getAllPossibleColumns().map((column) => ({
|
|
1024
1159
|
label: snakeCaseToTitleCase(column.displayName),
|
|
@@ -1048,10 +1183,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1048
1183
|
: []),
|
|
1049
1184
|
...(isTextColumnType(columnType)
|
|
1050
1185
|
? [
|
|
1051
|
-
{ label: 'is', value: 'LIKE' },
|
|
1052
|
-
{ label: 'is not', value: 'NOT LIKE' },
|
|
1053
|
-
{ label: 'is
|
|
1054
|
-
{ label: 'is not
|
|
1186
|
+
{ label: 'is exactly', value: 'LIKE' },
|
|
1187
|
+
{ label: 'is not exactly', value: 'NOT LIKE' },
|
|
1188
|
+
{ label: 'is', value: 'IN' },
|
|
1189
|
+
{ label: 'is not', value: 'NOT IN' },
|
|
1055
1190
|
{ label: 'is not null', value: 'IS NOT' },
|
|
1056
1191
|
{ label: 'is null', value: 'IS' },
|
|
1057
1192
|
]
|
|
@@ -1070,10 +1205,6 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1070
1205
|
]
|
|
1071
1206
|
: []),
|
|
1072
1207
|
];
|
|
1073
|
-
if (client.databaseType === 'BigQuery' &&
|
|
1074
|
-
isDateishColumnType(columnType)) {
|
|
1075
|
-
operatorOptions = operatorOptions.filter((option) => option.value !== 'equals');
|
|
1076
|
-
}
|
|
1077
1208
|
return (_jsxs("div", { style: {
|
|
1078
1209
|
display: 'flex',
|
|
1079
1210
|
gap: 12,
|
|
@@ -1083,45 +1214,49 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1083
1214
|
}, children: [_jsxs("div", { style: {
|
|
1084
1215
|
display: 'flex',
|
|
1085
1216
|
gap: 20,
|
|
1086
|
-
// justifyContent: "space-between",
|
|
1087
1217
|
flexDirection: showNodeAsRow(node, formData)
|
|
1088
1218
|
? 'row'
|
|
1089
1219
|
: 'column',
|
|
1090
1220
|
width: '100%',
|
|
1091
|
-
}, children: [_jsx(
|
|
1092
|
-
const columnType = getColumnTypeByName(value);
|
|
1221
|
+
}, children: [_jsx(SelectComponent, { value: leftChildValue, onChange: (event) => {
|
|
1222
|
+
const columnType = getColumnTypeByName(event.target.value);
|
|
1093
1223
|
if (isDateishColumnType(columnType)) {
|
|
1094
|
-
handleOperatorChange('IN_THE_LAST', node, keyPrefix, value);
|
|
1224
|
+
handleOperatorChange('IN_THE_LAST', node, keyPrefix, event.target.value);
|
|
1095
1225
|
}
|
|
1096
1226
|
else if (isNumericColumnType(columnType)) {
|
|
1097
1227
|
const newSubtree = deepCopy(defaultNumericComparison);
|
|
1098
|
-
newSubtree.left.column = value;
|
|
1228
|
+
newSubtree.left.column = event.target.value;
|
|
1099
1229
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
1100
1230
|
}
|
|
1101
1231
|
else {
|
|
1102
1232
|
const newSubtree = deepCopy(defaultEntry);
|
|
1103
|
-
newSubtree.left.args.value[0].column = value;
|
|
1233
|
+
newSubtree.left.args.value[0].column = event.target.value;
|
|
1104
1234
|
handleReplaceSubtree(keyPrefix, newSubtree);
|
|
1105
1235
|
}
|
|
1106
|
-
}, options: options }), operatorOptions.length > 0 && (_jsx(
|
|
1107
|
-
handleOperatorChange(value, node, keyPrefix, leftChildValue);
|
|
1108
|
-
},
|
|
1236
|
+
}, options: options }), operatorOptions.length > 0 && (_jsx(SelectComponent, { value: node.operator, onChange: (event) => {
|
|
1237
|
+
handleOperatorChange(event.target.value, node, keyPrefix, leftChildValue);
|
|
1238
|
+
}, options: operatorOptions })), node.right &&
|
|
1109
1239
|
node.right.type !== 'expr_list' &&
|
|
1110
1240
|
renderNode(node.right, keyPrefix + 'right.')] }, keyPrefix), node.right && node.right.type === 'expr_list' && (_jsx("div", { style: {
|
|
1111
1241
|
display: 'grid',
|
|
1112
1242
|
gridTemplateColumns: 'repeat(2, 1fr)',
|
|
1113
1243
|
gap: 12,
|
|
1114
|
-
}, children:
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1244
|
+
}, children: uniqueValues[table] &&
|
|
1245
|
+
Object.keys(uniqueValues[table][leftChildValue] ?? {}).map((key) => (_jsxs("label", { style: { display: 'flex', gap: 4 }, children: [_jsx(CheckboxComponent, { isChecked: uniqueValues[table][leftChildValue][key], onChange: (event) => {
|
|
1246
|
+
const newValues = deepCopy(uniqueValues);
|
|
1247
|
+
newValues[table][leftChildValue][key] =
|
|
1248
|
+
event.target.checked;
|
|
1249
|
+
setUniqueValues(newValues);
|
|
1250
|
+
if (event.target.checked) {
|
|
1251
|
+
handleInsertVariant(keyPrefix + 'right.' + 'value', key);
|
|
1252
|
+
}
|
|
1253
|
+
else {
|
|
1254
|
+
handleDeleteVariant(keyPrefix + 'right.' + 'value', key);
|
|
1255
|
+
}
|
|
1256
|
+
} }), _jsx("span", { style: {
|
|
1257
|
+
fontFamily: theme.fontFamily,
|
|
1258
|
+
margin: 'auto 0',
|
|
1259
|
+
}, children: key })] }, key))) }, keyPrefix + 'right.'))] }));
|
|
1125
1260
|
}
|
|
1126
1261
|
else {
|
|
1127
1262
|
const columnName = node.left.column;
|
|
@@ -1133,9 +1268,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1133
1268
|
justifyContent: 'space-between',
|
|
1134
1269
|
flexDirection: showNodeAsRow(node, formData) ? 'row' : 'column',
|
|
1135
1270
|
width: '100%',
|
|
1136
|
-
}, children: [node.left && renderNode(node.left, keyPrefix + 'left.'), _jsx(
|
|
1137
|
-
handleOperatorChange(value, node, keyPrefix);
|
|
1138
|
-
},
|
|
1271
|
+
}, children: [node.left && renderNode(node.left, keyPrefix + 'left.'), _jsx(SelectComponent, { value: node.operator, onChange: (event) => {
|
|
1272
|
+
handleOperatorChange(event.target.value, node, keyPrefix);
|
|
1273
|
+
}, options: [
|
|
1139
1274
|
// { label: `and`, value: "AND" },
|
|
1140
1275
|
// { label: `or`, value: "OR" },
|
|
1141
1276
|
...(isNumericColumnType(columnType)
|
|
@@ -1152,10 +1287,10 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1152
1287
|
: []),
|
|
1153
1288
|
...(isTextColumnType(columnType)
|
|
1154
1289
|
? [
|
|
1155
|
-
{ label: 'is', value: 'LIKE' },
|
|
1156
|
-
{ label: 'is not', value: 'NOT LIKE' },
|
|
1157
|
-
{ label: 'is
|
|
1158
|
-
{ label: 'is not
|
|
1290
|
+
{ label: 'is exactly', value: 'LIKE' },
|
|
1291
|
+
{ label: 'is not exactly', value: 'NOT LIKE' },
|
|
1292
|
+
{ label: 'is', value: 'IN' },
|
|
1293
|
+
{ label: 'is not', value: 'NOT IN' },
|
|
1159
1294
|
{ label: 'is not null', value: 'IS NOT' },
|
|
1160
1295
|
{ label: 'is null', value: 'IS' },
|
|
1161
1296
|
]
|
|
@@ -1165,6 +1300,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1165
1300
|
{ label: 'in the last', value: 'IN_THE_LAST' },
|
|
1166
1301
|
{ label: 'in the previous', value: 'IN_THE_PREVIOUS' },
|
|
1167
1302
|
{ label: 'in the current', value: 'IN_THE_CURRENT' },
|
|
1303
|
+
{ label: 'equals', value: 'EQUALS' },
|
|
1168
1304
|
{ label: 'is not null', value: 'IS NOT' },
|
|
1169
1305
|
{ label: 'is null', value: 'IS' },
|
|
1170
1306
|
]
|
|
@@ -1178,15 +1314,17 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1178
1314
|
label: snakeCaseToTitleCase(column.displayName),
|
|
1179
1315
|
value: column.name,
|
|
1180
1316
|
}));
|
|
1181
|
-
return (_jsx(
|
|
1182
|
-
handleChange([
|
|
1317
|
+
return (_jsx(SelectComponent, { value: node.column ?? options[0]?.value, onChange: (event) => {
|
|
1318
|
+
handleChange([
|
|
1319
|
+
{ value: event.target.value, path: keyPrefix + 'column' },
|
|
1320
|
+
]);
|
|
1183
1321
|
}, options: options }));
|
|
1184
1322
|
}
|
|
1185
1323
|
case 'expr_list': {
|
|
1186
1324
|
const len = node.value.length;
|
|
1187
1325
|
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'row', gap: 12 }, children: [node.value.map((elem, index) => {
|
|
1188
1326
|
if (elem.value) {
|
|
1189
|
-
return (_jsx(
|
|
1327
|
+
return (_jsx(TextInputComponent, { id: `expr_list_${index}`, width: 200, value: elem.value, onChange: (e) => handleChange([
|
|
1190
1328
|
{
|
|
1191
1329
|
value: e.target.value,
|
|
1192
1330
|
path: keyPrefix + `value.${index}.`,
|
|
@@ -1194,11 +1332,11 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1194
1332
|
]) }, `input_${index}`));
|
|
1195
1333
|
}
|
|
1196
1334
|
return renderNode(elem, keyPrefix + `value.${index}.`);
|
|
1197
|
-
}), len > 1 && (_jsx(
|
|
1335
|
+
}), len > 1 && (_jsx(SecondaryButtonComponent, { label: '-', onClick: () => handleDeleteVariant(keyPrefix + 'value') })), _jsx(SecondaryButtonComponent, { onClick: () => handleInsertVariant(keyPrefix + 'value'), label: '+' })] }, keyPrefix));
|
|
1198
1336
|
}
|
|
1199
1337
|
case 'double_quote_string':
|
|
1200
1338
|
case 'single_quote_string':
|
|
1201
|
-
return (_jsx(
|
|
1339
|
+
return (_jsx(TextInputComponent, { id: 'quoted_string', value: node.value.replaceAll('%', ''), width: 120, onChange: (e) => handleChange([
|
|
1202
1340
|
{
|
|
1203
1341
|
value: e.target.value,
|
|
1204
1342
|
path: keyPrefix + 'value',
|
|
@@ -1207,7 +1345,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1207
1345
|
case 'null':
|
|
1208
1346
|
return _jsx("div", {});
|
|
1209
1347
|
case 'number':
|
|
1210
|
-
return (_jsx(
|
|
1348
|
+
return (_jsx(TextInputComponent, { id: "quill_number_input", value: node.value, width: 120, onChange: (e) => {
|
|
1211
1349
|
handleChange([
|
|
1212
1350
|
{
|
|
1213
1351
|
value: e.target.value,
|
|
@@ -1260,15 +1398,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1260
1398
|
// @depreciated TODO: remove next update
|
|
1261
1399
|
// eslint-disable-next-line no-unused-vars
|
|
1262
1400
|
isTopLevelAnd = false, isParentRow = false) => {
|
|
1263
|
-
const
|
|
1264
|
-
? getInTheCurrentIntervalSentence(node, client.databaseType)
|
|
1265
|
-
: null;
|
|
1266
|
-
const isInTheLastIntervalSentence = isInTheLastInterval(node, client.databaseType)
|
|
1267
|
-
? getInTheLastIntervalSentence(node, client.databaseType)
|
|
1268
|
-
: null;
|
|
1269
|
-
const isInThePreviousIntervalSentence = isThePreviousInterval(node, client.databaseType)
|
|
1270
|
-
? getInThePreviousIntervalSentence(node, client.databaseType)
|
|
1271
|
-
: null;
|
|
1401
|
+
const uniqueSentence = getCustomSentence(node, client.databaseType);
|
|
1272
1402
|
let dateComparisonPartialMatch = null;
|
|
1273
1403
|
let dateEqualityPartialMatch = null;
|
|
1274
1404
|
if (client.databaseType !== 'BigQuery') {
|
|
@@ -1280,13 +1410,13 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1280
1410
|
const OPS = {
|
|
1281
1411
|
AND: 'and',
|
|
1282
1412
|
OR: 'or',
|
|
1283
|
-
LIKE: 'is',
|
|
1413
|
+
LIKE: 'is exactly',
|
|
1284
1414
|
BETWEEN: 'is between',
|
|
1285
|
-
IN: 'is
|
|
1286
|
-
'NOT IN': 'is not
|
|
1287
|
-
'NOT LIKE': 'is not',
|
|
1288
|
-
'!=': 'is not',
|
|
1289
|
-
'=': 'is',
|
|
1415
|
+
IN: 'is',
|
|
1416
|
+
'NOT IN': 'is not',
|
|
1417
|
+
'NOT LIKE': 'is not exactly',
|
|
1418
|
+
'!=': 'is not exactly',
|
|
1419
|
+
'=': 'is exactly',
|
|
1290
1420
|
'<': 'is less than',
|
|
1291
1421
|
'>': 'is greater than',
|
|
1292
1422
|
'<=': 'is less than or equal to',
|
|
@@ -1294,25 +1424,14 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1294
1424
|
'<>': 'is not',
|
|
1295
1425
|
'-': 'minus',
|
|
1296
1426
|
'IS NOT': 'is not',
|
|
1297
|
-
IS: 'is
|
|
1427
|
+
IS: 'is',
|
|
1298
1428
|
};
|
|
1299
1429
|
switch (node.type) {
|
|
1300
1430
|
case 'binary_expr':
|
|
1301
|
-
return (_jsx(TagWrapper, { keyPrefix: keyPrefix, formData: formData, activeEditItem: activeEditItem, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setCheckboxes: setCheckboxes, handleReplaceSubtree: handleReplaceSubtree, FilterPopover:
|
|
1302
|
-
display: 'flex',
|
|
1303
|
-
gap: 3,
|
|
1304
|
-
flexDirection: isRow ? 'row' : 'column',
|
|
1305
|
-
padding: '1px',
|
|
1306
|
-
border: isCard ? '1px solid black' : 'none',
|
|
1307
|
-
whiteSpace: 'nowrap',
|
|
1308
|
-
overflow: 'hidden',
|
|
1309
|
-
textOverflow: 'ellipsis',
|
|
1310
|
-
}, children: dateComparisonPartialMatch ??
|
|
1431
|
+
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, handleDelete: handleDelete, editPopoverKey: editPopoverKey, isCard: isCard, isRow: isRow, getByKey: getByKey, EditPopover: EditPopover, Button: ButtonComponent, renderNode: renderNode, children: dateComparisonPartialMatch ??
|
|
1311
1432
|
dateEqualityPartialMatch ??
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
isInThePreviousIntervalSentence ?? (_jsxs(_Fragment, { children: [node.left &&
|
|
1315
|
-
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: Select })) : null, node.right &&
|
|
1433
|
+
uniqueSentence ?? (_jsxs(_Fragment, { children: [node.left &&
|
|
1434
|
+
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 &&
|
|
1316
1435
|
renderSentence(formData, node.right, keyPrefix + 'right.', false, false, isRow)] })) }));
|
|
1317
1436
|
case 'column_ref':
|
|
1318
1437
|
return snakeCaseToTitleCase(node.column);
|
|
@@ -1347,6 +1466,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1347
1466
|
if (node.args.value.length < 1)
|
|
1348
1467
|
return null;
|
|
1349
1468
|
if (node.args.value[0].value) {
|
|
1469
|
+
if (node.args.value[0].type === 'single_quote_string') {
|
|
1470
|
+
return node.args.value[0].value.replaceAll('%', '');
|
|
1471
|
+
}
|
|
1350
1472
|
return snakeCaseToTitleCase(node.args.value[0].value.replaceAll('%', ''));
|
|
1351
1473
|
}
|
|
1352
1474
|
if (node.args.value[0].column)
|
|
@@ -1394,9 +1516,11 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1394
1516
|
}))
|
|
1395
1517
|
.sort((a, b) => {
|
|
1396
1518
|
const aIsId = a.name.toLowerCase() === 'id' ||
|
|
1397
|
-
a.name.toLowerCase().endsWith('_id')
|
|
1519
|
+
a.name.toLowerCase().endsWith('_id') ||
|
|
1520
|
+
a.name.endsWith('Id');
|
|
1398
1521
|
const bIsId = b.name.toLowerCase() === 'id' ||
|
|
1399
|
-
b.name.toLowerCase().endsWith('_id')
|
|
1522
|
+
b.name.toLowerCase().endsWith('_id') ||
|
|
1523
|
+
b.name.endsWith('Id');
|
|
1400
1524
|
if (aIsId && !bIsId)
|
|
1401
1525
|
return 1;
|
|
1402
1526
|
if (bIsId && !aIsId)
|
|
@@ -1413,7 +1537,8 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1413
1537
|
return false;
|
|
1414
1538
|
const allColumns = orderedColumnNames.filter((row) => {
|
|
1415
1539
|
const [table, _] = row.split('.');
|
|
1416
|
-
|
|
1540
|
+
const selectedTable = selectedColumns[0].split('.')[0];
|
|
1541
|
+
return selectedTable === table;
|
|
1417
1542
|
});
|
|
1418
1543
|
return selectedColumns.length === allColumns.length;
|
|
1419
1544
|
};
|
|
@@ -1432,12 +1557,12 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1432
1557
|
fontSize: 18,
|
|
1433
1558
|
margin: 0,
|
|
1434
1559
|
textAlign: 'left',
|
|
1435
|
-
}, children: "Add condition" }), _jsx(
|
|
1560
|
+
}, children: "Add condition" }), _jsx(TabsComponent, { value: topLevelBinaryOperator, options: DEFAULT_TAB_OPTIONS, onChange: (event) => setTopLevelBinaryOperator(event.target.value) }), activeEditItem && renderNode(activeEditItem), _jsx("div", { style: {
|
|
1436
1561
|
display: 'flex',
|
|
1437
1562
|
flexDirection: 'row',
|
|
1438
1563
|
gap: 8,
|
|
1439
1564
|
justifyContent: 'end',
|
|
1440
|
-
}, children: _jsx(
|
|
1565
|
+
}, children: _jsx(ButtonComponent, { onClick: onSave, label: 'Add condition' }) })] }));
|
|
1441
1566
|
};
|
|
1442
1567
|
const fetchUponChange = async (baseAst, newFormData) => {
|
|
1443
1568
|
// if newFormData is null still use it
|
|
@@ -1698,9 +1823,8 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1698
1823
|
newAst = convertRemoveSimpleParentheses(newAst);
|
|
1699
1824
|
const table = getTableNames(newAst)[0] ?? initialTableName;
|
|
1700
1825
|
const tableAlias = getTableAliases(newAst)[0] ?? initialTableName;
|
|
1701
|
-
newAst = removeNonSelectedTableReferences(newAst, tableAlias ?? table);
|
|
1826
|
+
newAst = removeNonSelectedTableReferences(newAst, tableAlias ?? table, getAllPossibleColumns().map((col) => col.name));
|
|
1702
1827
|
// newAst = convertDateComparison(newAst); // TODO
|
|
1703
|
-
ast = newAst; // so we fetch data for newAst later.
|
|
1704
1828
|
if (table !== currentTable) {
|
|
1705
1829
|
await getDistinctValues(table);
|
|
1706
1830
|
setCurrentTable(table);
|
|
@@ -1720,6 +1844,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1720
1844
|
}));
|
|
1721
1845
|
if (groupByPivot) {
|
|
1722
1846
|
setBaseAst(deepCopy({ ...newAst, orderby: null, limit: null }));
|
|
1847
|
+
newAst = deepCopy({ ...newAst, orderby: null, limit: null });
|
|
1723
1848
|
}
|
|
1724
1849
|
else {
|
|
1725
1850
|
setBaseAst(deepCopy({ ...newAst }));
|
|
@@ -1729,6 +1854,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1729
1854
|
// @ts-ignore
|
|
1730
1855
|
newAst?.where ? newAst?.where?.operator : 'AND');
|
|
1731
1856
|
}
|
|
1857
|
+
ast = newAst; // so we fetch data for newAst later.
|
|
1732
1858
|
const res2 = await fetch('https://quill-344421.uc.r.appspot.com/patterns', {
|
|
1733
1859
|
method: 'POST',
|
|
1734
1860
|
headers: {
|
|
@@ -1809,11 +1935,11 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1809
1935
|
fetchSqlQuery(newAst);
|
|
1810
1936
|
};
|
|
1811
1937
|
function TopLevelBooleanSwitch({ node, keyPrefix, handleOperatorChange, }) {
|
|
1812
|
-
return (_jsx("div", { style: { width: 'fit-content' }, children: _jsx(
|
|
1938
|
+
return (_jsx("div", { style: { width: 'fit-content' }, children: _jsx(TabsComponent, { value: node.operator, options: DEFAULT_TAB_OPTIONS, onChange: (event) => {
|
|
1813
1939
|
if (loading) {
|
|
1814
1940
|
return;
|
|
1815
1941
|
}
|
|
1816
|
-
handleOperatorChange(value, node, keyPrefix);
|
|
1942
|
+
handleOperatorChange(event.target.value, node, keyPrefix);
|
|
1817
1943
|
} }) }));
|
|
1818
1944
|
}
|
|
1819
1945
|
const DraggableItem = ({ id, label, onDelete }) => {
|
|
@@ -1822,9 +1948,9 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1822
1948
|
transform: DND_CSS.Transform.toString(transform),
|
|
1823
1949
|
transition,
|
|
1824
1950
|
};
|
|
1825
|
-
return (_jsx("div", { style: { ...style }, ref: setNodeRef, children: _jsx(
|
|
1951
|
+
return (_jsx("div", { style: { ...style }, ref: setNodeRef, children: _jsx(DraggableColumnComponent, { label: snakeCaseToTitleCase(label), onDelete: onDelete, DragHandle: (props) => (_jsx("div", { style: {
|
|
1826
1952
|
cursor: 'grab',
|
|
1827
|
-
}, ...attributes, ...listeners, children: _jsx(
|
|
1953
|
+
}, ...attributes, ...listeners, children: _jsx(props.dragIcon, {}) })) }) }));
|
|
1828
1954
|
};
|
|
1829
1955
|
function DraggableColumns() {
|
|
1830
1956
|
const sensors = useSensors(useSensor(PointerSensor), useSensor(KeyboardSensor, {
|
|
@@ -1833,9 +1959,11 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1833
1959
|
// When a drag event ends, switch the item order.
|
|
1834
1960
|
function handleDragEnd(event) {
|
|
1835
1961
|
const { active, over } = event;
|
|
1962
|
+
if (!active || !over)
|
|
1963
|
+
return;
|
|
1836
1964
|
if (active.id !== over.id) {
|
|
1837
|
-
const oldIndex = orderedColumnNames.findIndex((c) => c.endsWith(active.id));
|
|
1838
|
-
const newIndex = orderedColumnNames.findIndex((c) => c.endsWith(over.id));
|
|
1965
|
+
const oldIndex = orderedColumnNames.findIndex((c) => c.endsWith(`${currentTable}.${active.id}`));
|
|
1966
|
+
const newIndex = orderedColumnNames.findIndex((c) => c.endsWith(`${currentTable}.${over.id}`));
|
|
1839
1967
|
const newOrder = arrayMove(orderedColumnNames, oldIndex, newIndex);
|
|
1840
1968
|
setOrderedColumnNames(newOrder);
|
|
1841
1969
|
const orderedSelectedColumns = [];
|
|
@@ -1845,6 +1973,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1845
1973
|
orderedSelectedColumns.push(column);
|
|
1846
1974
|
}
|
|
1847
1975
|
}
|
|
1976
|
+
setSelectedOrderedColumns(orderedSelectedColumns);
|
|
1848
1977
|
// If there is already an AST saved in state, only update the columns
|
|
1849
1978
|
// otherwise fill in the defaultAST shape and also update columns.
|
|
1850
1979
|
const fallbackAST = {
|
|
@@ -1860,7 +1989,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1860
1989
|
};
|
|
1861
1990
|
const newAst = baseAst ? newBaseAst : fallbackAST;
|
|
1862
1991
|
setBaseAst(newAst);
|
|
1863
|
-
fetchSqlQuery(newAst);
|
|
1992
|
+
fetchSqlQuery(newAst, undefined, false);
|
|
1864
1993
|
}
|
|
1865
1994
|
}
|
|
1866
1995
|
const columnNamesInAst = baseAst?.columns.map((col) => {
|
|
@@ -1890,25 +2019,27 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1890
2019
|
flexDirection: 'row',
|
|
1891
2020
|
height: '100%',
|
|
1892
2021
|
...containerStyle,
|
|
1893
|
-
}, ref: parentRef, children: [_jsxs(
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
2022
|
+
}, ref: parentRef, children: [_jsxs(SidebarComponent, { children: [_jsx(SidebarHeadingComponent, { label: "Columns" }), _jsx("div", { style: { height: 4, width: '100%' } }), _jsx(DraggableColumns, {}), _jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2023
|
+
if (loadingSchema)
|
|
2024
|
+
return;
|
|
2025
|
+
if (!openPopover) {
|
|
2026
|
+
setOpenPopover('AddColumnPopover');
|
|
2027
|
+
}
|
|
2028
|
+
}, label: 'Select columns' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddColumnPopover', setIsOpen: (isOpen) => {
|
|
2029
|
+
if (!isOpen) {
|
|
2030
|
+
setIsPending(false);
|
|
2031
|
+
setActiveEditItem(null);
|
|
2032
|
+
setActivePath(null);
|
|
2033
|
+
setOpenPopover(null);
|
|
2034
|
+
}
|
|
2035
|
+
}, popoverTitle: "Select columns", popoverChildren: _jsx(AddColumnPopover, { onSave: () => {
|
|
1905
2036
|
setActiveEditItem(null);
|
|
1906
2037
|
setActivePath(null);
|
|
1907
2038
|
setOpenPopover(null);
|
|
1908
2039
|
}, orderedColumnNames: orderedColumnNames, setOrderedColumnNames: setOrderedColumnNames, selectedColumns: selectedColumns, setSelectedColumns: setSelectedColumns, isSelectedAllColumns: isSelectedAllColumns, clearAllState: clearAllState, nameToColumn: nameToColumn, baseAst: baseAst, setBaseAst: (newAst) => {
|
|
1909
2040
|
setBaseAst(newAst);
|
|
1910
2041
|
fetchSqlQuery(newAst);
|
|
1911
|
-
}, pivot: pivot, initialTableName: initialTableName, defaultAST: defaultAST, defaultTable: defaultTable, setPivot: setPivot, TextInput:
|
|
2042
|
+
}, 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: {
|
|
1912
2043
|
display: 'flex',
|
|
1913
2044
|
flexDirection: 'column',
|
|
1914
2045
|
gap: 8,
|
|
@@ -1918,39 +2049,41 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1918
2049
|
flexDirection: 'column',
|
|
1919
2050
|
gap: 2.5,
|
|
1920
2051
|
alignItems: 'flex-start',
|
|
1921
|
-
}, children: [_jsx(
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
2052
|
+
}, children: [_jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2053
|
+
if (!selectedColumns ||
|
|
2054
|
+
selectedColumns.length === 0 ||
|
|
2055
|
+
loading) {
|
|
2056
|
+
return;
|
|
2057
|
+
}
|
|
2058
|
+
if (!openPopover) {
|
|
2059
|
+
const value = orderedColumnNames[0];
|
|
2060
|
+
const [_table, column] = value.split('.');
|
|
2061
|
+
const columnType = getColumnTypeByName(column);
|
|
2062
|
+
if (isNumericColumnType(columnType)) {
|
|
2063
|
+
const newSubtree = deepCopy(defaultNumericComparison);
|
|
2064
|
+
newSubtree.left.column = column;
|
|
2065
|
+
setActiveEditItem(newSubtree);
|
|
1926
2066
|
}
|
|
1927
|
-
|
|
1928
|
-
const
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
if (isNumericColumnType(columnType)) {
|
|
1932
|
-
const newSubtree = deepCopy(defaultNumericComparison);
|
|
1933
|
-
newSubtree.left.column = column;
|
|
1934
|
-
setActiveEditItem(newSubtree);
|
|
1935
|
-
}
|
|
1936
|
-
else {
|
|
1937
|
-
const newSubtree = deepCopy(defaultEntry);
|
|
1938
|
-
newSubtree.left.args.value[0].column = column;
|
|
1939
|
-
setActiveEditItem(newSubtree);
|
|
1940
|
-
}
|
|
1941
|
-
setOpenPopover('AddFilterPopover');
|
|
1942
|
-
setActivePath('');
|
|
1943
|
-
setIsPending(true);
|
|
2067
|
+
else {
|
|
2068
|
+
const newSubtree = deepCopy(defaultEntry);
|
|
2069
|
+
newSubtree.left.args.value[0].column = column;
|
|
2070
|
+
setActiveEditItem(newSubtree);
|
|
1944
2071
|
}
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
2072
|
+
setOpenPopover('AddFilterPopover');
|
|
2073
|
+
setActivePath('');
|
|
2074
|
+
setIsPending(true);
|
|
2075
|
+
}
|
|
2076
|
+
}, label: 'Add filter' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddFilterPopover', setIsOpen: (isOpen) => {
|
|
2077
|
+
if (!isOpen) {
|
|
2078
|
+
setIsPending(false);
|
|
2079
|
+
setActivePath(null);
|
|
2080
|
+
setOpenPopover(null);
|
|
2081
|
+
clearCheckboxes();
|
|
2082
|
+
setTimeout(() => {
|
|
2083
|
+
setActiveEditItem(null);
|
|
2084
|
+
}, 300);
|
|
2085
|
+
}
|
|
2086
|
+
}, popoverTitle: 'Add filter', popoverChildren: _jsx(AddFilterPopover, { onSave: () => {
|
|
1954
2087
|
if (isNodeEmptyCollection(activeEditItem)) {
|
|
1955
2088
|
setIsPending(false);
|
|
1956
2089
|
setActivePath(null);
|
|
@@ -1970,44 +2103,46 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
1970
2103
|
setActiveEditItem(null);
|
|
1971
2104
|
}, 300);
|
|
1972
2105
|
}
|
|
1973
|
-
}, Button:
|
|
2106
|
+
}, Button: ButtonComponent, renderNode: renderNode, activeEditItem: activeEditItem }) }), baseAst?.where &&
|
|
1974
2107
|
false && ( // temp removed the AddConditionPopover
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2108
|
+
_jsxs(_Fragment, { children: [_jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2109
|
+
if (!openPopover) {
|
|
2110
|
+
setActiveEditItem(deepCopy(defaultEntry));
|
|
2111
|
+
setOpenPopover('AddConditionPopover');
|
|
2112
|
+
setActivePath('');
|
|
2113
|
+
setIsPending(true);
|
|
2114
|
+
}
|
|
2115
|
+
}, label: "Add condition" }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddConditionPopover', setIsOpen: (isOpen) => {
|
|
2116
|
+
if (!isOpen) {
|
|
2117
|
+
setIsPending(false);
|
|
2118
|
+
setTimeout(() => {
|
|
2119
|
+
setActiveEditItem(null);
|
|
2120
|
+
}, 300);
|
|
2121
|
+
setActivePath(null);
|
|
2122
|
+
setOpenPopover(null);
|
|
2123
|
+
clearCheckboxes();
|
|
2124
|
+
}
|
|
2125
|
+
}, popoverTitle: "Add condition", popoverChildren: _jsx(AddConditionPopover, { onSave: () => {
|
|
2126
|
+
if (isNodeEmptyCollection(activeEditItem)) {
|
|
2127
|
+
setIsPending(false);
|
|
2128
|
+
setTimeout(() => {
|
|
2129
|
+
setActiveEditItem(null);
|
|
2130
|
+
}, 300);
|
|
2131
|
+
setActivePath(null);
|
|
2132
|
+
setOpenPopover(null);
|
|
2133
|
+
clearCheckboxes();
|
|
2134
|
+
}
|
|
2135
|
+
else {
|
|
2136
|
+
setIsPending(false);
|
|
2137
|
+
handleInsertion(activeEditItem, topLevelBinaryOperator, true);
|
|
2138
|
+
setTimeout(() => {
|
|
2139
|
+
setActiveEditItem(null);
|
|
2140
|
+
}, 300);
|
|
2141
|
+
setActivePath(null);
|
|
2142
|
+
setOpenPopover(null);
|
|
2143
|
+
clearCheckboxes();
|
|
2144
|
+
}
|
|
2145
|
+
} }) })] }))] }), _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, CardComponent: CardComponent, 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: () => {
|
|
2011
2146
|
setPivot(null);
|
|
2012
2147
|
setPivotData(null);
|
|
2013
2148
|
},
|
|
@@ -2021,7 +2156,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2021
2156
|
setPivot(pivot);
|
|
2022
2157
|
const pivotedData = generatePivotTable(pivot, rows, [null, null, null], false);
|
|
2023
2158
|
setPivotData(pivotedData || []);
|
|
2024
|
-
}, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent:
|
|
2159
|
+
}, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent: LabelComponent, HeaderComponent: HeaderComponent, dateRange: [null, null, null], recommendPivotCount: 3, SecondaryButtonComponent: SecondaryButtonComponent }), pivot && (_jsx(PivotCard, { pivotTable: {
|
|
2025
2160
|
pivot: pivot,
|
|
2026
2161
|
rows: pivotData?.rows || [],
|
|
2027
2162
|
columns: pivotData?.columns || [],
|
|
@@ -2033,11 +2168,11 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2033
2168
|
setPivotValueField(pivot?.valueField);
|
|
2034
2169
|
setPivotAggregation(pivot?.aggregationType);
|
|
2035
2170
|
setPivotPopUpTitle('Edit Pivot');
|
|
2036
|
-
}, selectedPivotIndex: -1, onEditPivot: () => { }, ButtonComponent:
|
|
2171
|
+
}, selectedPivotIndex: -1, onEditPivot: () => { }, CardComponent: CardComponent, ButtonComponent: ButtonComponent, HeaderComponent: HeaderComponent, showEdit: false, onClose: () => {
|
|
2037
2172
|
setPivot(null);
|
|
2038
2173
|
setPivotData(null);
|
|
2039
2174
|
setBaseAst(deepCopy(baseAst)); // trigger refetch
|
|
2040
|
-
}, minHeight: 180, LabelComponent:
|
|
2175
|
+
}, 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: {
|
|
2041
2176
|
display: 'flex',
|
|
2042
2177
|
flexDirection: 'column',
|
|
2043
2178
|
gap: 8,
|
|
@@ -2045,7 +2180,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2045
2180
|
}, children: _jsx(SortSentence, { sortData: {
|
|
2046
2181
|
type: pivot.sortDirection,
|
|
2047
2182
|
expr: { type: 'column_ref', column: pivot.rowField },
|
|
2048
|
-
}, columns: selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover:
|
|
2183
|
+
}, columns: selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setActivePath: setActivePath, setOpenPopover: setOpenPopover, SortPopover: SortPopoverComponent, EditPopover: AddSortPopover, handleDelete: () => {
|
|
2049
2184
|
setPivot({ ...pivot, sort: false });
|
|
2050
2185
|
setBaseAst(deepCopy(baseAst));
|
|
2051
2186
|
if (!pivot) {
|
|
@@ -2058,7 +2193,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2058
2193
|
if (!pivot) {
|
|
2059
2194
|
fetchSqlQuery(baseAst);
|
|
2060
2195
|
}
|
|
2061
|
-
}, Select:
|
|
2196
|
+
}, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent }, `sort-sentence-pivot`) })), baseAst && baseAst.orderby && (_jsx("div", { style: {
|
|
2062
2197
|
display: 'flex',
|
|
2063
2198
|
flexDirection: 'column',
|
|
2064
2199
|
gap: 8,
|
|
@@ -2085,31 +2220,33 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2085
2220
|
if (!pivot) {
|
|
2086
2221
|
fetchSqlQuery(newAst);
|
|
2087
2222
|
}
|
|
2088
|
-
}, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover:
|
|
2223
|
+
}, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setActivePath: setActivePath, setOpenPopover: setOpenPopover, SortPopover: SortPopoverComponent, EditPopover: AddSortPopover, handleDelete: () => {
|
|
2089
2224
|
const newAst = { ...baseAst };
|
|
2090
2225
|
newAst.orderby.splice(id, 1);
|
|
2091
2226
|
setBaseAst(deepCopy(newAst));
|
|
2092
2227
|
if (!pivot) {
|
|
2093
2228
|
fetchSqlQuery(newAst);
|
|
2094
2229
|
}
|
|
2095
|
-
}, Select:
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2230
|
+
}, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent }, `sort-sentence-${id}`))) })), _jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2231
|
+
if (!selectedColumns || selectedColumns.length === 0) {
|
|
2232
|
+
return;
|
|
2233
|
+
}
|
|
2234
|
+
if (!openPopover) {
|
|
2235
|
+
setOpenPopover('AddSortPopover');
|
|
2236
|
+
}
|
|
2237
|
+
}, label: "Add sort" }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddSortPopover', setIsOpen: (isOpen) => {
|
|
2238
|
+
if (!isOpen) {
|
|
2239
|
+
setIsPending(false);
|
|
2240
|
+
setActiveEditItem(null);
|
|
2241
|
+
setActivePath(null);
|
|
2242
|
+
setOpenPopover(null);
|
|
2243
|
+
}
|
|
2244
|
+
}, 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: {
|
|
2108
2245
|
display: 'flex',
|
|
2109
2246
|
flexDirection: 'column',
|
|
2110
2247
|
gap: 8,
|
|
2111
2248
|
marginBottom: 12,
|
|
2112
|
-
}, children: _jsx(LimitSentence, { limit: baseAst.limit, setOpenPopover: setOpenPopover, LimitPopover:
|
|
2249
|
+
}, children: _jsx(LimitSentence, { limit: baseAst.limit, setOpenPopover: setOpenPopover, LimitPopover: LimitPopoverComponent, EditPopover: AddLimitPopover, handleDelete: () => {
|
|
2113
2250
|
const newAst = { ...baseAst };
|
|
2114
2251
|
newAst.limit = null;
|
|
2115
2252
|
setBaseAst(deepCopy(newAst));
|
|
@@ -2128,27 +2265,29 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2128
2265
|
setOpenPopover(null);
|
|
2129
2266
|
setBaseAst(deepCopy(newAst));
|
|
2130
2267
|
fetchSqlQuery(newAst);
|
|
2131
|
-
}, TextInput:
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2268
|
+
}, TextInput: TextInputComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent }) })) : (_jsxs(_Fragment, { children: [_jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2269
|
+
if (!openPopover) {
|
|
2270
|
+
setOpenPopover('AddLimitPopover');
|
|
2271
|
+
}
|
|
2272
|
+
}, label: 'Add limit' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddLimitPopover', setIsOpen: (isOpen) => {
|
|
2273
|
+
if (!isOpen) {
|
|
2274
|
+
setIsPending(false);
|
|
2275
|
+
setActiveEditItem(null);
|
|
2276
|
+
setActivePath(null);
|
|
2277
|
+
setOpenPopover(null);
|
|
2278
|
+
}
|
|
2279
|
+
}, popoverTitle: "Limit", popoverChildren: _jsx(TextInputComponent, { id: "loading_input_limit", value: '0', width: 120, onChange: () => { } }) })] }))] }), _jsxs(ContainerComponent, { children: [isAIEnabled && (_jsxs("form", { ref: askAILoadingContainerRef, onSubmit: (event) => {
|
|
2141
2280
|
event.preventDefault();
|
|
2142
2281
|
}, style: {
|
|
2143
2282
|
display: 'flex',
|
|
2144
2283
|
flexDirection: 'row',
|
|
2145
2284
|
gap: 12,
|
|
2146
2285
|
padding: 1,
|
|
2147
|
-
}, children: [_jsx(
|
|
2286
|
+
}, 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: {
|
|
2148
2287
|
display: 'flex',
|
|
2149
2288
|
flexDirection: 'row',
|
|
2150
2289
|
gap: '12px',
|
|
2151
|
-
}, children: [_jsx("div", { style: { width: '100%' } }), _jsx(
|
|
2290
|
+
}, 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;}` })] }));
|
|
2152
2291
|
}
|
|
2153
2292
|
return (_jsxs("div", { ref: parentRef, style: {
|
|
2154
2293
|
display: 'flex',
|
|
@@ -2157,26 +2296,31 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2157
2296
|
overflowY: 'auto',
|
|
2158
2297
|
boxSizing: 'border-box',
|
|
2159
2298
|
...containerStyle,
|
|
2160
|
-
}, children: [_jsxs(
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2299
|
+
}, children: [_jsxs(SidebarComponent, { children: [_jsx(SidebarHeadingComponent, { label: "Columns" }), _jsx("div", { style: { height: 4, width: '100%' } }), _jsx(DraggableColumns, {}), _jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2300
|
+
if (!orderedColumnNames) {
|
|
2301
|
+
return;
|
|
2302
|
+
}
|
|
2303
|
+
if (!openPopover) {
|
|
2304
|
+
setOpenPopover('AddColumnPopover');
|
|
2305
|
+
}
|
|
2306
|
+
}, label: "Select columns" }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddColumnPopover', setIsOpen: (isOpen) => {
|
|
2307
|
+
if (!isOpen) {
|
|
2308
|
+
// delay onClose callback so onClick no-ops
|
|
2309
|
+
setTimeout(() => {
|
|
2310
|
+
setIsPending(false);
|
|
2311
|
+
setActiveEditItem(null);
|
|
2312
|
+
setActivePath(null);
|
|
2313
|
+
setOpenPopover(null);
|
|
2314
|
+
}, 100);
|
|
2315
|
+
}
|
|
2316
|
+
}, popoverTitle: "Select columns", popoverChildren: _jsx(AddColumnPopover, { onSave: () => {
|
|
2173
2317
|
setActiveEditItem(null);
|
|
2174
2318
|
setActivePath(null);
|
|
2175
2319
|
setOpenPopover(null);
|
|
2176
2320
|
}, orderedColumnNames: orderedColumnNames, setOrderedColumnNames: setOrderedColumnNames, selectedColumns: selectedColumns, setSelectedColumns: setSelectedColumns, isSelectedAllColumns: isSelectedAllColumns, clearAllState: clearAllState, nameToColumn: nameToColumn, baseAst: baseAst, setBaseAst: (ast) => {
|
|
2177
2321
|
setBaseAst(ast);
|
|
2178
2322
|
fetchSqlQuery(ast);
|
|
2179
|
-
}, pivot: pivot, initialTableName: initialTableName, defaultAST: defaultAST, defaultTable: defaultTable, setPivot: setPivot, TextInput:
|
|
2323
|
+
}, 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: {
|
|
2180
2324
|
display: 'flex',
|
|
2181
2325
|
flexDirection: 'column',
|
|
2182
2326
|
gap: 8,
|
|
@@ -2186,52 +2330,42 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2186
2330
|
flexDirection: 'column',
|
|
2187
2331
|
gap: 2.5,
|
|
2188
2332
|
alignItems: 'flex-start',
|
|
2189
|
-
}, children: [_jsx(
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2333
|
+
}, children: [_jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2334
|
+
if (!selectedColumns || selectedColumns.length === 0 || loading) {
|
|
2335
|
+
return;
|
|
2336
|
+
}
|
|
2337
|
+
if (!openPopover) {
|
|
2338
|
+
const value = orderedColumnNames[0];
|
|
2339
|
+
const [_table, column] = value.split('.');
|
|
2340
|
+
const columnType = getColumnTypeByName(column);
|
|
2341
|
+
if (isNumericColumnType(columnType)) {
|
|
2342
|
+
const newSubtree = deepCopy(defaultNumericComparison);
|
|
2343
|
+
newSubtree.left.column = column;
|
|
2344
|
+
setActiveEditItem(newSubtree);
|
|
2194
2345
|
}
|
|
2195
|
-
|
|
2196
|
-
const
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
if (isNumericColumnType(columnType)) {
|
|
2200
|
-
const newSubtree = deepCopy(defaultNumericComparison);
|
|
2201
|
-
newSubtree.left.column = column;
|
|
2202
|
-
setActiveEditItem(newSubtree);
|
|
2203
|
-
}
|
|
2204
|
-
else {
|
|
2205
|
-
const newSubtree = deepCopy(defaultEntry);
|
|
2206
|
-
newSubtree.left.args.value[0].column = column;
|
|
2207
|
-
setActiveEditItem(newSubtree);
|
|
2208
|
-
}
|
|
2209
|
-
setOpenPopover('AddFilterPopover');
|
|
2210
|
-
setActivePath('');
|
|
2211
|
-
setIsPending(true);
|
|
2346
|
+
else {
|
|
2347
|
+
const newSubtree = deepCopy(defaultEntry);
|
|
2348
|
+
newSubtree.left.args.value[0].column = column;
|
|
2349
|
+
setActiveEditItem(newSubtree);
|
|
2212
2350
|
}
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
}, 200);
|
|
2222
|
-
}, children: _jsx(AddFilterPopover, { onSave: () => {
|
|
2223
|
-
if (isNodeEmptyCollection(activeEditItem)) {
|
|
2351
|
+
setOpenPopover('AddFilterPopover');
|
|
2352
|
+
setActivePath('');
|
|
2353
|
+
setIsPending(true);
|
|
2354
|
+
}
|
|
2355
|
+
}, label: 'Add filter' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddFilterPopover', setIsOpen: (isOpen) => {
|
|
2356
|
+
if (!isOpen) {
|
|
2357
|
+
// delay onClose callback so onClick no-ops
|
|
2358
|
+
setTimeout(() => {
|
|
2224
2359
|
setIsPending(false);
|
|
2225
2360
|
setActivePath(null);
|
|
2226
2361
|
setOpenPopover(null);
|
|
2227
2362
|
clearCheckboxes();
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2363
|
+
setActiveEditItem(null);
|
|
2364
|
+
}, 200);
|
|
2365
|
+
}
|
|
2366
|
+
}, popoverTitle: "Add filter", popoverChildren: _jsx(AddFilterPopover, { onSave: () => {
|
|
2367
|
+
if (isNodeEmptyCollection(activeEditItem)) {
|
|
2233
2368
|
setIsPending(false);
|
|
2234
|
-
handleInsertion(activeEditItem, 'AND', false);
|
|
2235
2369
|
setActivePath(null);
|
|
2236
2370
|
setOpenPopover(null);
|
|
2237
2371
|
clearCheckboxes();
|
|
@@ -2239,45 +2373,57 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2239
2373
|
setActiveEditItem(null);
|
|
2240
2374
|
}, 300);
|
|
2241
2375
|
}
|
|
2242
|
-
|
|
2243
|
-
false && ( // temp removed the AddConditionPopover
|
|
2244
|
-
_jsx(Popover, { isOpen: openPopover === 'AddConditionPopover', trigger: _jsx(SecondaryButton, { onClick: () => {
|
|
2245
|
-
if (!openPopover) {
|
|
2246
|
-
setActiveEditItem(deepCopy(defaultEntry));
|
|
2247
|
-
setOpenPopover('AddConditionPopover');
|
|
2248
|
-
setActivePath('');
|
|
2249
|
-
setIsPending(true);
|
|
2250
|
-
}
|
|
2251
|
-
}, label: 'Add condition' }), onClose: () => {
|
|
2252
|
-
// delay onClose callback so onClick no-ops
|
|
2253
|
-
setTimeout(() => {
|
|
2254
|
-
setIsPending(false);
|
|
2255
|
-
setActiveEditItem(null);
|
|
2256
|
-
setActivePath(null);
|
|
2257
|
-
setOpenPopover(null);
|
|
2258
|
-
clearCheckboxes();
|
|
2259
|
-
}, 200);
|
|
2260
|
-
}, children: _jsx(AddConditionPopover, { onSave: () => {
|
|
2261
|
-
if (isNodeEmptyCollection(activeEditItem)) {
|
|
2376
|
+
else {
|
|
2262
2377
|
setIsPending(false);
|
|
2263
|
-
|
|
2264
|
-
setActiveEditItem(null);
|
|
2265
|
-
}, 300);
|
|
2378
|
+
handleInsertion(activeEditItem, 'AND', false);
|
|
2266
2379
|
setActivePath(null);
|
|
2267
2380
|
setOpenPopover(null);
|
|
2268
2381
|
clearCheckboxes();
|
|
2269
|
-
}
|
|
2270
|
-
else {
|
|
2271
|
-
setIsPending(false);
|
|
2272
|
-
handleInsertion(activeEditItem, topLevelBinaryOperator, true);
|
|
2273
2382
|
setTimeout(() => {
|
|
2274
2383
|
setActiveEditItem(null);
|
|
2275
2384
|
}, 300);
|
|
2276
|
-
setActivePath(null);
|
|
2277
|
-
setOpenPopover(null);
|
|
2278
|
-
clearCheckboxes();
|
|
2279
2385
|
}
|
|
2280
|
-
}
|
|
2386
|
+
}, Button: ButtonComponent, renderNode: renderNode, activeEditItem: activeEditItem }) }), baseAst?.where &&
|
|
2387
|
+
false && ( // temp removed the AddConditionPopover
|
|
2388
|
+
_jsxs(_Fragment, { children: [_jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2389
|
+
if (!openPopover) {
|
|
2390
|
+
setActiveEditItem(deepCopy(defaultEntry));
|
|
2391
|
+
setOpenPopover('AddConditionPopover');
|
|
2392
|
+
setActivePath('');
|
|
2393
|
+
setIsPending(true);
|
|
2394
|
+
}
|
|
2395
|
+
}, label: 'Add condition' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddConditionPopover', setIsOpen: (isOpen) => {
|
|
2396
|
+
if (!isOpen) {
|
|
2397
|
+
// delay onClose callback so onClick no-ops
|
|
2398
|
+
setTimeout(() => {
|
|
2399
|
+
setIsPending(false);
|
|
2400
|
+
setActiveEditItem(null);
|
|
2401
|
+
setActivePath(null);
|
|
2402
|
+
setOpenPopover(null);
|
|
2403
|
+
clearCheckboxes();
|
|
2404
|
+
}, 200);
|
|
2405
|
+
}
|
|
2406
|
+
}, popoverChildren: _jsx(AddConditionPopover, { onSave: () => {
|
|
2407
|
+
if (isNodeEmptyCollection(activeEditItem)) {
|
|
2408
|
+
setIsPending(false);
|
|
2409
|
+
setTimeout(() => {
|
|
2410
|
+
setActiveEditItem(null);
|
|
2411
|
+
}, 300);
|
|
2412
|
+
setActivePath(null);
|
|
2413
|
+
setOpenPopover(null);
|
|
2414
|
+
clearCheckboxes();
|
|
2415
|
+
}
|
|
2416
|
+
else {
|
|
2417
|
+
setIsPending(false);
|
|
2418
|
+
handleInsertion(activeEditItem, topLevelBinaryOperator, true);
|
|
2419
|
+
setTimeout(() => {
|
|
2420
|
+
setActiveEditItem(null);
|
|
2421
|
+
}, 300);
|
|
2422
|
+
setActivePath(null);
|
|
2423
|
+
setOpenPopover(null);
|
|
2424
|
+
clearCheckboxes();
|
|
2425
|
+
}
|
|
2426
|
+
} }) })] }))] }), _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, CardComponent: CardComponent, 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: () => {
|
|
2281
2427
|
setPivot(null);
|
|
2282
2428
|
setPivotData(null);
|
|
2283
2429
|
}, selectPivot: (pivot) => {
|
|
@@ -2293,7 +2439,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2293
2439
|
setPivot(pivot);
|
|
2294
2440
|
const pivotedData = generatePivotTable(pivot, rows, [null, null, null], false);
|
|
2295
2441
|
setPivotData(pivotedData || []);
|
|
2296
|
-
}, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent:
|
|
2442
|
+
}, selectPivotOnEdit: true, showTrigger: !pivot, theme: theme, LabelComponent: LabelComponent, HeaderComponent: HeaderComponent, dateRange: [null, null, null], recommendPivotCount: 3 }), pivot && (_jsx(PivotCard, { pivotTable: {
|
|
2297
2443
|
pivot: pivot,
|
|
2298
2444
|
rows: pivotData?.rows || [],
|
|
2299
2445
|
columns: pivotData?.columns || [],
|
|
@@ -2305,11 +2451,11 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2305
2451
|
setPivotValueField(pivot?.valueField);
|
|
2306
2452
|
setPivotAggregation(pivot?.aggregationType);
|
|
2307
2453
|
setPivotPopUpTitle('Edit Pivot');
|
|
2308
|
-
}, selectedPivotIndex: -1, onEditPivot: () => { }, ButtonComponent:
|
|
2454
|
+
}, selectedPivotIndex: -1, onEditPivot: () => { }, ButtonComponent: ButtonComponent, HeaderComponent: HeaderComponent, CardComponent: CardComponent, showEdit: false, onClose: () => {
|
|
2309
2455
|
setPivot(null);
|
|
2310
2456
|
setPivotData(null);
|
|
2311
2457
|
setBaseAst(deepCopy(baseAst));
|
|
2312
|
-
}, minHeight: 180, LabelComponent:
|
|
2458
|
+
}, 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: {
|
|
2313
2459
|
display: 'flex',
|
|
2314
2460
|
flexDirection: 'column',
|
|
2315
2461
|
gap: 8,
|
|
@@ -2317,7 +2463,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2317
2463
|
}, children: _jsx(SortSentence, { sortData: {
|
|
2318
2464
|
type: pivot.sortDirection,
|
|
2319
2465
|
expr: { type: 'column_ref', column: pivot.rowField },
|
|
2320
|
-
}, columns: pivot ? [`.${pivot.rowField}`] : selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover:
|
|
2466
|
+
}, columns: pivot ? [`.${pivot.rowField}`] : selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setActivePath: setActivePath, setOpenPopover: setOpenPopover, SortPopover: SortPopoverComponent, EditPopover: AddSortPopover, handleDelete: () => {
|
|
2321
2467
|
if (pivot) {
|
|
2322
2468
|
setPivot({ ...pivot, sort: false });
|
|
2323
2469
|
const pivotedData = generatePivotTable({ ...pivot, sort: false }, rows, [null, null, null], false);
|
|
@@ -2336,12 +2482,12 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2336
2482
|
setOpenPopover(null);
|
|
2337
2483
|
setBaseAst(deepCopy(baseAst));
|
|
2338
2484
|
fetchSqlQuery(deepCopy(baseAst));
|
|
2339
|
-
}, Select:
|
|
2485
|
+
}, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent }, `sort-sentence-pivot`) })), baseAst && baseAst.orderby && (_jsx("div", { style: {
|
|
2340
2486
|
display: 'flex',
|
|
2341
2487
|
flexDirection: 'column',
|
|
2342
2488
|
gap: 8,
|
|
2343
2489
|
marginBottom: 12,
|
|
2344
|
-
}, children: baseAst.orderby.map((sortData, id) => (_jsx(SortSentence, { sortData: sortData, columns: selectedColumns, setIsPending: setIsPending, setEditPopoverKey: setEditPopoverKey, setActiveEditItem: setActiveEditItem, setOpenPopover: setOpenPopover, SortPopover:
|
|
2490
|
+
}, 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: () => {
|
|
2345
2491
|
if (pivot) {
|
|
2346
2492
|
setPivot({ ...pivot, sort: false });
|
|
2347
2493
|
return;
|
|
@@ -2378,19 +2524,21 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2378
2524
|
setOpenPopover(null);
|
|
2379
2525
|
setBaseAst(deepCopy(newAst));
|
|
2380
2526
|
fetchSqlQuery(deepCopy(newAst));
|
|
2381
|
-
}, Select:
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2527
|
+
}, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent }, `sort-sentence-${id}`))) })), _jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2528
|
+
if (!selectedColumns || selectedColumns.length === 0) {
|
|
2529
|
+
return;
|
|
2530
|
+
}
|
|
2531
|
+
if (!openPopover) {
|
|
2532
|
+
setOpenPopover('AddSortPopover');
|
|
2533
|
+
}
|
|
2534
|
+
}, label: 'Add sort' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddSortPopover', setIsOpen: (isOpen) => {
|
|
2535
|
+
if (!isOpen) {
|
|
2536
|
+
setIsPending(false);
|
|
2537
|
+
setActiveEditItem(null);
|
|
2538
|
+
setActivePath(null);
|
|
2539
|
+
setOpenPopover(null);
|
|
2540
|
+
}
|
|
2541
|
+
}, popoverTitle: "Sort by", popoverChildren: _jsx(AddSortPopover, { columns: pivot ? [`.${pivot.rowField}`] : selectedColumns, Select: SelectComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, onSave: (column, direction) => {
|
|
2394
2542
|
if (column === '')
|
|
2395
2543
|
return;
|
|
2396
2544
|
if (pivot) {
|
|
@@ -2414,12 +2562,12 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2414
2562
|
setOpenPopover(null);
|
|
2415
2563
|
setBaseAst(deepCopy(newAst));
|
|
2416
2564
|
fetchSqlQuery(deepCopy(newAst));
|
|
2417
|
-
} }) }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(
|
|
2565
|
+
} }) }), _jsx("div", { style: { height: 28, width: '100%' } }), _jsx(SidebarHeadingComponent, { label: "Limit" }), _jsx("div", { style: { height: 4, width: '100%' } }), baseAst && baseAst.limit ? (_jsx("div", { style: {
|
|
2418
2566
|
display: 'flex',
|
|
2419
2567
|
flexDirection: 'column',
|
|
2420
2568
|
gap: 8,
|
|
2421
2569
|
marginBottom: 12,
|
|
2422
|
-
}, children: _jsx(LimitSentence, { limit: baseAst.limit, setOpenPopover: setOpenPopover, LimitPopover:
|
|
2570
|
+
}, children: _jsx(LimitSentence, { limit: baseAst.limit, setOpenPopover: setOpenPopover, LimitPopover: LimitPopoverComponent, EditPopover: AddLimitPopover, handleDelete: () => {
|
|
2423
2571
|
const newAst = { ...baseAst };
|
|
2424
2572
|
newAst.limit = null;
|
|
2425
2573
|
setBaseAst(deepCopy(newAst));
|
|
@@ -2438,36 +2586,38 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2438
2586
|
setOpenPopover(null);
|
|
2439
2587
|
setBaseAst(deepCopy(newAst));
|
|
2440
2588
|
fetchSqlQuery(deepCopy(newAst));
|
|
2441
|
-
}, TextInput:
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2589
|
+
}, TextInput: TextInputComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent }) })) : (_jsxs(_Fragment, { children: [_jsx(SecondaryButtonComponent, { onClick: () => {
|
|
2590
|
+
if (!selectedColumns || selectedColumns.length === 0) {
|
|
2591
|
+
return;
|
|
2592
|
+
}
|
|
2593
|
+
if (!baseAst) {
|
|
2594
|
+
return;
|
|
2595
|
+
}
|
|
2596
|
+
if (!openPopover) {
|
|
2597
|
+
setOpenPopover('AddLimitPopover');
|
|
2598
|
+
}
|
|
2599
|
+
}, label: 'Add limit' }), _jsx(PopoverComponent, { isOpen: openPopover === 'AddLimitPopover', setIsOpen: (isOpen) => {
|
|
2600
|
+
if (!isOpen) {
|
|
2601
|
+
setIsPending(false);
|
|
2602
|
+
setActiveEditItem(null);
|
|
2603
|
+
setActivePath(null);
|
|
2604
|
+
setOpenPopover(null);
|
|
2605
|
+
}
|
|
2606
|
+
}, popoverTitle: "Limit", popoverChildren: _jsx(AddLimitPopover, { TextInput: TextInputComponent, Button: ButtonComponent, SecondaryButton: SecondaryButtonComponent, onSave: (limit) => {
|
|
2607
|
+
const newAst = { ...baseAst };
|
|
2608
|
+
newAst.limit = {
|
|
2609
|
+
seperator: '',
|
|
2610
|
+
value: [
|
|
2611
|
+
{
|
|
2612
|
+
type: 'number',
|
|
2613
|
+
value: Number(limit),
|
|
2614
|
+
},
|
|
2615
|
+
],
|
|
2616
|
+
};
|
|
2617
|
+
setOpenPopover(null);
|
|
2618
|
+
setBaseAst(deepCopy(newAst));
|
|
2619
|
+
fetchSqlQuery(deepCopy(newAst));
|
|
2620
|
+
} }) })] }))] }), _jsxs(ContainerComponent, { children: [isAIEnabled && (_jsxs("form", { ref: askAIContainerRef, onSubmit: (event) => {
|
|
2471
2621
|
event.preventDefault();
|
|
2472
2622
|
handleAsk();
|
|
2473
2623
|
}, style: {
|
|
@@ -2475,14 +2625,14 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2475
2625
|
flexDirection: 'row',
|
|
2476
2626
|
gap: 12,
|
|
2477
2627
|
padding: 1,
|
|
2478
|
-
}, children: [_jsx(
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2628
|
+
}, 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({
|
|
2629
|
+
rows: pivotData?.rows || rows,
|
|
2630
|
+
fields: pivotData?.fields || fields,
|
|
2631
|
+
}, baseAst?.columns ?? []), columns: pivot
|
|
2632
|
+
? pivotData?.columns || emptyPivotColumns()
|
|
2633
|
+
: enforceOrderOnColumns(Object.keys(rows[0] ?? {})).map((c) => {
|
|
2634
|
+
return { label: snakeCaseToTitleCase(c), field: c };
|
|
2635
|
+
}) })), _jsxs("div", { style: {
|
|
2486
2636
|
display: 'flex',
|
|
2487
2637
|
flexDirection: 'row',
|
|
2488
2638
|
gap: '12px',
|
|
@@ -2491,10 +2641,7 @@ export default function ReportBuilder({ initialTableName = '', onAddToDashboardC
|
|
|
2491
2641
|
fontSize: 14,
|
|
2492
2642
|
padding: '12px',
|
|
2493
2643
|
whiteSpace: 'nowrap',
|
|
2494
|
-
}, children: errorMessage })), _jsx("div", { style: { width: '100%' } }), baseAst && (_jsxs(_Fragment, { children: [_jsx(
|
|
2644
|
+
}, children: errorMessage })), _jsx("div", { style: { width: '100%' } }), baseAst && (_jsxs(_Fragment, { children: [_jsx(SecondaryButtonComponent, { label: isCopying ? '✅ Copied' : 'Copy SQL', onClick: () => copyToClipboard(activeQuery) }), _jsx(ButtonComponent, { onClick: () => {
|
|
2495
2645
|
setIsChartBuilderOpen(true);
|
|
2496
|
-
}, label: 'Add to dashboard' })] }))] })] }), _jsx("style", { children: `body{margin:0;}` }), _jsx(ChartBuilderWithModal, { rows:
|
|
2497
|
-
// TODO: Modal={Modal}
|
|
2498
|
-
// TODO: Popover={Popover}
|
|
2499
|
-
DeleteButton: DeleteButton })] }));
|
|
2646
|
+
}, 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, CardComponent: CardComponent, ModalComponent: ModalComponent, PopoverComponent: PopoverComponent, DeleteButtonComponent: DeleteButtonComponent })] }));
|
|
2500
2647
|
}
|