@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.
Files changed (175) hide show
  1. package/lib/components/DataCubePlaceholder.d.ts.map +1 -1
  2. package/lib/components/DataCubePlaceholder.js +2 -1
  3. package/lib/components/DataCubePlaceholder.js.map +1 -1
  4. package/lib/components/core/DataCubePureCodeEditorUtils.d.ts +2 -1
  5. package/lib/components/core/DataCubePureCodeEditorUtils.d.ts.map +1 -1
  6. package/lib/components/core/DataCubePureCodeEditorUtils.js.map +1 -1
  7. package/lib/components/view/editor/DataCubeEditor.d.ts.map +1 -1
  8. package/lib/components/view/editor/DataCubeEditor.js +4 -2
  9. package/lib/components/view/editor/DataCubeEditor.js.map +1 -1
  10. package/lib/components/view/editor/DataCubeEditorColumnsPanel.d.ts.map +1 -1
  11. package/lib/components/view/editor/DataCubeEditorColumnsPanel.js +3 -3
  12. package/lib/components/view/editor/DataCubeEditorColumnsPanel.js.map +1 -1
  13. package/lib/components/view/editor/DataCubeEditorColumnsSelector.d.ts +47 -0
  14. package/lib/components/view/editor/DataCubeEditorColumnsSelector.d.ts.map +1 -0
  15. package/lib/components/view/editor/{DataCubeEditorColumnSelector.js → DataCubeEditorColumnsSelector.js} +70 -55
  16. package/lib/components/view/editor/DataCubeEditorColumnsSelector.js.map +1 -0
  17. package/lib/components/view/editor/DataCubeEditorDimensionsPanel.d.ts +3 -13
  18. package/lib/components/view/editor/DataCubeEditorDimensionsPanel.d.ts.map +1 -1
  19. package/lib/components/view/editor/DataCubeEditorDimensionsPanel.js +707 -264
  20. package/lib/components/view/editor/DataCubeEditorDimensionsPanel.js.map +1 -1
  21. package/lib/components/view/editor/DataCubeEditorHorizontalPivotsPanel.js +2 -2
  22. package/lib/components/view/editor/DataCubeEditorHorizontalPivotsPanel.js.map +1 -1
  23. package/lib/components/view/editor/DataCubeEditorSortsPanel.js +2 -2
  24. package/lib/components/view/editor/DataCubeEditorSortsPanel.js.map +1 -1
  25. package/lib/components/view/editor/DataCubeEditorVerticalPivotsPanel.js +2 -2
  26. package/lib/components/view/editor/DataCubeEditorVerticalPivotsPanel.js.map +1 -1
  27. package/lib/components/view/{grid/DataCubeGridShared.d.ts → extend/DataCubeCodeEditor.d.ts} +7 -3
  28. package/lib/components/view/extend/DataCubeCodeEditor.d.ts.map +1 -0
  29. package/lib/components/view/extend/DataCubeCodeEditor.js +114 -0
  30. package/lib/components/view/extend/DataCubeCodeEditor.js.map +1 -0
  31. package/lib/components/view/extend/DataCubeCodeEditorState.d.ts +43 -0
  32. package/lib/components/view/extend/DataCubeCodeEditorState.d.ts.map +1 -0
  33. package/lib/components/view/extend/DataCubeCodeEditorState.js +37 -0
  34. package/lib/components/view/extend/DataCubeCodeEditorState.js.map +1 -0
  35. package/lib/components/view/extend/DataCubeColumnEditor.d.ts.map +1 -1
  36. package/lib/components/view/extend/DataCubeColumnEditor.js +5 -84
  37. package/lib/components/view/extend/DataCubeColumnEditor.js.map +1 -1
  38. package/lib/components/view/grid/DataCubeGrid.d.ts +2 -1
  39. package/lib/components/view/grid/DataCubeGrid.d.ts.map +1 -1
  40. package/lib/components/view/grid/DataCubeGrid.js +29 -19
  41. package/lib/components/view/grid/DataCubeGrid.js.map +1 -1
  42. package/lib/components/view/grid/DataCubeMultidimensionalGrid.d.ts +1 -1
  43. package/lib/components/view/grid/DataCubeMultidimensionalGrid.d.ts.map +1 -1
  44. package/lib/components/view/grid/DataCubeMultidimensionalGrid.js +2 -1
  45. package/lib/components/view/grid/DataCubeMultidimensionalGrid.js.map +1 -1
  46. package/lib/index.css +2 -2
  47. package/lib/index.css.map +1 -1
  48. package/lib/index.d.ts +3 -0
  49. package/lib/index.d.ts.map +1 -1
  50. package/lib/index.js +3 -0
  51. package/lib/index.js.map +1 -1
  52. package/lib/package.json +1 -1
  53. package/lib/stores/DataCubeAPI.d.ts.map +1 -1
  54. package/lib/stores/DataCubeAPI.js +3 -1
  55. package/lib/stores/DataCubeAPI.js.map +1 -1
  56. package/lib/stores/core/DataCubeEngine.d.ts +1 -1
  57. package/lib/stores/core/DataCubeEngine.d.ts.map +1 -1
  58. package/lib/stores/core/DataCubeQueryEngine.d.ts +5 -0
  59. package/lib/stores/core/DataCubeQueryEngine.d.ts.map +1 -1
  60. package/lib/stores/core/DataCubeQueryEngine.js +6 -0
  61. package/lib/stores/core/DataCubeQueryEngine.js.map +1 -1
  62. package/lib/stores/core/DataCubeSnapshot.d.ts +1 -1
  63. package/lib/stores/core/DataCubeSnapshot.d.ts.map +1 -1
  64. package/lib/stores/core/model/AdhocQueryDataCubeSource.d.ts +2 -0
  65. package/lib/stores/core/model/AdhocQueryDataCubeSource.d.ts.map +1 -1
  66. package/lib/stores/core/model/AdhocQueryDataCubeSource.js +3 -0
  67. package/lib/stores/core/model/AdhocQueryDataCubeSource.js.map +1 -1
  68. package/lib/stores/core/model/DataCubeConfiguration.d.ts +11 -0
  69. package/lib/stores/core/model/DataCubeConfiguration.d.ts.map +1 -1
  70. package/lib/stores/core/model/DataCubeConfiguration.js +19 -1
  71. package/lib/stores/core/model/DataCubeConfiguration.js.map +1 -1
  72. package/lib/stores/services/DataCubeSettingService.d.ts.map +1 -1
  73. package/lib/stores/services/DataCubeSettingService.js +10 -6
  74. package/lib/stores/services/DataCubeSettingService.js.map +1 -1
  75. package/lib/stores/view/DataCubeInfoState.d.ts +2 -0
  76. package/lib/stores/view/DataCubeInfoState.d.ts.map +1 -1
  77. package/lib/stores/view/DataCubeInfoState.js +3 -0
  78. package/lib/stores/view/DataCubeInfoState.js.map +1 -1
  79. package/lib/stores/view/editor/DataCubeEditorColumnsPanelState.d.ts +8 -8
  80. package/lib/stores/view/editor/DataCubeEditorColumnsPanelState.d.ts.map +1 -1
  81. package/lib/stores/view/editor/DataCubeEditorColumnsPanelState.js +6 -6
  82. package/lib/stores/view/editor/DataCubeEditorColumnsPanelState.js.map +1 -1
  83. package/lib/stores/view/editor/{DataCubeEditorColumnSelectorState.d.ts → DataCubeEditorColumnsSelectorState.d.ts} +6 -6
  84. package/lib/stores/view/editor/DataCubeEditorColumnsSelectorState.d.ts.map +1 -0
  85. package/lib/stores/view/editor/{DataCubeEditorColumnSelectorState.js → DataCubeEditorColumnsSelectorState.js} +4 -4
  86. package/lib/stores/view/editor/DataCubeEditorColumnsSelectorState.js.map +1 -0
  87. package/lib/stores/view/editor/DataCubeEditorDimensionsPanelState.d.ts +29 -6
  88. package/lib/stores/view/editor/DataCubeEditorDimensionsPanelState.d.ts.map +1 -1
  89. package/lib/stores/view/editor/DataCubeEditorDimensionsPanelState.js +102 -39
  90. package/lib/stores/view/editor/DataCubeEditorDimensionsPanelState.js.map +1 -1
  91. package/lib/stores/view/editor/DataCubeEditorHorizontalPivotsPanelState.d.ts +5 -5
  92. package/lib/stores/view/editor/DataCubeEditorHorizontalPivotsPanelState.d.ts.map +1 -1
  93. package/lib/stores/view/editor/DataCubeEditorHorizontalPivotsPanelState.js +7 -6
  94. package/lib/stores/view/editor/DataCubeEditorHorizontalPivotsPanelState.js.map +1 -1
  95. package/lib/stores/view/editor/DataCubeEditorMutableConfiguration.d.ts +2 -1
  96. package/lib/stores/view/editor/DataCubeEditorMutableConfiguration.d.ts.map +1 -1
  97. package/lib/stores/view/editor/DataCubeEditorMutableConfiguration.js +5 -0
  98. package/lib/stores/view/editor/DataCubeEditorMutableConfiguration.js.map +1 -1
  99. package/lib/stores/view/editor/DataCubeEditorSortsPanelState.d.ts +5 -5
  100. package/lib/stores/view/editor/DataCubeEditorSortsPanelState.d.ts.map +1 -1
  101. package/lib/stores/view/editor/DataCubeEditorSortsPanelState.js +6 -6
  102. package/lib/stores/view/editor/DataCubeEditorSortsPanelState.js.map +1 -1
  103. package/lib/stores/view/editor/DataCubeEditorState.d.ts +3 -0
  104. package/lib/stores/view/editor/DataCubeEditorState.d.ts.map +1 -1
  105. package/lib/stores/view/editor/DataCubeEditorState.js +6 -0
  106. package/lib/stores/view/editor/DataCubeEditorState.js.map +1 -1
  107. package/lib/stores/view/editor/DataCubeEditorVerticalPivotsPanelState.d.ts +5 -5
  108. package/lib/stores/view/editor/DataCubeEditorVerticalPivotsPanelState.d.ts.map +1 -1
  109. package/lib/stores/view/editor/DataCubeEditorVerticalPivotsPanelState.js +6 -6
  110. package/lib/stores/view/editor/DataCubeEditorVerticalPivotsPanelState.js.map +1 -1
  111. package/lib/stores/view/extend/DataCubeColumnEditorState.d.ts +7 -14
  112. package/lib/stores/view/extend/DataCubeColumnEditorState.d.ts.map +1 -1
  113. package/lib/stores/view/extend/DataCubeColumnEditorState.js +14 -22
  114. package/lib/stores/view/extend/DataCubeColumnEditorState.js.map +1 -1
  115. package/lib/stores/view/grid/DataCubeGridClientEngine.d.ts +2 -1
  116. package/lib/stores/view/grid/DataCubeGridClientEngine.d.ts.map +1 -1
  117. package/lib/stores/view/grid/DataCubeGridClientEngine.js +7 -0
  118. package/lib/stores/view/grid/DataCubeGridClientEngine.js.map +1 -1
  119. package/lib/stores/view/grid/DataCubeGridClientExportEngine.js +1 -1
  120. package/lib/stores/view/grid/DataCubeGridClientExportEngine.js.map +1 -1
  121. package/lib/stores/view/grid/DataCubeGridMenuBuilder.d.ts +2 -0
  122. package/lib/stores/view/grid/DataCubeGridMenuBuilder.d.ts.map +1 -1
  123. package/lib/stores/view/grid/DataCubeGridMenuBuilder.js +9 -16
  124. package/lib/stores/view/grid/DataCubeGridMenuBuilder.js.map +1 -1
  125. package/lib/stores/view/grid/DataCubeGridState.d.ts +2 -2
  126. package/lib/stores/view/grid/DataCubeGridState.d.ts.map +1 -1
  127. package/lib/stores/view/grid/DataCubeGridState.js +19 -6
  128. package/lib/stores/view/grid/DataCubeGridState.js.map +1 -1
  129. package/package.json +5 -5
  130. package/src/components/DataCubePlaceholder.tsx +2 -0
  131. package/src/components/core/DataCubePureCodeEditorUtils.tsx +2 -1
  132. package/src/components/view/editor/DataCubeEditor.tsx +8 -3
  133. package/src/components/view/editor/DataCubeEditorColumnsPanel.tsx +6 -8
  134. package/src/components/view/editor/{DataCubeEditorColumnSelector.tsx → DataCubeEditorColumnsSelector.tsx} +108 -83
  135. package/src/components/view/editor/DataCubeEditorDimensionsPanel.tsx +1259 -503
  136. package/src/components/view/editor/DataCubeEditorHorizontalPivotsPanel.tsx +5 -5
  137. package/src/components/view/editor/DataCubeEditorSortsPanel.tsx +10 -10
  138. package/src/components/view/editor/DataCubeEditorVerticalPivotsPanel.tsx +2 -2
  139. package/src/components/view/extend/DataCubeCodeEditor.tsx +175 -0
  140. package/src/components/view/extend/DataCubeCodeEditorState.tsx +72 -0
  141. package/src/components/view/extend/DataCubeColumnEditor.tsx +5 -133
  142. package/src/components/view/grid/DataCubeGrid.tsx +70 -53
  143. package/src/components/view/grid/DataCubeMultidimensionalGrid.tsx +3 -1
  144. package/src/index.tsx +3 -0
  145. package/src/stores/DataCubeAPI.ts +3 -1
  146. package/src/stores/core/DataCubeEngine.tsx +1 -1
  147. package/src/stores/core/DataCubeQueryEngine.ts +6 -0
  148. package/src/stores/core/DataCubeSnapshot.ts +1 -1
  149. package/src/stores/core/model/AdhocQueryDataCubeSource.ts +3 -0
  150. package/src/stores/core/model/DataCubeConfiguration.ts +31 -0
  151. package/src/stores/services/DataCubeSettingService.tsx +10 -6
  152. package/src/stores/view/DataCubeInfoState.ts +4 -0
  153. package/src/stores/view/editor/DataCubeEditorColumnsPanelState.ts +13 -13
  154. package/src/stores/view/editor/{DataCubeEditorColumnSelectorState.ts → DataCubeEditorColumnsSelectorState.ts} +6 -6
  155. package/src/stores/view/editor/DataCubeEditorDimensionsPanelState.ts +162 -58
  156. package/src/stores/view/editor/DataCubeEditorHorizontalPivotsPanelState.ts +12 -11
  157. package/src/stores/view/editor/DataCubeEditorMutableConfiguration.ts +8 -0
  158. package/src/stores/view/editor/DataCubeEditorSortsPanelState.ts +10 -10
  159. package/src/stores/view/editor/DataCubeEditorState.tsx +6 -0
  160. package/src/stores/view/editor/DataCubeEditorVerticalPivotsPanelState.ts +11 -11
  161. package/src/stores/view/extend/DataCubeColumnEditorState.tsx +16 -26
  162. package/src/stores/view/grid/DataCubeGridClientEngine.ts +8 -0
  163. package/src/stores/view/grid/DataCubeGridClientExportEngine.ts +1 -1
  164. package/src/stores/view/grid/DataCubeGridMenuBuilder.tsx +26 -1
  165. package/src/stores/view/grid/DataCubeGridState.ts +23 -6
  166. package/tsconfig.json +4 -3
  167. package/lib/components/view/editor/DataCubeEditorColumnSelector.d.ts +0 -38
  168. package/lib/components/view/editor/DataCubeEditorColumnSelector.d.ts.map +0 -1
  169. package/lib/components/view/editor/DataCubeEditorColumnSelector.js.map +0 -1
  170. package/lib/components/view/grid/DataCubeGridShared.d.ts.map +0 -1
  171. package/lib/components/view/grid/DataCubeGridShared.js +0 -25
  172. package/lib/components/view/grid/DataCubeGridShared.js.map +0 -1
  173. package/lib/stores/view/editor/DataCubeEditorColumnSelectorState.d.ts.map +0 -1
  174. package/lib/stores/view/editor/DataCubeEditorColumnSelectorState.js.map +0 -1
  175. 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 React, { useCallback, useEffect, useRef, useState } from 'react';
