@finos/legend-data-cube 0.1.11 → 0.1.13
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/lib/components/DataCubePlaceholder.d.ts.map +1 -1
- package/lib/components/DataCubePlaceholder.js +2 -1
- package/lib/components/DataCubePlaceholder.js.map +1 -1
- package/lib/components/core/DataCubePureCodeEditorUtils.d.ts +2 -1
- package/lib/components/core/DataCubePureCodeEditorUtils.d.ts.map +1 -1
- package/lib/components/core/DataCubePureCodeEditorUtils.js.map +1 -1
- package/lib/components/view/editor/DataCubeEditor.d.ts.map +1 -1
- package/lib/components/view/editor/DataCubeEditor.js +4 -2
- package/lib/components/view/editor/DataCubeEditor.js.map +1 -1
- package/lib/components/view/editor/DataCubeEditorColumnsPanel.d.ts.map +1 -1
- package/lib/components/view/editor/DataCubeEditorColumnsPanel.js +3 -3
- package/lib/components/view/editor/DataCubeEditorColumnsPanel.js.map +1 -1
- package/lib/components/view/editor/DataCubeEditorColumnsSelector.d.ts +47 -0
- package/lib/components/view/editor/DataCubeEditorColumnsSelector.d.ts.map +1 -0
- package/lib/components/view/editor/{DataCubeEditorColumnSelector.js → DataCubeEditorColumnsSelector.js} +70 -55
- package/lib/components/view/editor/DataCubeEditorColumnsSelector.js.map +1 -0
- package/lib/components/view/editor/DataCubeEditorDimensionsPanel.d.ts +3 -13
- package/lib/components/view/editor/DataCubeEditorDimensionsPanel.d.ts.map +1 -1
- package/lib/components/view/editor/DataCubeEditorDimensionsPanel.js +707 -264
- package/lib/components/view/editor/DataCubeEditorDimensionsPanel.js.map +1 -1
- package/lib/components/view/editor/DataCubeEditorHorizontalPivotsPanel.js +2 -2
- package/lib/components/view/editor/DataCubeEditorHorizontalPivotsPanel.js.map +1 -1
- package/lib/components/view/editor/DataCubeEditorSortsPanel.js +2 -2
- package/lib/components/view/editor/DataCubeEditorSortsPanel.js.map +1 -1
- package/lib/components/view/editor/DataCubeEditorVerticalPivotsPanel.js +2 -2
- package/lib/components/view/editor/DataCubeEditorVerticalPivotsPanel.js.map +1 -1
- package/lib/components/view/{grid/DataCubeGridShared.d.ts → extend/DataCubeCodeEditor.d.ts} +7 -3
- package/lib/components/view/extend/DataCubeCodeEditor.d.ts.map +1 -0
- package/lib/components/view/extend/DataCubeCodeEditor.js +114 -0
- package/lib/components/view/extend/DataCubeCodeEditor.js.map +1 -0
- package/lib/components/view/extend/DataCubeCodeEditorState.d.ts +43 -0
- package/lib/components/view/extend/DataCubeCodeEditorState.d.ts.map +1 -0
- package/lib/components/view/extend/DataCubeCodeEditorState.js +37 -0
- package/lib/components/view/extend/DataCubeCodeEditorState.js.map +1 -0
- package/lib/components/view/extend/DataCubeColumnEditor.d.ts.map +1 -1
- package/lib/components/view/extend/DataCubeColumnEditor.js +5 -84
- package/lib/components/view/extend/DataCubeColumnEditor.js.map +1 -1
- package/lib/components/view/grid/DataCubeGrid.d.ts +2 -1
- package/lib/components/view/grid/DataCubeGrid.d.ts.map +1 -1
- package/lib/components/view/grid/DataCubeGrid.js +29 -19
- package/lib/components/view/grid/DataCubeGrid.js.map +1 -1
- package/lib/components/view/grid/DataCubeMultidimensionalGrid.d.ts +1 -1
- package/lib/components/view/grid/DataCubeMultidimensionalGrid.d.ts.map +1 -1
- package/lib/components/view/grid/DataCubeMultidimensionalGrid.js +2 -1
- package/lib/components/view/grid/DataCubeMultidimensionalGrid.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/DataCubeAPI.d.ts.map +1 -1
- package/lib/stores/DataCubeAPI.js +3 -1
- package/lib/stores/DataCubeAPI.js.map +1 -1
- package/lib/stores/core/DataCubeEngine.d.ts +1 -1
- package/lib/stores/core/DataCubeEngine.d.ts.map +1 -1
- package/lib/stores/core/DataCubeQueryEngine.d.ts +5 -0
- package/lib/stores/core/DataCubeQueryEngine.d.ts.map +1 -1
- package/lib/stores/core/DataCubeQueryEngine.js +6 -0
- package/lib/stores/core/DataCubeQueryEngine.js.map +1 -1
- package/lib/stores/core/DataCubeSnapshot.d.ts +1 -1
- package/lib/stores/core/DataCubeSnapshot.d.ts.map +1 -1
- package/lib/stores/core/model/AdhocQueryDataCubeSource.d.ts +2 -0
- package/lib/stores/core/model/AdhocQueryDataCubeSource.d.ts.map +1 -1
- package/lib/stores/core/model/AdhocQueryDataCubeSource.js +3 -0
- package/lib/stores/core/model/AdhocQueryDataCubeSource.js.map +1 -1
- package/lib/stores/core/model/DataCubeConfiguration.d.ts +11 -0
- package/lib/stores/core/model/DataCubeConfiguration.d.ts.map +1 -1
- package/lib/stores/core/model/DataCubeConfiguration.js +19 -1
- package/lib/stores/core/model/DataCubeConfiguration.js.map +1 -1
- package/lib/stores/services/DataCubeSettingService.d.ts.map +1 -1
- package/lib/stores/services/DataCubeSettingService.js +10 -6
- package/lib/stores/services/DataCubeSettingService.js.map +1 -1
- package/lib/stores/view/DataCubeInfoState.d.ts +2 -0
- package/lib/stores/view/DataCubeInfoState.d.ts.map +1 -1
- package/lib/stores/view/DataCubeInfoState.js +3 -0
- package/lib/stores/view/DataCubeInfoState.js.map +1 -1
- package/lib/stores/view/editor/DataCubeEditorColumnsPanelState.d.ts +8 -8
- package/lib/stores/view/editor/DataCubeEditorColumnsPanelState.d.ts.map +1 -1
- package/lib/stores/view/editor/DataCubeEditorColumnsPanelState.js +6 -6
- package/lib/stores/view/editor/DataCubeEditorColumnsPanelState.js.map +1 -1
- package/lib/stores/view/editor/{DataCubeEditorColumnSelectorState.d.ts → DataCubeEditorColumnsSelectorState.d.ts} +6 -6
- package/lib/stores/view/editor/DataCubeEditorColumnsSelectorState.d.ts.map +1 -0
- package/lib/stores/view/editor/{DataCubeEditorColumnSelectorState.js → DataCubeEditorColumnsSelectorState.js} +4 -4
- package/lib/stores/view/editor/DataCubeEditorColumnsSelectorState.js.map +1 -0
- package/lib/stores/view/editor/DataCubeEditorDimensionsPanelState.d.ts +29 -6
- package/lib/stores/view/editor/DataCubeEditorDimensionsPanelState.d.ts.map +1 -1
- package/lib/stores/view/editor/DataCubeEditorDimensionsPanelState.js +102 -39
- package/lib/stores/view/editor/DataCubeEditorDimensionsPanelState.js.map +1 -1
- package/lib/stores/view/editor/DataCubeEditorHorizontalPivotsPanelState.d.ts +5 -5
- package/lib/stores/view/editor/DataCubeEditorHorizontalPivotsPanelState.d.ts.map +1 -1
- package/lib/stores/view/editor/DataCubeEditorHorizontalPivotsPanelState.js +7 -6
- package/lib/stores/view/editor/DataCubeEditorHorizontalPivotsPanelState.js.map +1 -1
- package/lib/stores/view/editor/DataCubeEditorMutableConfiguration.d.ts +2 -1
- package/lib/stores/view/editor/DataCubeEditorMutableConfiguration.d.ts.map +1 -1
- package/lib/stores/view/editor/DataCubeEditorMutableConfiguration.js +5 -0
- package/lib/stores/view/editor/DataCubeEditorMutableConfiguration.js.map +1 -1
- package/lib/stores/view/editor/DataCubeEditorSortsPanelState.d.ts +5 -5
- package/lib/stores/view/editor/DataCubeEditorSortsPanelState.d.ts.map +1 -1
- package/lib/stores/view/editor/DataCubeEditorSortsPanelState.js +6 -6
- package/lib/stores/view/editor/DataCubeEditorSortsPanelState.js.map +1 -1
- package/lib/stores/view/editor/DataCubeEditorState.d.ts +3 -0
- package/lib/stores/view/editor/DataCubeEditorState.d.ts.map +1 -1
- package/lib/stores/view/editor/DataCubeEditorState.js +6 -0
- package/lib/stores/view/editor/DataCubeEditorState.js.map +1 -1
- package/lib/stores/view/editor/DataCubeEditorVerticalPivotsPanelState.d.ts +5 -5
- package/lib/stores/view/editor/DataCubeEditorVerticalPivotsPanelState.d.ts.map +1 -1
- package/lib/stores/view/editor/DataCubeEditorVerticalPivotsPanelState.js +6 -6
- package/lib/stores/view/editor/DataCubeEditorVerticalPivotsPanelState.js.map +1 -1
- package/lib/stores/view/extend/DataCubeColumnEditorState.d.ts +7 -14
- package/lib/stores/view/extend/DataCubeColumnEditorState.d.ts.map +1 -1
- package/lib/stores/view/extend/DataCubeColumnEditorState.js +14 -22
- package/lib/stores/view/extend/DataCubeColumnEditorState.js.map +1 -1
- package/lib/stores/view/grid/DataCubeGridClientEngine.d.ts +2 -1
- package/lib/stores/view/grid/DataCubeGridClientEngine.d.ts.map +1 -1
- package/lib/stores/view/grid/DataCubeGridClientEngine.js +7 -0
- package/lib/stores/view/grid/DataCubeGridClientEngine.js.map +1 -1
- package/lib/stores/view/grid/DataCubeGridClientExportEngine.js +1 -1
- package/lib/stores/view/grid/DataCubeGridClientExportEngine.js.map +1 -1
- package/lib/stores/view/grid/DataCubeGridMenuBuilder.d.ts +2 -0
- package/lib/stores/view/grid/DataCubeGridMenuBuilder.d.ts.map +1 -1
- package/lib/stores/view/grid/DataCubeGridMenuBuilder.js +9 -16
- package/lib/stores/view/grid/DataCubeGridMenuBuilder.js.map +1 -1
- package/lib/stores/view/grid/DataCubeGridState.d.ts +2 -2
- package/lib/stores/view/grid/DataCubeGridState.d.ts.map +1 -1
- package/lib/stores/view/grid/DataCubeGridState.js +19 -6
- package/lib/stores/view/grid/DataCubeGridState.js.map +1 -1
- package/package.json +5 -5
- package/src/components/DataCubePlaceholder.tsx +2 -0
- package/src/components/core/DataCubePureCodeEditorUtils.tsx +2 -1
- package/src/components/view/editor/DataCubeEditor.tsx +8 -3
- package/src/components/view/editor/DataCubeEditorColumnsPanel.tsx +6 -8
- package/src/components/view/editor/{DataCubeEditorColumnSelector.tsx → DataCubeEditorColumnsSelector.tsx} +108 -83
- package/src/components/view/editor/DataCubeEditorDimensionsPanel.tsx +1259 -503
- package/src/components/view/editor/DataCubeEditorHorizontalPivotsPanel.tsx +5 -5
- package/src/components/view/editor/DataCubeEditorSortsPanel.tsx +10 -10
- package/src/components/view/editor/DataCubeEditorVerticalPivotsPanel.tsx +2 -2
- package/src/components/view/extend/DataCubeCodeEditor.tsx +175 -0
- package/src/components/view/extend/DataCubeCodeEditorState.tsx +72 -0
- package/src/components/view/extend/DataCubeColumnEditor.tsx +5 -133
- package/src/components/view/grid/DataCubeGrid.tsx +70 -53
- package/src/components/view/grid/DataCubeMultidimensionalGrid.tsx +3 -1
- package/src/index.tsx +3 -0
- package/src/stores/DataCubeAPI.ts +3 -1
- package/src/stores/core/DataCubeEngine.tsx +1 -1
- package/src/stores/core/DataCubeQueryEngine.ts +6 -0
- package/src/stores/core/DataCubeSnapshot.ts +1 -1
- package/src/stores/core/model/AdhocQueryDataCubeSource.ts +3 -0
- package/src/stores/core/model/DataCubeConfiguration.ts +31 -0
- package/src/stores/services/DataCubeSettingService.tsx +10 -6
- package/src/stores/view/DataCubeInfoState.ts +4 -0
- package/src/stores/view/editor/DataCubeEditorColumnsPanelState.ts +13 -13
- package/src/stores/view/editor/{DataCubeEditorColumnSelectorState.ts → DataCubeEditorColumnsSelectorState.ts} +6 -6
- package/src/stores/view/editor/DataCubeEditorDimensionsPanelState.ts +162 -58
- package/src/stores/view/editor/DataCubeEditorHorizontalPivotsPanelState.ts +12 -11
- package/src/stores/view/editor/DataCubeEditorMutableConfiguration.ts +8 -0
- package/src/stores/view/editor/DataCubeEditorSortsPanelState.ts +10 -10
- package/src/stores/view/editor/DataCubeEditorState.tsx +6 -0
- package/src/stores/view/editor/DataCubeEditorVerticalPivotsPanelState.ts +11 -11
- package/src/stores/view/extend/DataCubeColumnEditorState.tsx +16 -26
- package/src/stores/view/grid/DataCubeGridClientEngine.ts +8 -0
- package/src/stores/view/grid/DataCubeGridClientExportEngine.ts +1 -1
- package/src/stores/view/grid/DataCubeGridMenuBuilder.tsx +26 -1
- package/src/stores/view/grid/DataCubeGridState.ts +23 -6
- package/tsconfig.json +4 -3
- package/lib/components/view/editor/DataCubeEditorColumnSelector.d.ts +0 -38
- package/lib/components/view/editor/DataCubeEditorColumnSelector.d.ts.map +0 -1
- package/lib/components/view/editor/DataCubeEditorColumnSelector.js.map +0 -1
- package/lib/components/view/grid/DataCubeGridShared.d.ts.map +0 -1
- package/lib/components/view/grid/DataCubeGridShared.js +0 -25
- package/lib/components/view/grid/DataCubeGridShared.js.map +0 -1
- package/lib/stores/view/editor/DataCubeEditorColumnSelectorState.d.ts.map +0 -1
- package/lib/stores/view/editor/DataCubeEditorColumnSelectorState.js.map +0 -1
- package/src/components/view/grid/DataCubeGridShared.tsx +0 -42
|
@@ -15,297 +15,740 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
import { observer } from 'mobx-react-lite';
|
|
18
|
-
import { DataCubeIcon } from '@finos/legend-art';
|
|
18
|
+
import { cn, DataCubeIcon } from '@finos/legend-art';
|
|
19
19
|
import { AllCommunityModule, } from 'ag-grid-community';
|
|
20
|
-
import
|
|
20
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
21
21
|
import { AgGridReact, } from 'ag-grid-react';
|
|
22
|
-
import {} from '
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
22
|
+
import { filterByType, isNonNullable } from '@finos/legend-shared';
|
|
23
|
+
import { getAllNodes, getDataForAllFilteredNodes, } from '../../../stores/view/grid/DataCubeGridClientEngine.js';
|
|
24
|
+
import { FormAlert, FormBadge_WIP, FormCheckbox, } from '../../core/DataCubeFormUtils.js';
|
|
25
|
+
import { DataCubeGridMode } from '../../../stores/core/DataCubeQueryEngine.js';
|
|
26
|
+
import { DataCubeEditorColumnsSelectorColumnState } from '../../../stores/view/editor/DataCubeEditorColumnsSelectorState.js';
|
|
27
|
+
import { getColumnsSelectorBaseGridProps, INTERNAL__EDITOR_COLUMNS_SELECTOR_ROW_HEIGHT, } from './DataCubeEditorColumnsSelector.js';
|
|
28
|
+
import { DataCubeEditorDimensionState, } from '../../../stores/view/editor/DataCubeEditorDimensionsPanelState.js';
|
|
29
|
+
import { TreeDataModule } from 'ag-grid-enterprise';
|
|
30
|
+
import { _findCol } from '../../../stores/core/model/DataCubeColumn.js';
|
|
31
|
+
import { AlertType } from '../../../stores/services/DataCubeAlertService.js';
|
|
32
|
+
import { DEFAULT_ALERT_WINDOW_CONFIG } from '../../../stores/services/DataCubeLayoutService.js';
|
|
33
|
+
// NOTE: This is a workaround to prevent ag-grid license key check from flooding the console screen
|
|
34
|
+
// with its stack trace in Chrome.
|
|
35
|
+
// We MUST NEVER completely surpress this warning in production, else it's a violation of the ag-grid license!
|
|
36
|
+
// See https://www.ag-grid.com/react-data-grid/licensing/
|
|
37
|
+
const __INTERNAL__original_console_error = console.error; // eslint-disable-line no-console
|
|
38
|
+
/**
|
|
39
|
+
* Move this display to a separate component to avoid re-rendering the header too frequently
|
|
40
|
+
*/
|
|
41
|
+
const AvailableColumnsSearchResultCountBadge = observer((props) => {
|
|
42
|
+
const { panel, gridApi } = props;
|
|
43
|
+
return (_jsxs("div", { className: "flex items-center justify-center rounded-lg bg-neutral-500 px-1 py-0.5 font-mono text-xs font-bold text-white", children: [`${getDataForAllFilteredNodes(gridApi).length}/${panel.availableColumnsForDisplay.length}`, _jsx("span", { className: "hidden", children: panel.availableColumnsSearchText })] }));
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* Move this display to a separate component to avoid re-rendering the header too frequently
|
|
47
|
+
*/
|
|
48
|
+
const DimensionsTreeSearchResultCountBadge = observer((props) => {
|
|
49
|
+
const { panel, gridApi } = props;
|
|
50
|
+
return (_jsxs("div", { className: "flex items-center justify-center rounded-lg bg-neutral-500 px-1 py-0.5 font-mono text-xs font-bold text-white", children: [`${getDataForAllFilteredNodes(gridApi)
|
|
51
|
+
.map((node) => node.data)
|
|
52
|
+
.filter((node) => node instanceof DataCubeEditorDimensionState)
|
|
53
|
+
.length}/${panel.dimensions.length}`, _jsx("span", { className: "hidden", children: panel.dimensionsTreeSearchText })] }));
|
|
54
|
+
});
|
|
55
|
+
/**
|
|
56
|
+
* Move this display to a separate component to avoid re-rendering too frequently
|
|
57
|
+
*/
|
|
58
|
+
const DimensionLabel = observer((props) => {
|
|
59
|
+
const { panel, dimension, gridApi } = props;
|
|
60
|
+
const nameInputRef = useRef(null);
|
|
61
|
+
const [name, setName] = useState(dimension.name);
|
|
62
|
+
const validationError = name.trim() === ''
|
|
63
|
+
? `Name is required`
|
|
64
|
+
: Boolean(panel.dimensions
|
|
65
|
+
.filter((dim) => dim.name !== dimension.name)
|
|
66
|
+
.find((dim) => dim.name === name))
|
|
67
|
+
? `Name must be unique`
|
|
68
|
+
: undefined;
|
|
69
|
+
const isNameValid = !validationError;
|
|
70
|
+
const updateName = () => {
|
|
71
|
+
if (!isNameValid) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
dimension.setName(name);
|
|
75
|
+
dimension.setIsRenaming(false);
|
|
76
|
+
gridApi.clearFocusedCell();
|
|
77
|
+
};
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
setName(dimension.name);
|
|
80
|
+
}, [dimension.name]);
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
if (dimension.isRenaming) {
|
|
83
|
+
nameInputRef.current?.focus();
|
|
84
|
+
}
|
|
85
|
+
}, [dimension.isRenaming]);
|
|
86
|
+
return (_jsxs("div", { className: "flex h-full w-full items-center pl-1", title: `[Dimension: ${dimension.name}]\nDouble-click to remove all columns`, children: [_jsx("div", { className: "text-2xs flex h-3 flex-shrink-0 items-center justify-center rounded-sm bg-neutral-500 px-1 font-bold text-white", children: "DIM" }), !dimension.isRenaming && (_jsx("div", { className: "h-full flex-1 cursor-pointer items-center overflow-hidden overflow-ellipsis whitespace-nowrap pl-1", title: "Double-click to remove dimension",
|
|
87
|
+
/**
|
|
88
|
+
* ag-grid row select event listener is at a deeper layer so we need to stop
|
|
89
|
+
* the propagation as event capturing is happening, not when it's bubbling.
|
|
90
|
+
*/
|
|
91
|
+
onDoubleClickCapture: (event) => {
|
|
92
|
+
event.stopPropagation();
|
|
93
|
+
dimension.setIsRenaming(true);
|
|
94
|
+
gridApi.clearFocusedCell();
|
|
95
|
+
}, children: dimension.name })), dimension.isRenaming && (_jsxs("div", { className: "relative flex items-center",
|
|
96
|
+
/**
|
|
97
|
+
* ag-grid row select event listener is at a deeper layer so we need to stop
|
|
98
|
+
* the propagation as event capturing is happening, not when it's bubbling.
|
|
99
|
+
*/
|
|
100
|
+
onDoubleClickCapture: (event) => {
|
|
101
|
+
event.stopPropagation();
|
|
102
|
+
gridApi.clearFocusedCell();
|
|
103
|
+
}, children: [_jsx("input", { ref: nameInputRef, className: cn('ml-0.5 h-4 border border-neutral-300 pl-[1px] pr-6 focus:border-sky-600 focus:!outline-none', {
|
|
104
|
+
'border-red-600 focus:border-red-600': !isNameValid,
|
|
105
|
+
}), value: name, onChange: (event) => {
|
|
106
|
+
setName(event.target.value);
|
|
107
|
+
}, onKeyDown: (event) => {
|
|
108
|
+
if (event.code === 'Escape') {
|
|
109
|
+
nameInputRef.current?.focus();
|
|
110
|
+
nameInputRef.current?.select();
|
|
111
|
+
}
|
|
112
|
+
}, onKeyDownCapture: (event) => {
|
|
113
|
+
if (event.code === 'Enter') {
|
|
114
|
+
event.stopPropagation();
|
|
115
|
+
updateName();
|
|
116
|
+
}
|
|
117
|
+
}, onBlur: () => {
|
|
118
|
+
dimension.setIsRenaming(false);
|
|
119
|
+
setName(dimension.name);
|
|
120
|
+
} }), isNameValid && (_jsx("button", { className: "text-2xs absolute right-0.5 flex h-3 w-5 items-center justify-center rounded-sm bg-sky-600 text-white", onClick: (event) => {
|
|
121
|
+
event.stopPropagation();
|
|
122
|
+
updateName();
|
|
123
|
+
}, children: "Save" }))] }))] }));
|
|
124
|
+
});
|
|
125
|
+
function confirmPopulateStubDimensionWhenAddingColumns(view, handler) {
|
|
126
|
+
view.alertService.alert({
|
|
127
|
+
message: `No target dimensions to add columns to`,
|
|
128
|
+
text: `Columns need to be added to a dimension, but no dimension has been specified.\nDo you want to proceed with creating a new dimension and add the columns to it?`,
|
|
129
|
+
type: AlertType.WARNING,
|
|
130
|
+
actions: [
|
|
131
|
+
{
|
|
132
|
+
label: 'Proceed',
|
|
133
|
+
handler,
|
|
50
134
|
},
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (params.api.getQuickFilter()) {
|
|
61
|
-
return (_jsxs("div", { className: "flex items-center border-[1.5px] border-neutral-300 p-2 font-semibold text-neutral-400", children: [_jsx("div", { children: _jsx(DataCubeIcon.WarningCircle, { className: "mr-1 text-lg" }) }), "No match found"] }));
|
|
62
|
-
}
|
|
63
|
-
if (params.noColumnsSelectedRenderer) {
|
|
64
|
-
return params.noColumnsSelectedRenderer();
|
|
65
|
-
}
|
|
66
|
-
return _jsx("div", {});
|
|
67
|
-
},
|
|
68
|
-
// Show no rows overlay when there are no search results
|
|
69
|
-
// See https://stackoverflow.com/a/72637410
|
|
70
|
-
onModelUpdated: (event) => {
|
|
71
|
-
if (event.api.getDisplayedRowCount() === 0) {
|
|
72
|
-
event.api.showNoRowsOverlay();
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
event.api.hideOverlay();
|
|
76
|
-
}
|
|
135
|
+
{
|
|
136
|
+
label: 'Cancel',
|
|
137
|
+
handler: () => { },
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
windowConfig: {
|
|
141
|
+
...DEFAULT_ALERT_WINDOW_CONFIG,
|
|
142
|
+
width: 550,
|
|
143
|
+
height: 180,
|
|
77
144
|
},
|
|
78
|
-
};
|
|
145
|
+
});
|
|
79
146
|
}
|
|
80
|
-
function
|
|
147
|
+
function computeDragOverNode(event) {
|
|
148
|
+
let overIndex = event.overIndex === -1 ? undefined : event.overIndex;
|
|
149
|
+
// if the drag point passes the middle of the row, we consider
|
|
150
|
+
// the spot to be the one before the row
|
|
151
|
+
if (overIndex !== undefined &&
|
|
152
|
+
event.y % INTERNAL__EDITOR_COLUMNS_SELECTOR_ROW_HEIGHT <
|
|
153
|
+
INTERNAL__EDITOR_COLUMNS_SELECTOR_ROW_HEIGHT / 2) {
|
|
154
|
+
overIndex -= 1;
|
|
155
|
+
}
|
|
81
156
|
return {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
filter: true,
|
|
87
|
-
sortable: false,
|
|
88
|
-
resizable: false,
|
|
89
|
-
suppressHeaderMenuButton: true,
|
|
90
|
-
getQuickFilterText: (params) => params.value,
|
|
157
|
+
overIndex,
|
|
158
|
+
overNode: (overIndex !== undefined
|
|
159
|
+
? getAllNodes(event.api).at(overIndex === -1 ? 0 : overIndex)
|
|
160
|
+
: undefined),
|
|
91
161
|
};
|
|
92
162
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
? // subscribing to the search text to trigger re-render as it changes
|
|
100
|
-
selector.availableColumnsSearchText
|
|
101
|
-
: selector.selectedColumnsSearchText })] }));
|
|
102
|
-
});
|
|
103
|
-
export const DataCubeEditorColumnSelector = observer(function DataCubeEditorColumnSelector(props) {
|
|
104
|
-
const { selector, columnLabelRenderer, columnActionRenderer, noColumnsSelectedRenderer, } = props;
|
|
163
|
+
export const DataCubeEditorDimensionsPanel = observer((props) => {
|
|
164
|
+
const { view } = props;
|
|
165
|
+
const editor = view.editor;
|
|
166
|
+
const panel = editor.dimensions;
|
|
167
|
+
const searchAvailableColumnsInputRef = useRef(null);
|
|
168
|
+
const searchDimensionsTreeInputRef = useRef(null);
|
|
105
169
|
const [selectedAvailableColumns, setSelectedAvailableColumns] = useState([]);
|
|
106
170
|
const [selectedSelectedColumns, setSelectedSelectedColumns] = useState([]);
|
|
171
|
+
const [selectedDimensions, setSelectedDimensions] = useState([]);
|
|
107
172
|
const [availableColumnsGridApi, setAvailableColumnsGridApi] = useState(null);
|
|
108
|
-
const [
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
173
|
+
const [dimensionsTreeGridApi, setDimensionsTreeGridApi] = useState(null);
|
|
174
|
+
const onAvailableColumnsExternalDragStop = useCallback((params) => {
|
|
175
|
+
// NOTE: here, we do not scope the columns being moved by the search
|
|
176
|
+
// this is a complicated behavior to implement and it's not clear if
|
|
177
|
+
// it's necessary, the current behavior is sensible in its own way.
|
|
178
|
+
const columnsToMove = params.nodes
|
|
179
|
+
.map((node) => node.data?.data)
|
|
180
|
+
.filter(filterByType(DataCubeEditorColumnsSelectorColumnState));
|
|
181
|
+
panel.deselectColumns(columnsToMove);
|
|
182
|
+
panel.refreshDimensionsTreeData();
|
|
183
|
+
}, [panel]);
|
|
184
|
+
const onDimensionsTreeExternalDragStop = useCallback((event) => {
|
|
185
|
+
const { overNode } = computeDragOverNode(event);
|
|
186
|
+
// NOTE: here, we do not scope the columns being moved by the search
|
|
187
|
+
// this is a complicated behavior to implement and it's not clear if
|
|
188
|
+
// it's necessary, the current behavior is sensible in its own way.
|
|
189
|
+
const columnsToMove = event.nodes
|
|
123
190
|
.map((node) => node.data)
|
|
124
191
|
.filter(isNonNullable);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
192
|
+
const dimension = (!overNode?.data
|
|
193
|
+
? undefined
|
|
194
|
+
: overNode.data.data instanceof DataCubeEditorDimensionState
|
|
195
|
+
? overNode.data.data
|
|
196
|
+
: overNode.parent?.data?.data instanceof
|
|
197
|
+
DataCubeEditorDimensionState
|
|
198
|
+
? overNode.parent.data.data
|
|
199
|
+
: undefined) ?? panel.dimensions.at(-1);
|
|
200
|
+
if (dimension) {
|
|
201
|
+
// dropping position will be honored and affect columns
|
|
202
|
+
// ordering within the dimension accordingly
|
|
203
|
+
const colIdx = overNode?.data?.data instanceof
|
|
204
|
+
DataCubeEditorColumnsSelectorColumnState
|
|
205
|
+
? dimension.columns.indexOf(overNode.data.data)
|
|
206
|
+
: overNode?.data?.data instanceof DataCubeEditorDimensionState
|
|
207
|
+
? -1
|
|
208
|
+
: undefined;
|
|
209
|
+
dimension.setColumns(colIdx !== undefined
|
|
210
|
+
? [
|
|
211
|
+
...dimension.columns.slice(0, colIdx + 1),
|
|
212
|
+
...columnsToMove,
|
|
213
|
+
...dimension.columns.slice(colIdx + 1),
|
|
214
|
+
]
|
|
215
|
+
: [...dimension.columns, ...columnsToMove]);
|
|
216
|
+
panel.refreshDimensionsTreeData();
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
confirmPopulateStubDimensionWhenAddingColumns(view, () => {
|
|
220
|
+
const newDimension = panel.newDimension();
|
|
221
|
+
newDimension.setColumns([...columnsToMove]);
|
|
222
|
+
panel.refreshDimensionsTreeData();
|
|
223
|
+
});
|
|
136
224
|
}
|
|
137
|
-
|
|
138
|
-
}, [selector]);
|
|
225
|
+
}, [panel, view]);
|
|
139
226
|
/**
|
|
140
|
-
* Setup
|
|
227
|
+
* Setup drop zones for each grid to allow moving columns between them
|
|
141
228
|
* See https://www.ag-grid.com/react-data-grid/row-dragging-to-grid/
|
|
142
229
|
*/
|
|
143
230
|
useEffect(() => {
|
|
144
|
-
if (!availableColumnsGridApi || !
|
|
231
|
+
if (!availableColumnsGridApi || !dimensionsTreeGridApi) {
|
|
145
232
|
return;
|
|
146
233
|
}
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
234
|
+
const dimensionstreeDropZoneParams = !dimensionsTreeGridApi.isDestroyed()
|
|
235
|
+
? dimensionsTreeGridApi.getRowDropZoneParams({
|
|
236
|
+
onDragStop: (event) => {
|
|
237
|
+
onDimensionsTreeExternalDragStop(event);
|
|
238
|
+
availableColumnsGridApi.clearFocusedCell();
|
|
239
|
+
},
|
|
240
|
+
})
|
|
241
|
+
: undefined;
|
|
242
|
+
if (dimensionstreeDropZoneParams &&
|
|
243
|
+
!availableColumnsGridApi.isDestroyed()) {
|
|
244
|
+
availableColumnsGridApi.addRowDropZone(dimensionstreeDropZoneParams);
|
|
156
245
|
}
|
|
157
|
-
const availableColumnsDropZoneParams = availableColumnsGridApi.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
246
|
+
const availableColumnsDropZoneParams = !availableColumnsGridApi.isDestroyed()
|
|
247
|
+
? availableColumnsGridApi.getRowDropZoneParams({
|
|
248
|
+
onDragStop: (event) => {
|
|
249
|
+
onAvailableColumnsExternalDragStop(event);
|
|
250
|
+
dimensionsTreeGridApi.clearFocusedCell();
|
|
251
|
+
},
|
|
252
|
+
})
|
|
253
|
+
: undefined;
|
|
254
|
+
if (availableColumnsDropZoneParams &&
|
|
255
|
+
!dimensionsTreeGridApi.isDestroyed()) {
|
|
256
|
+
dimensionsTreeGridApi.addRowDropZone(availableColumnsDropZoneParams);
|
|
166
257
|
}
|
|
167
258
|
}, [
|
|
168
259
|
availableColumnsGridApi,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
260
|
+
dimensionsTreeGridApi,
|
|
261
|
+
onDimensionsTreeExternalDragStop,
|
|
262
|
+
onAvailableColumnsExternalDragStop,
|
|
172
263
|
]);
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
264
|
+
const [dimensionsTreeOnHoverIndex, setDimensionsTreeOnHoverIndex] = useState(undefined);
|
|
265
|
+
// This event will be triggered when user drops any node on the dimensions tree,
|
|
266
|
+
// regardless of the source, i.e. this includes columns from available columns grid
|
|
267
|
+
// so we have to guard against that case because the logic should already been handled
|
|
268
|
+
// by the drag stop hook in the external drop zone config for dimensions tree.
|
|
269
|
+
const isDimensionsTreeRowDragEnabled = selectedDimensions.length === 0 || selectedSelectedColumns.length === 0;
|
|
270
|
+
const onDimensionsTreeRowDragEnd = useCallback((event) => {
|
|
271
|
+
const { overIndex, overNode } = computeDragOverNode(event);
|
|
272
|
+
setDimensionsTreeOnHoverIndex(undefined);
|
|
273
|
+
// NOTE: here, we do not scope the columns being moved by the search
|
|
274
|
+
// this is a complicated behavior to implement and it's not clear if
|
|
275
|
+
// it's necessary, the current behavior is sensible in its own way.
|
|
276
|
+
const dragEntities = event.nodes
|
|
277
|
+
.map((node) =>
|
|
278
|
+
// this assertion is valid because we also need to handle columns being dragged from external sources
|
|
279
|
+
node.data)
|
|
280
|
+
.filter((data) => !(data instanceof DataCubeEditorDimensionState));
|
|
281
|
+
// we guard against DnD from the available columns grid to the dimensions tree
|
|
282
|
+
if (dragEntities.length === 0) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
const dragColumns = [];
|
|
286
|
+
const dragDimensions = [];
|
|
287
|
+
dragEntities.forEach((node) => {
|
|
288
|
+
if (node.data instanceof DataCubeEditorDimensionState) {
|
|
289
|
+
dragDimensions.push(node.data);
|
|
290
|
+
}
|
|
291
|
+
else if (node.data instanceof DataCubeEditorColumnsSelectorColumnState) {
|
|
292
|
+
dragColumns.push(node.data);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
if (dragColumns.length > 0 && dragDimensions.length > 0) {
|
|
296
|
+
// we don't support DnD for a mixture of columns and dimensions
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
// moving dimensions
|
|
300
|
+
if (dragDimensions.length > 0) {
|
|
301
|
+
// dropping position will be honored and affect dimensions ordering
|
|
302
|
+
let dimensionIdx = undefined;
|
|
303
|
+
if (overIndex === -1) {
|
|
304
|
+
dimensionIdx = -1;
|
|
305
|
+
}
|
|
306
|
+
else if (overNode !== undefined) {
|
|
307
|
+
const dimension = !overNode.data
|
|
308
|
+
? undefined
|
|
309
|
+
: overNode.data.data instanceof DataCubeEditorDimensionState
|
|
310
|
+
? overNode.data.data
|
|
311
|
+
: overNode.parent?.data?.data instanceof
|
|
312
|
+
DataCubeEditorDimensionState
|
|
313
|
+
? overNode.parent.data.data
|
|
314
|
+
: undefined;
|
|
315
|
+
if (dimension) {
|
|
316
|
+
const _idx = panel.dimensions.indexOf(dimension);
|
|
317
|
+
// when compute the move position, account for dimensions which will be moved out
|
|
318
|
+
// these would shift the move position up.
|
|
319
|
+
dimensionIdx =
|
|
320
|
+
_idx === -1
|
|
321
|
+
? -1
|
|
322
|
+
: _idx -
|
|
323
|
+
panel.dimensions
|
|
324
|
+
.slice(0, _idx + 1)
|
|
325
|
+
.filter((dim) => dragDimensions.find((_dim) => dim.name === _dim.name)).length;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
const dimensions = panel.dimensions.filter((dim) => !dragDimensions.find((_dim) => dim.name === _dim.name));
|
|
329
|
+
panel.setDimensions(dimensionIdx !== undefined
|
|
330
|
+
? [
|
|
331
|
+
...dimensions.slice(0, dimensionIdx + 1),
|
|
332
|
+
...dragDimensions,
|
|
333
|
+
...dimensions.slice(dimensionIdx + 1),
|
|
334
|
+
]
|
|
335
|
+
: [...dimensions, ...dragDimensions]);
|
|
336
|
+
panel.refreshDimensionsTreeData();
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
// moving columns
|
|
340
|
+
if (dragColumns.length > 0) {
|
|
341
|
+
const dimension = (!overNode?.data
|
|
342
|
+
? undefined
|
|
343
|
+
: overNode.data.data instanceof DataCubeEditorDimensionState
|
|
344
|
+
? overNode.data.data
|
|
345
|
+
: overNode.parent?.data?.data instanceof
|
|
346
|
+
DataCubeEditorDimensionState
|
|
347
|
+
? overNode.parent.data.data
|
|
348
|
+
: undefined) ?? panel.dimensions.at(-1);
|
|
349
|
+
if (dimension) {
|
|
350
|
+
// dropping position will be honored and affect columns
|
|
351
|
+
// ordering within the dimension accordingly
|
|
352
|
+
let colIdx = undefined;
|
|
353
|
+
if (overNode?.data?.data instanceof DataCubeEditorDimensionState) {
|
|
354
|
+
colIdx = -1;
|
|
355
|
+
}
|
|
356
|
+
else if (overNode?.data?.data instanceof
|
|
357
|
+
DataCubeEditorColumnsSelectorColumnState) {
|
|
358
|
+
const _idx = dimension.columns.indexOf(overNode.data.data);
|
|
359
|
+
// when compute the move position, account for columns which will be moved out
|
|
360
|
+
// these would shift the move position up.
|
|
361
|
+
colIdx =
|
|
362
|
+
_idx === -1
|
|
363
|
+
? -1
|
|
364
|
+
: _idx -
|
|
365
|
+
dimension.columns
|
|
366
|
+
.slice(0, _idx + 1)
|
|
367
|
+
.filter((col) => _findCol(dragColumns, col.name)).length;
|
|
368
|
+
}
|
|
369
|
+
panel.deselectColumns(dragColumns);
|
|
370
|
+
dimension.setColumns(colIdx !== undefined
|
|
371
|
+
? [
|
|
372
|
+
...dimension.columns.slice(0, colIdx + 1),
|
|
373
|
+
...dragColumns,
|
|
374
|
+
...dimension.columns.slice(colIdx + 1),
|
|
375
|
+
]
|
|
376
|
+
: [...dimension.columns, ...dragColumns]);
|
|
377
|
+
panel.refreshDimensionsTreeData();
|
|
378
|
+
}
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
}, [panel]);
|
|
382
|
+
const onDimensionsTreeRowDragMove = useCallback((event) => {
|
|
383
|
+
const { overIndex, overNode } = computeDragOverNode(event);
|
|
384
|
+
setDimensionsTreeOnHoverIndex(overIndex);
|
|
385
|
+
event.api.refreshCells({
|
|
386
|
+
rowNodes: overNode ? [overNode] : [],
|
|
387
|
+
force: true, // since no data change is happening, we need to force refresh
|
|
388
|
+
});
|
|
389
|
+
}, []);
|
|
390
|
+
const onDimensionsTreeRowDragCancel = useCallback((event) => {
|
|
391
|
+
setDimensionsTreeOnHoverIndex(undefined);
|
|
392
|
+
}, []);
|
|
393
|
+
const onDimensionsTreeRowDragLeave = useCallback((event) => {
|
|
394
|
+
setDimensionsTreeOnHoverIndex(undefined);
|
|
395
|
+
}, []);
|
|
396
|
+
useEffect(() => {
|
|
397
|
+
// on load, reset all renaming state for all dimensions
|
|
398
|
+
panel.dimensions.forEach((dimension) => dimension.setIsRenaming(false));
|
|
399
|
+
// reset transient grid states
|
|
400
|
+
setDimensionsTreeOnHoverIndex(undefined);
|
|
401
|
+
}, [panel]);
|
|
402
|
+
// eslint-disable-next-line no-process-env
|
|
403
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
404
|
+
// eslint-disable-next-line no-console
|
|
405
|
+
console.error = (message, ...agrs) => {
|
|
406
|
+
console.debug(`%c ${message}`, 'color: silver'); // eslint-disable-line no-console
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
return (_jsxs("div", { className: "h-full w-full select-none p-2", children: [_jsxs("div", { className: "flex h-6", children: [_jsx("div", { className: "flex h-6 items-center text-xl font-medium", children: _jsx(DataCubeIcon.TableDimension, {}) }), _jsxs("div", { className: "ml-1 flex h-6 items-center text-xl font-medium", children: ["Dimensions", _jsx(FormBadge_WIP, {})] })] }), _jsxs("div", { className: "h-[calc(100%_-_24px)] w-full", children: [_jsx("div", { className: "h-10 py-2", children: _jsx("div", { className: "flex h-6 w-full items-center", children: _jsx(FormCheckbox, { label: "Enable multidimensional grid mode", checked: editor.generalProperties.configuration.gridMode ===
|
|
410
|
+
DataCubeGridMode.MULTIDIMENSIONAL, onChange: () => {
|
|
411
|
+
if (editor.generalProperties.configuration.gridMode ===
|
|
412
|
+
DataCubeGridMode.MULTIDIMENSIONAL) {
|
|
413
|
+
editor.generalProperties.configuration.setGridMode(DataCubeGridMode.STANDARD);
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
if (
|
|
417
|
+
// only suggest converting vertical pivots if no dimensions have been specified
|
|
418
|
+
editor.verticalPivots.selector.selectedColumns.length !==
|
|
419
|
+
0 &&
|
|
420
|
+
panel.dimensions.length === 0) {
|
|
421
|
+
view.alertService.alert({
|
|
422
|
+
message: `Specified vertical pivots will be ignored in multidimensional grid mode.`,
|
|
423
|
+
text: `Multidimensional grid mode will ignore any specified vertical pivots, essentially, vertical pivot columns can be considered as one dimension.\nFor convenience, these vertical pivots can be converted into a dimension, do you want this conversion to happen?`,
|
|
424
|
+
type: AlertType.WARNING,
|
|
425
|
+
actions: [
|
|
426
|
+
{
|
|
427
|
+
label: 'Yes',
|
|
428
|
+
handler: () => {
|
|
429
|
+
const groupByColumns = editor.verticalPivots.selector.selectedColumns;
|
|
430
|
+
const newDimension = panel.newDimension();
|
|
431
|
+
newDimension.setColumns(panel.availableColumns.filter((column) => _findCol(groupByColumns, column.name)));
|
|
432
|
+
editor.verticalPivots.selector.setSelectedColumns([]);
|
|
433
|
+
panel.refreshDimensionsTreeData();
|
|
434
|
+
editor.generalProperties.configuration.setGridMode(DataCubeGridMode.MULTIDIMENSIONAL);
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
label: 'No',
|
|
439
|
+
handler: () => {
|
|
440
|
+
editor.generalProperties.configuration.setGridMode(DataCubeGridMode.MULTIDIMENSIONAL);
|
|
441
|
+
},
|
|
442
|
+
},
|
|
443
|
+
],
|
|
444
|
+
windowConfig: {
|
|
445
|
+
...DEFAULT_ALERT_WINDOW_CONFIG,
|
|
446
|
+
width: 550,
|
|
447
|
+
height: 220,
|
|
448
|
+
},
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
editor.generalProperties.configuration.setGridMode(DataCubeGridMode.MULTIDIMENSIONAL);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
} }) }) }), editor.generalProperties.configuration.gridMode !==
|
|
456
|
+
DataCubeGridMode.MULTIDIMENSIONAL && (_jsx(FormAlert, { message: "Multidimensional grid mode is experimental", type: AlertType.WARNING, text: `This is an alternative grid view for DataCube with a different mode of interaction: dimensions (ordered list of columns to group by) are defined and will be used to explore data "top-down". Initially, the grid will show the root aggregation, then user can drill down into each dimension. This grid mode comes with the following limitations:
|
|
457
|
+
- Specified vertical pivots will be ignored: essentially, vertical pivot can be considered as one dimension in this mode
|
|
458
|
+
- No support for pagination
|
|
459
|
+
- Initial view can take longer to materialize if drilldown is deep` })), editor.generalProperties.configuration.gridMode ===
|
|
460
|
+
DataCubeGridMode.MULTIDIMENSIONAL && (_jsx("div", { className: "flex h-[calc(100%_-_40px)] w-full", children: _jsxs("div", { className: "data-cube-column-selector flex h-full w-full", children: [_jsxs("div", { className: "h-full w-[calc(50%_-_20px)]", children: [_jsx("div", { className: "flex h-5 items-center text-sm", children: "Available columns:" }), _jsxs("div", { className: "h-[calc(100%_-_20px)] rounded-sm border border-neutral-200", children: [_jsxs("div", { className: "relative h-6 border-b border-neutral-200", children: [_jsx("input", { className: "h-full w-full pl-10 pr-6 placeholder-neutral-400", ref: searchAvailableColumnsInputRef, placeholder: "Search columns...", value: panel.availableColumnsSearchText, onChange: (event) => panel.setAvailableColumnsSearchText(event.target.value), onKeyDown: (event) => {
|
|
461
|
+
if (event.code === 'Escape') {
|
|
462
|
+
event.stopPropagation();
|
|
463
|
+
searchAvailableColumnsInputRef.current?.select();
|
|
464
|
+
panel.setAvailableColumnsSearchText('');
|
|
465
|
+
}
|
|
466
|
+
} }), _jsx("div", { className: "absolute left-0 top-0 flex h-6 w-10 items-center justify-center", children: _jsx(DataCubeIcon.Search, { className: "stroke-[3px] text-lg text-neutral-500" }) }), _jsx("button", { className: "absolute right-0 top-0 flex h-6 w-6 items-center justify-center text-neutral-500 disabled:text-neutral-300", disabled: !panel.availableColumnsSearchText, title: "Clear search [Esc]", onClick: () => {
|
|
467
|
+
panel.setAvailableColumnsSearchText('');
|
|
468
|
+
searchAvailableColumnsInputRef.current?.focus();
|
|
469
|
+
}, children: _jsx(DataCubeIcon.X, { className: "text-lg" }) })] }), _jsx("div", { className: "h-[calc(100%_-_24px)]", children: _jsx(AgGridReact, { ...getColumnsSelectorBaseGridProps(),
|
|
470
|
+
// Disable managed row-dragging to disallow changing the order of columns
|
|
471
|
+
// and to make sure the row data and the available columns state are in sync
|
|
472
|
+
rowDragManaged: false, onGridReady: (params) => setAvailableColumnsGridApi(params.api), onSelectionChanged: (event) => {
|
|
473
|
+
setSelectedAvailableColumns(event.api
|
|
474
|
+
.getSelectedNodes()
|
|
475
|
+
.map((node) => node.data)
|
|
476
|
+
.filter(isNonNullable));
|
|
477
|
+
},
|
|
478
|
+
// Using ag-grid quick filter is a cheap way to implement search
|
|
479
|
+
quickFilterText: panel.availableColumnsSearchText, rowData: panel.availableColumnsForDisplay, rowClass: "border-t border-b border-1 border-transparent", columnDefs: [
|
|
480
|
+
{
|
|
481
|
+
field: 'name',
|
|
482
|
+
colId: 'name',
|
|
483
|
+
flex: 1,
|
|
484
|
+
minWidth: 100,
|
|
485
|
+
filter: true,
|
|
486
|
+
sortable: false,
|
|
487
|
+
resizable: false,
|
|
488
|
+
suppressHeaderMenuButton: true,
|
|
489
|
+
getQuickFilterText: (params) => params.value,
|
|
490
|
+
/**
|
|
491
|
+
* Support double-click to add all (filtered by search) columns
|
|
492
|
+
*/
|
|
493
|
+
headerComponent: (params) => (_jsxs("button", { title: "Double-click to add all columns", className: "flex h-full w-full items-center justify-between pl-0.5", onDoubleClick: () => {
|
|
494
|
+
// The columns being moved are scoped by the current search
|
|
495
|
+
const filteredNodes = getDataForAllFilteredNodes(params.api);
|
|
496
|
+
const dimension = panel.dimensions.at(-1);
|
|
497
|
+
if (dimension) {
|
|
498
|
+
dimension.setColumns([
|
|
499
|
+
...dimension.columns,
|
|
500
|
+
...filteredNodes,
|
|
501
|
+
]);
|
|
502
|
+
panel.refreshDimensionsTreeData();
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
confirmPopulateStubDimensionWhenAddingColumns(view, () => {
|
|
506
|
+
const newDimension = panel.newDimension();
|
|
507
|
+
newDimension.setColumns([
|
|
508
|
+
...filteredNodes,
|
|
509
|
+
]);
|
|
510
|
+
panel.refreshDimensionsTreeData();
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
params.api.clearFocusedCell();
|
|
514
|
+
}, children: [_jsx("div", { children: `[All Columns]` }), _jsx(AvailableColumnsSearchResultCountBadge, { panel: panel, gridApi: params.api })] })),
|
|
515
|
+
cellRenderer: (params) => {
|
|
516
|
+
const data = params.data;
|
|
517
|
+
if (!data) {
|
|
518
|
+
return null;
|
|
519
|
+
}
|
|
520
|
+
return (_jsx("div", { className: "flex h-full w-full cursor-pointer items-center", title: `[${data.name}]\nDouble-click to add column`, onDoubleClick: () => {
|
|
521
|
+
const dimension = panel.dimensions.at(-1);
|
|
522
|
+
if (dimension) {
|
|
523
|
+
dimension.setColumns([
|
|
524
|
+
...dimension.columns,
|
|
525
|
+
data,
|
|
526
|
+
]);
|
|
527
|
+
panel.refreshDimensionsTreeData();
|
|
528
|
+
}
|
|
529
|
+
else {
|
|
530
|
+
confirmPopulateStubDimensionWhenAddingColumns(view, () => {
|
|
531
|
+
const newDimension = panel.newDimension();
|
|
532
|
+
newDimension.setColumns([data]);
|
|
533
|
+
panel.refreshDimensionsTreeData();
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
params.api.clearFocusedCell();
|
|
537
|
+
}, children: _jsx("div", { className: "h-full flex-1 items-center overflow-hidden overflow-ellipsis whitespace-nowrap pl-2", children: data.name }) }));
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
] }) })] })] }), _jsx("div", { className: "flex h-full w-10 items-center justify-center", children: _jsxs("div", { className: "flex flex-col", children: [_jsx("button", { className: "flex items-center justify-center rounded-sm border border-neutral-300 bg-neutral-100 text-neutral-500 hover:bg-neutral-200 disabled:bg-neutral-200 disabled:text-neutral-400", title: "Add selected column(s)",
|
|
541
|
+
/**
|
|
542
|
+
* Support add selected (filtered by search) columns
|
|
543
|
+
* We reset the selection after this operation
|
|
544
|
+
*/
|
|
545
|
+
onClick: () => {
|
|
546
|
+
if (!availableColumnsGridApi ||
|
|
547
|
+
selectedAvailableColumns.length === 0) {
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
199
550
|
// The columns being moved are scoped by the current search
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
cellRenderer: (params) => {
|
|
208
|
-
const data = params.data;
|
|
209
|
-
if (!data) {
|
|
210
|
-
return null;
|
|
211
|
-
}
|
|
212
|
-
return (_jsxs("div", { className: "flex h-full w-full cursor-pointer items-center", title: `[${data.name}]\nDouble-click to add column`, onDoubleClick: () => {
|
|
213
|
-
selector.setSelectedColumns([
|
|
214
|
-
...selector.selectedColumns,
|
|
215
|
-
data,
|
|
551
|
+
const filteredNodes = getDataForAllFilteredNodes(availableColumnsGridApi);
|
|
552
|
+
const columnsToMove = selectedAvailableColumns.filter((column) => _findCol(filteredNodes, column.name));
|
|
553
|
+
const dimension = panel.dimensions.at(-1);
|
|
554
|
+
if (dimension) {
|
|
555
|
+
dimension.setColumns([
|
|
556
|
+
...dimension.columns,
|
|
557
|
+
...columnsToMove,
|
|
216
558
|
]);
|
|
217
|
-
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const columnsToMove = selectedAvailableColumns.filter((column) => filteredData.includes(column));
|
|
239
|
-
selector.setSelectedColumns([
|
|
240
|
-
...selector.selectedColumns,
|
|
241
|
-
...columnsToMove,
|
|
242
|
-
]);
|
|
243
|
-
availableColumnsGridApi.clearFocusedCell();
|
|
244
|
-
}, disabled: selectedAvailableColumns.length === 0, children: _jsx(DataCubeIcon.ChevronRight, { className: "text-2xl" }) }), _jsx("button", { className: "mt-2 flex items-center justify-center rounded-sm border border-neutral-300 bg-neutral-100 text-neutral-500 hover:bg-neutral-200 disabled:bg-neutral-200 disabled:text-neutral-400", title: "Remove selected columns",
|
|
245
|
-
/**
|
|
246
|
-
* Support remove selected (filtered by search) columns
|
|
247
|
-
* We reset the selection after this operation
|
|
248
|
-
*/
|
|
249
|
-
onClick: () => {
|
|
250
|
-
if (!selectedColumnsGridApi) {
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
// The columns being moved are scoped by the current search
|
|
254
|
-
const filteredData = getDataForAllFilteredNodes(selectedColumnsGridApi);
|
|
255
|
-
const columnsToMove = selectedSelectedColumns.filter((column) => filteredData.includes(column));
|
|
256
|
-
selector.setSelectedColumns(selector.selectedColumns.filter((column) => !columnsToMove.includes(column)));
|
|
257
|
-
selectedColumnsGridApi.clearFocusedCell();
|
|
258
|
-
}, disabled: selectedSelectedColumns.length === 0, children: _jsx(DataCubeIcon.ChevronLeft, { className: "text-2xl" }) })] }) }), _jsxs("div", { className: "h-full w-[calc(50%_-_20px)]", children: [_jsx("div", { className: "flex h-5 items-center text-sm", children: "Selected columns:" }), _jsxs("div", { className: "h-[calc(100%_-_20px)] rounded-sm border border-neutral-200", children: [_jsxs("div", { className: "relative h-6 border-b border-neutral-200", children: [_jsx("input", { className: "h-full w-full pl-10 placeholder-neutral-400", ref: searchSelectedColumnsInputRef, placeholder: "Click here to search...", value: selector.selectedColumnsSearchText, onChange: (event) => selector.setSelectedColumnsSearchText(event.target.value), onKeyDown: (event) => {
|
|
259
|
-
if (event.code === 'Escape') {
|
|
260
|
-
event.stopPropagation();
|
|
261
|
-
selector.setSelectedColumnsSearchText('');
|
|
262
|
-
}
|
|
263
|
-
} }), _jsx("div", { className: "absolute left-0 top-0 flex h-6 w-10 items-center justify-center", children: _jsx(DataCubeIcon.Search, { className: "stroke-[3px] text-lg text-neutral-500" }) }), _jsx("button", { className: "absolute right-0 top-0 flex h-6 w-6 items-center justify-center text-neutral-500 disabled:text-neutral-300", disabled: !selector.selectedColumnsSearchText, title: "Clear search [Esc]", onClick: () => {
|
|
264
|
-
selector.setSelectedColumnsSearchText('');
|
|
265
|
-
searchSelectedColumnsInputRef.current?.focus();
|
|
266
|
-
}, children: _jsx(DataCubeIcon.X, { className: "text-lg" }) })] }), _jsx("div", { className: "h-[calc(100%_-_24px)]", children: _jsx(AgGridReact, { theme: "legacy", ...getBaseGridProps(),
|
|
267
|
-
// NOTE: technically, we don't want to enable managed row-dragging here
|
|
268
|
-
// but enabling this gives us free row moving management and interaction
|
|
269
|
-
// comes out of the box from ag-grid, we will just sync the state with
|
|
270
|
-
// grid row data afterwards to ensure consistency
|
|
271
|
-
rowDragManaged: true, onRowDragEnd: onSelectedColumnsDragEnd, onGridReady: (params) => setSelectedColumnsGridApi(params.api), onSelectionChanged: (event) => {
|
|
272
|
-
setSelectedSelectedColumns(event.api
|
|
273
|
-
.getSelectedNodes()
|
|
274
|
-
.map((node) => node.data)
|
|
275
|
-
.filter(isNonNullable));
|
|
276
|
-
},
|
|
277
|
-
// Using ag-grid quick filter is a cheap way to implement search
|
|
278
|
-
quickFilterText: selector.selectedColumnsSearchText, noRowsOverlayComponentParams: {
|
|
279
|
-
noColumnsSelectedRenderer,
|
|
280
|
-
}, rowData: selector.selectedColumnsForDisplay, columnDefs: [
|
|
281
|
-
{
|
|
282
|
-
...getBaseColumnDef(),
|
|
283
|
-
/**
|
|
284
|
-
* Support double-click to remove all (filtered by search) columns
|
|
285
|
-
*/
|
|
286
|
-
headerComponent: (params) => (_jsxs("button", { title: "Double-click to remove all columns", className: "flex h-full w-full items-center justify-between pl-0.5", onDoubleClick: () => {
|
|
559
|
+
panel.refreshDimensionsTreeData();
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
confirmPopulateStubDimensionWhenAddingColumns(view, () => {
|
|
563
|
+
const newDimension = panel.newDimension();
|
|
564
|
+
newDimension.setColumns([...columnsToMove]);
|
|
565
|
+
panel.refreshDimensionsTreeData();
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
availableColumnsGridApi.clearFocusedCell();
|
|
569
|
+
}, disabled: !availableColumnsGridApi ||
|
|
570
|
+
selectedAvailableColumns.length === 0, children: _jsx(DataCubeIcon.ChevronRight, { className: "text-2xl" }) }), _jsx("button", { className: "mt-2 flex items-center justify-center rounded-sm border border-neutral-300 bg-neutral-100 text-neutral-500 hover:bg-neutral-200 disabled:bg-neutral-200 disabled:text-neutral-400", title: "Remove selected column(s)",
|
|
571
|
+
/**
|
|
572
|
+
* Support remove selected (filtered by search) columns
|
|
573
|
+
* We reset the selection after this operation
|
|
574
|
+
*/
|
|
575
|
+
onClick: () => {
|
|
576
|
+
if (!dimensionsTreeGridApi ||
|
|
577
|
+
selectedSelectedColumns.length === 0) {
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
287
580
|
// The columns being moved are scoped by the current search
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
581
|
+
const filteredNodes = getDataForAllFilteredNodes(dimensionsTreeGridApi);
|
|
582
|
+
const columnsToMove = selectedSelectedColumns.filter((column) => _findCol(filteredNodes, column.name));
|
|
583
|
+
panel.deselectColumns(columnsToMove);
|
|
584
|
+
panel.refreshDimensionsTreeData();
|
|
585
|
+
dimensionsTreeGridApi.clearFocusedCell();
|
|
586
|
+
}, disabled: !dimensionsTreeGridApi ||
|
|
587
|
+
selectedSelectedColumns.length === 0, children: _jsx(DataCubeIcon.ChevronLeft, { className: "text-2xl" }) })] }) }), _jsxs("div", { className: "data-cube-tree-selector h-full w-[calc(50%_-_20px)]", children: [_jsx("div", { className: "flex h-5 items-center text-sm", children: "Dimensions:" }), _jsxs("div", { className: "h-[calc(100%_-_20px)] rounded-sm border border-neutral-200", children: [_jsxs("div", { className: "flex h-6", children: [_jsxs("div", { className: "relative h-6 w-[calc(100%_-_124px)] border-b border-r border-neutral-200", children: [_jsx("input", { className: "h-full w-full pl-10 pr-6 placeholder-neutral-400", ref: searchDimensionsTreeInputRef, placeholder: "Search...", value: panel.dimensionsTreeSearchText, onChange: (event) => panel.setDimensionsTreeSearchText(event.target.value), onKeyDown: (event) => {
|
|
588
|
+
if (event.code === 'Escape') {
|
|
589
|
+
event.stopPropagation();
|
|
590
|
+
searchDimensionsTreeInputRef.current?.select();
|
|
591
|
+
panel.setDimensionsTreeSearchText('');
|
|
592
|
+
}
|
|
593
|
+
} }), _jsx("div", { className: "absolute left-0 top-0 flex h-6 w-10 items-center justify-center", children: _jsx(DataCubeIcon.Search, { className: "stroke-[3px] text-lg text-neutral-500" }) }), _jsx("button", { className: "absolute right-0 top-0 flex h-6 w-6 items-center justify-center text-neutral-500 disabled:text-neutral-300", disabled: !panel.dimensionsTreeSearchText, title: "Clear search [Esc]", onClick: () => {
|
|
594
|
+
panel.setDimensionsTreeSearchText('');
|
|
595
|
+
searchDimensionsTreeInputRef.current?.focus();
|
|
596
|
+
}, children: _jsx(DataCubeIcon.X, { className: "text-lg" }) })] }), _jsxs("div", { className: "flex h-6 items-center border-b border-neutral-200", children: [_jsx("button", { className: "flex h-6 w-6 items-center justify-center text-neutral-500 disabled:text-neutral-300", title: "Add new dimension", onClick: () => {
|
|
597
|
+
panel.newDimension();
|
|
598
|
+
panel.refreshDimensionsTreeData();
|
|
599
|
+
}, children: _jsx(DataCubeIcon.Plus, { className: "text-lg" }) }), _jsx("div", { className: "h-3 w-[1px] bg-neutral-200" }), _jsx("button", { className: "flex h-6 w-6 items-center justify-center text-neutral-500 disabled:text-neutral-300", title: "Move dimension(s) up", disabled: selectedDimensions.length === 0, onClick: () => {
|
|
600
|
+
if (selectedDimensions.length === 0) {
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
const minIdx = Math.min(...selectedDimensions.map((dimension) => panel.dimensions.indexOf(dimension)));
|
|
604
|
+
const precedings = [
|
|
605
|
+
...panel.dimensions.slice(0, Math.max(minIdx - 1, 0)),
|
|
606
|
+
// ensure moving dimensions maintain their relative ordering
|
|
607
|
+
...panel.dimensions
|
|
608
|
+
.map((dimension) => selectedDimensions.find((dim) => dim.name === dimension.name))
|
|
609
|
+
.filter(isNonNullable),
|
|
610
|
+
];
|
|
611
|
+
panel.setDimensions([
|
|
612
|
+
...precedings,
|
|
613
|
+
...panel.dimensions.filter((dimension) => !precedings.find((dim) => dim.name === dimension.name)),
|
|
614
|
+
]);
|
|
615
|
+
panel.refreshDimensionsTreeData();
|
|
616
|
+
}, children: _jsx(DataCubeIcon.ChevronUp, { className: "text-lg" }) }), _jsx("div", { className: "h-3 w-[1px] bg-neutral-200" }), _jsx("button", { className: "flex h-6 w-6 items-center justify-center text-neutral-500 disabled:text-neutral-300", title: "Move dimension(s) down", disabled: selectedDimensions.length === 0, onClick: () => {
|
|
617
|
+
if (selectedDimensions.length === 0) {
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
const maxIdx = Math.max(...selectedDimensions.map((dimension) => panel.dimensions.indexOf(dimension)));
|
|
621
|
+
const followings = [
|
|
622
|
+
// ensure moving dimensions maintain their relative ordering
|
|
623
|
+
...panel.dimensions
|
|
624
|
+
.map((dimension) => selectedDimensions.find((dim) => dim.name === dimension.name))
|
|
625
|
+
.filter(isNonNullable),
|
|
626
|
+
...panel.dimensions.slice(Math.min(maxIdx + 1, panel.dimensions.length) +
|
|
627
|
+
1),
|
|
628
|
+
];
|
|
629
|
+
panel.setDimensions([
|
|
630
|
+
...panel.dimensions.filter((dimension) => !followings.find((dim) => dim.name === dimension.name)),
|
|
631
|
+
...followings,
|
|
632
|
+
]);
|
|
633
|
+
panel.refreshDimensionsTreeData();
|
|
634
|
+
}, children: _jsx(DataCubeIcon.ChevronDown, { className: "text-lg" }) }), _jsx("div", { className: "h-3 w-[1px] bg-neutral-200" }), _jsx("button", { className: "flex h-6 w-6 items-center justify-center text-neutral-500 disabled:text-neutral-300", title: "Remove dimension(s)", disabled: selectedDimensions.length === 0, onClick: () => {
|
|
635
|
+
if (selectedDimensions.length === 0) {
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
selectedDimensions.at(0)?.setIsRenaming(true);
|
|
639
|
+
}, children: _jsx(DataCubeIcon.Pencil, { className: "text-lg" }) }), _jsx("div", { className: "h-3 w-[1px] bg-neutral-200" }), _jsx("button", { className: "flex h-6 w-6 items-center justify-center text-neutral-500 disabled:text-neutral-300", title: "Rename dimension", disabled: selectedDimensions.length === 0, onClick: () => {
|
|
640
|
+
if (selectedDimensions.length === 0) {
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
panel.setDimensions(panel.dimensions.filter((dimension) => !selectedDimensions.find((dim) => dim.name === dimension.name)));
|
|
644
|
+
panel.refreshDimensionsTreeData();
|
|
645
|
+
}, children: _jsx(DataCubeIcon.Delete, { className: "text-lg" }) })] })] }), _jsx("div", { className: "h-[calc(100%_-_24px)]", children: _jsx(AgGridReact, { ...getColumnsSelectorBaseGridProps(), modules: [AllCommunityModule, TreeDataModule], className: "ag-theme-quartz", treeData: true, treeDataChildrenField: "children", groupDefaultExpanded: -1,
|
|
646
|
+
// Disable managed row-dragging to disallow changing the order of columns
|
|
647
|
+
// and to make sure the row data and the available columns state are in sync
|
|
648
|
+
onGridReady: (params) => {
|
|
649
|
+
setDimensionsTreeGridApi(params.api);
|
|
650
|
+
// eslint-disable-next-line no-process-env
|
|
651
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
652
|
+
// restore original error logging
|
|
653
|
+
console.error = __INTERNAL__original_console_error; // eslint-disable-line no-console
|
|
654
|
+
}
|
|
655
|
+
}, onSelectionChanged: (event) => {
|
|
656
|
+
const selectedNodes = event.api
|
|
657
|
+
.getSelectedNodes()
|
|
658
|
+
.map((node) => node.data)
|
|
659
|
+
.filter(isNonNullable);
|
|
660
|
+
const _selectedColumns = [];
|
|
661
|
+
const _selectedDimensions = [];
|
|
662
|
+
selectedNodes.forEach((node) => {
|
|
663
|
+
if (node.data instanceof DataCubeEditorDimensionState) {
|
|
664
|
+
_selectedDimensions.push(node.data);
|
|
665
|
+
}
|
|
666
|
+
else if (node.data instanceof
|
|
667
|
+
DataCubeEditorColumnsSelectorColumnState) {
|
|
668
|
+
_selectedColumns.push(node.data);
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
setSelectedDimensions(_selectedDimensions);
|
|
672
|
+
setSelectedSelectedColumns(_selectedColumns);
|
|
673
|
+
}, rowSelection: {
|
|
674
|
+
mode: 'multiRow',
|
|
675
|
+
groupSelects: 'self',
|
|
676
|
+
}, columnDefs: [],
|
|
677
|
+
// Using ag-grid quick filter is a cheap way to implement search
|
|
678
|
+
quickFilterText: panel.dimensionsTreeSearchText, rowData: panel.dimensionsTreeData.nodes, rowClassRules: {
|
|
679
|
+
'border-t border-b border-1 border-transparent': () => true,
|
|
680
|
+
'border-b-sky-600': (params) => {
|
|
681
|
+
return (dimensionsTreeOnHoverIndex !== undefined &&
|
|
682
|
+
params.rowIndex === dimensionsTreeOnHoverIndex);
|
|
683
|
+
},
|
|
684
|
+
'border-t-sky-600': (params) => {
|
|
685
|
+
return (dimensionsTreeOnHoverIndex === -1 &&
|
|
686
|
+
params.rowIndex === 0);
|
|
687
|
+
},
|
|
688
|
+
}, autoGroupColumnDef: {
|
|
689
|
+
headerName: 'Name',
|
|
690
|
+
field: 'name',
|
|
691
|
+
colId: 'name',
|
|
692
|
+
flex: 1,
|
|
693
|
+
minWidth: 100,
|
|
694
|
+
filter: true,
|
|
695
|
+
sortable: false,
|
|
696
|
+
resizable: false,
|
|
697
|
+
suppressHeaderMenuButton: true,
|
|
698
|
+
suppressKeyboardEvent: (event) => {
|
|
699
|
+
if (panel.dimensions.some((dimension) => dimension.isRenaming)) {
|
|
700
|
+
// only allow tabbing through the grid when renaming
|
|
701
|
+
if (event.event.code === 'Tab') {
|
|
702
|
+
return false;
|
|
703
|
+
}
|
|
704
|
+
return true;
|
|
705
|
+
}
|
|
706
|
+
return false;
|
|
707
|
+
},
|
|
708
|
+
getQuickFilterText: (params) => params.value,
|
|
709
|
+
/**
|
|
710
|
+
* Support double-click to remove all (filtered by search) columns
|
|
711
|
+
*/
|
|
712
|
+
headerComponent: (params) => (_jsxs("button", { title: "Double-click to remove all columns", className: "flex h-full w-full items-center justify-between pl-0.5", onDoubleClick: () => {
|
|
713
|
+
// The columns being moved are scoped by the current search
|
|
714
|
+
const filteredNodes = getDataForAllFilteredNodes(params.api);
|
|
715
|
+
panel.deselectColumns(panel.selectedColumns.filter((column) => _findCol(filteredNodes, column.name)));
|
|
716
|
+
panel.refreshDimensionsTreeData();
|
|
717
|
+
params.api.clearFocusedCell();
|
|
718
|
+
}, children: [_jsx("div", { children: `[All Dimensions]` }), _jsx(DimensionsTreeSearchResultCountBadge, { panel: panel, gridApi: params.api })] })),
|
|
719
|
+
onCellDoubleClicked: (params) => {
|
|
720
|
+
if (params.data?.data instanceof
|
|
721
|
+
DataCubeEditorDimensionState) {
|
|
722
|
+
params.data.data.setColumns([]);
|
|
723
|
+
panel.refreshDimensionsTreeData();
|
|
724
|
+
params.api.clearFocusedCell();
|
|
725
|
+
}
|
|
726
|
+
},
|
|
727
|
+
cellRendererParams: {
|
|
728
|
+
innerRenderer: (params) => {
|
|
729
|
+
const data = params.data;
|
|
730
|
+
if (!data) {
|
|
731
|
+
return null;
|
|
732
|
+
}
|
|
733
|
+
if (data.data instanceof
|
|
734
|
+
DataCubeEditorDimensionState) {
|
|
735
|
+
return (_jsx(DimensionLabel, { panel: panel, dimension: data.data, gridApi: params.api }));
|
|
736
|
+
}
|
|
737
|
+
return (_jsx("div", { className: "flex h-full w-full cursor-pointer items-center", title: `[${data.name}]\nDouble-click to remove column`, onDoubleClick: () => {
|
|
738
|
+
if (data.data instanceof
|
|
739
|
+
DataCubeEditorColumnsSelectorColumnState) {
|
|
740
|
+
panel.deselectColumns([data.data]);
|
|
741
|
+
panel.refreshDimensionsTreeData();
|
|
742
|
+
}
|
|
743
|
+
params.api.clearFocusedCell();
|
|
744
|
+
}, children: _jsx("div", { className: "h-full flex-1 items-center overflow-hidden overflow-ellipsis whitespace-nowrap pl-1", children: data.name }) }));
|
|
745
|
+
},
|
|
746
|
+
},
|
|
747
|
+
}, noRowsOverlayComponent: (params) => {
|
|
748
|
+
if (params.api.getQuickFilter()) {
|
|
749
|
+
return (_jsxs("div", { className: "flex items-center border-[1.5px] border-neutral-300 p-2 font-semibold text-neutral-400", children: [_jsx("div", { children: _jsx(DataCubeIcon.WarningCircle, { className: "mr-1 text-lg" }) }), "No match found"] }));
|
|
750
|
+
}
|
|
751
|
+
return (_jsxs("div", { className: "flex items-center border-[1.5px] border-neutral-200 p-2 font-semibold text-neutral-400", children: [_jsx("div", { children: _jsx(DataCubeIcon.Warning, { className: "mr-1 text-lg" }) }), "No dimensions specified"] }));
|
|
752
|
+
}, suppressRowDrag: !isDimensionsTreeRowDragEnabled, rowDragEntireRow: isDimensionsTreeRowDragEnabled, onRowDragEnd: onDimensionsTreeRowDragEnd, onRowDragMove: onDimensionsTreeRowDragMove, onRowDragCancel: onDimensionsTreeRowDragCancel, onRowDragLeave: onDimensionsTreeRowDragLeave }) })] })] })] }) }))] })] }));
|
|
310
753
|
});
|
|
311
754
|
//# sourceMappingURL=DataCubeEditorDimensionsPanel.js.map
|