20
+ import { useCallback, useEffect, useRef, useState } from 'react';
21
21
  import { AgGridReact, } from 'ag-grid-react';
22
- import {} from '../../../stores/view/editor/DataCubeEditorColumnSelectorState.js';
23
- import { isNonNullable } from '@finos/legend-shared';
24
- import { getDataForAllFilteredNodes, getDataForAllNodes, } from '../../../stores/view/grid/DataCubeGridClientEngine.js';
25
- function getBaseGridProps() {
26
- return {
27
- modules: [AllCommunityModule],
28
- className: 'ag-theme-quartz',
29
- animateRows: false,
30
- getRowId: (params) => params.data.name,
31
- editType: 'fullRow',
32
- rowDragMultiRow: true,
33
- rowDragEntireRow: true,
34
- rowSelection: {
35
- mode: 'multiRow',
36
- checkboxes: true,
37
- headerCheckbox: true,
38
- enableClickSelection: true,
39
- },
40
- selectionColumnDef: {
41
- width: 40,
42
- headerClass: '!pl-[23px]',
43
- cellClass: '!pl-1.5',
44
- rowDrag: true,
45
- rowDragText: (params, dragItemCount) => {
46
- if (dragItemCount > 1) {
47
- return `${dragItemCount} columns`;
48
- }
49
- return (params.rowNode?.data).name;
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
- sortable: false,
52
- resizable: false,
53
- suppressHeaderMenuButton: true,
54
- },
55
- suppressMoveWhenRowDragging: true,
56
- rowHeight: 20,
57
- headerHeight: 20,
58
- suppressRowHoverHighlight: false,
59
- noRowsOverlayComponent: (params) => {
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 getBaseColumnDef() {
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
- field: 'name',
83
- colId: 'name',
84
- flex: 1,
85
- minWidth: 100,
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
- * Move this display to a separate component to avoid re-rendering the header too frequently
95
- */
96
- const ColumnsSearchResultCountBadge = observer(function ColumnsSearchResultCountBadge(props) {
97
- const { selector, gridApi, scope } = props;
98
- 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}/${scope === 'available' ? selector.availableColumnsForDisplay.length : selector.selectedColumnsForDisplay.length}`, _jsx("span", { className: "hidden", children: scope === 'available'
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 [selectedColumnsGridApi, setSelectedColumnsGridApi] = useState(null);
109
- const searchAvailableColumnsInputRef = useRef(null);
110
- const searchSelectedColumnsInputRef = useRef(null);
111
- /**
112
- * Since we use managed row dragging for selected columns,
113
- * we just need to sync the row data with the state.
114
- * Dragging (multiple) rows to specific position have been
115
- * handled by ag-grid.
116
- */
117
- const onSelectedColumnsDragStop = useCallback((params) => {
118
- selector.setSelectedColumns(getDataForAllNodes(params.api));
119
- }, [selector]);
120
- const onAvailableColumnsDragStop = useCallback((params) => {
121
- const nodes = params.nodes;
122
- const columnsToMove = nodes
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
- selector.setSelectedColumns(selector.selectedColumns.filter((column) => !columnsToMove.includes(column)));
126
- }, [selector]);
127
- /**
128
- * Since we use managed row dragging for selected columns,
129
- * we just need to sync the row data with the state
130
- * Dragging (multiple) rows to specific position have been
131
- * handled by ag-grid.
132
- */
133
- const onSelectedColumnsDragEnd = useCallback((event) => {
134
- if (event.overIndex === -1) {
135
- return;
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
- selector.setSelectedColumns(getDataForAllNodes(event.api));
138
- }, [selector]);
225
+ }, [panel, view]);
139
226
  /**
140
- * Setup row drop zones for each grid to be the other
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 || !selectedColumnsGridApi) {
231
+ if (!availableColumnsGridApi || !dimensionsTreeGridApi) {
145
232
  return;
146
233
  }
147
- const selectedColumnsDropZoneParams = selectedColumnsGridApi.getRowDropZoneParams({
148
- onDragStop: (event) => {
149
- onSelectedColumnsDragStop(event);
150
- availableColumnsGridApi.clearFocusedCell();
151
- },
152
- });
153
- if (selectedColumnsDropZoneParams) {
154
- availableColumnsGridApi.removeRowDropZone(selectedColumnsDropZoneParams);
155
- availableColumnsGridApi.addRowDropZone(selectedColumnsDropZoneParams);
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.getRowDropZoneParams({
158
- onDragStop: (event) => {
159
- onAvailableColumnsDragStop(event);
160
- selectedColumnsGridApi.clearFocusedCell();
161
- },
162
- });
163
- if (availableColumnsDropZoneParams) {
164
- selectedColumnsGridApi.removeRowDropZone(availableColumnsDropZoneParams);
165
- selectedColumnsGridApi.addRowDropZone(availableColumnsDropZoneParams);
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
- selectedColumnsGridApi,
170
- onSelectedColumnsDragStop,
171
- onAvailableColumnsDragStop,
260
+ dimensionsTreeGridApi,
261
+ onDimensionsTreeExternalDragStop,
262
+ onAvailableColumnsExternalDragStop,
172
263
  ]);
173
- return (_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: "Click here to search...", value: selector.availableColumnsSearchText, onChange: (event) => selector.setAvailableColumnsSearchText(event.target.value), onKeyDown: (event) => {
174
- if (event.code === 'Escape') {
175
- event.stopPropagation();
176
- searchAvailableColumnsInputRef.current?.select();
177
- selector.setAvailableColumnsSearchText('');
178
- }
179
- } }), _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.availableColumnsSearchText, title: "Clear search [Esc]", onClick: () => {
180
- selector.setAvailableColumnsSearchText('');
181
- searchAvailableColumnsInputRef.current?.focus();
182
- }, children: _jsx(DataCubeIcon.X, { className: "text-lg" }) })] }), _jsx("div", { className: "h-[calc(100%_-_24px)]", children: _jsx(AgGridReact, { theme: "legacy", ...getBaseGridProps(),
183
- // Disable managed row-dragging to disallow changing the order of columns
184
- // and to make sure the row data and the available columns state are in sync
185
- rowDragManaged: false, onGridReady: (params) => setAvailableColumnsGridApi(params.api), onSelectionChanged: (event) => {
186
- setSelectedAvailableColumns(event.api
187
- .getSelectedNodes()
188
- .map((node) => node.data)
189
- .filter(isNonNullable));
190
- },
191
- // Using ag-grid quick filter is a cheap way to implement search
192
- quickFilterText: selector.availableColumnsSearchText, rowData: selector.availableColumnsForDisplay, columnDefs: [
193
- {
194
- ...getBaseColumnDef(),
195
- /**
196
- * Support double-click to add all (filtered by search) columns
197
- */
198
- 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: () => {
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 filteredData = getDataForAllFilteredNodes(params.api);
201
- selector.setSelectedColumns([
202
- ...selector.selectedColumns,
203
- ...filteredData,
204
- ]);
205
- params.api.clearFocusedCell();
206
- }, children: [_jsx("div", { children: `[All Columns]` }), _jsx(ColumnsSearchResultCountBadge, { selector: selector, gridApi: params.api, scope: "available" })] })),
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
- params.api.clearFocusedCell();
218
- }, children: [columnLabelRenderer?.({
219
- selector,
220
- column: data,
221
- }) ?? (_jsx("div", { className: "h-full flex-1 items-center overflow-hidden overflow-ellipsis whitespace-nowrap pl-2", children: data.name })), _jsx("div", { className: "flex h-full", children: columnActionRenderer?.({
222
- selector,
223
- column: data,
224
- }) ?? null })] }));
225
- },
226
- },
227
- ] }) })] })] }), _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 columns",
228
- /**
229
- * Support add selected (filtered by search) columns
230
- * We reset the selection after this operation
231
- */
232
- onClick: () => {
233
- if (!availableColumnsGridApi) {
234
- return;
235
- }
236
- // The columns being moved are scoped by the current search
237
- const filteredData = getDataForAllFilteredNodes(availableColumnsGridApi);
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 filteredData = getDataForAllFilteredNodes(params.api);
289
- selector.setSelectedColumns(selector.selectedColumns.filter((column) => !filteredData.includes(column)));
290
- params.api.clearFocusedCell();
291
- }, children: [_jsx("div", { children: `[All Columns]` }), _jsx(ColumnsSearchResultCountBadge, { selector: selector, gridApi: params.api, scope: "selected" })] })),
292
- cellRenderer: (params) => {
293
- const data = params.data;
294
- if (!data) {
295
- return null;
296
- }
297
- return (_jsxs("div", { className: "flex h-full w-full cursor-pointer items-center", title: `[${data.name}]\nDouble-click to add column`, onDoubleClick: () => {
298
- selector.setSelectedColumns(selector.selectedColumns.filter((column) => column !== data));
299
- params.api.clearFocusedCell();
300
- }, children: [columnLabelRenderer?.({
301
- selector,
302
- column: data,
303
- }) ?? (_jsx("div", { className: "h-full flex-1 items-center overflow-hidden overflow-ellipsis whitespace-nowrap pl-2", children: data.name })), _jsx("div", { className: "flex h-full", children: columnActionRenderer?.({
304
- selector,
305
- column: data,
306
- }) ?? null })] }));
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