@finos/legend-query-builder 4.11.4 → 4.11.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. package/lib/components/QueryBuilder.js +1 -1
  2. package/lib/components/QueryBuilder.js.map +1 -1
  3. package/lib/components/execution-plan/SQLExecutionNodeViewer.js +1 -1
  4. package/lib/components/execution-plan/SQLExecutionNodeViewer.js.map +1 -1
  5. package/lib/components/{QueryBuilderResultPanel.d.ts → result/QueryBuilderResultPanel.d.ts} +1 -2
  6. package/lib/components/result/QueryBuilderResultPanel.d.ts.map +1 -0
  7. package/lib/components/result/QueryBuilderResultPanel.js +185 -0
  8. package/lib/components/result/QueryBuilderResultPanel.js.map +1 -0
  9. package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts +24 -0
  10. package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts.map +1 -0
  11. package/lib/components/result/tds/QueryBuilderTDSGridResult.js +140 -0
  12. package/lib/components/result/tds/QueryBuilderTDSGridResult.js.map +1 -0
  13. package/lib/components/result/tds/QueryBuilderTDSResultShared.d.ts +41 -0
  14. package/lib/components/result/tds/QueryBuilderTDSResultShared.d.ts.map +1 -0
  15. package/lib/components/result/tds/QueryBuilderTDSResultShared.js +465 -0
  16. package/lib/components/result/tds/QueryBuilderTDSResultShared.js.map +1 -0
  17. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.d.ts +24 -0
  18. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.d.ts.map +1 -0
  19. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.js +47 -0
  20. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.js.map +1 -0
  21. package/lib/index.css +2 -2
  22. package/lib/index.css.map +1 -1
  23. package/lib/package.json +1 -1
  24. package/lib/stores/QueryBuilderResultState.d.ts +5 -1
  25. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  26. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  27. package/package.json +2 -2
  28. package/src/components/QueryBuilder.tsx +1 -1
  29. package/src/components/execution-plan/SQLExecutionNodeViewer.tsx +1 -1
  30. package/src/components/result/QueryBuilderResultPanel.tsx +570 -0
  31. package/src/components/result/tds/QueryBuilderTDSGridResult.tsx +239 -0
  32. package/src/components/result/tds/QueryBuilderTDSResultShared.tsx +866 -0
  33. package/src/components/result/tds/QueryBuilderTDSSimpleGridResult.tsx +80 -0
  34. package/src/stores/QueryBuilderResultState.ts +12 -1
  35. package/tsconfig.json +4 -1
  36. package/lib/components/QueryBuilderResultPanel.d.ts.map +0 -1
  37. package/lib/components/QueryBuilderResultPanel.js +0 -633
  38. package/lib/components/QueryBuilderResultPanel.js.map +0 -1
  39. package/src/components/QueryBuilderResultPanel.tsx +0 -1412
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { clsx } from '@finos/legend-art';
18
+ import { observer } from 'mobx-react-lite';
19
+ import type { QueryBuilderState } from '../../../stores/QueryBuilderState.js';
20
+ import type { TDSExecutionResult } from '@finos/legend-graph';
21
+ import { useState } from 'react';
22
+ import {
23
+ DataGrid,
24
+ type DataGridApi,
25
+ type DataGridCellRange,
26
+ type DataGridColumnApi,
27
+ type DataGridColumnDefinition,
28
+ type DataGridIRowNode,
29
+ } from '@finos/legend-lego/data-grid';
30
+ import {
31
+ getAggregationTDSColumnCustomizations,
32
+ getRowDataFromExecutionResult,
33
+ QueryResultEnterpriseCellRenderer,
34
+ } from './QueryBuilderTDSResultShared.js';
35
+ import type {
36
+ QueryBuilderResultState,
37
+ QueryBuilderTDSResultCellData,
38
+ QueryBuilderTDSResultCellDataType,
39
+ QueryBuilderTDSRowDataType,
40
+ } from '../../../stores/QueryBuilderResultState.js';
41
+
42
+ const getAdvancedColDefs = (
43
+ executionResult: TDSExecutionResult,
44
+ resultState: QueryBuilderResultState,
45
+ // TODO: fix col return type
46
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
+ ): DataGridColumnDefinition<any, any>[] =>
48
+ executionResult.result.columns.map((colName) => {
49
+ const col = {
50
+ minWidth: 50,
51
+ sortable: true,
52
+ resizable: true,
53
+ field: colName,
54
+ flex: 1,
55
+ enablePivot: true,
56
+ enableRowGroup: true,
57
+ enableValue: true,
58
+ ...getAggregationTDSColumnCustomizations(executionResult, colName),
59
+ } as DataGridColumnDefinition;
60
+ const persistedColumn = resultState.gridConfig.columns.find(
61
+ (c) => c.colId === colName,
62
+ );
63
+ if (persistedColumn) {
64
+ if (persistedColumn.width) {
65
+ col.width = persistedColumn.width;
66
+ }
67
+ col.pinned = persistedColumn.pinned ?? null;
68
+ col.rowGroup = persistedColumn.rowGroup ?? false;
69
+ col.rowGroupIndex = persistedColumn.rowGroupIndex ?? null;
70
+ col.aggFunc = persistedColumn.aggFunc ?? null;
71
+ col.pivot = persistedColumn.pivot ?? false;
72
+ col.hide = persistedColumn.hide ?? false;
73
+ }
74
+ return col;
75
+ });
76
+
77
+ const getEnterpriseModeColDefs = (
78
+ executionResult: TDSExecutionResult,
79
+ resultState: QueryBuilderResultState,
80
+ ): DataGridColumnDefinition<
81
+ QueryBuilderTDSRowDataType,
82
+ QueryBuilderTDSResultCellDataType
83
+ >[] =>
84
+ executionResult.result.columns.map(
85
+ (colName) =>
86
+ ({
87
+ minWidth: 50,
88
+ sortable: true,
89
+ resizable: true,
90
+ field: colName,
91
+ flex: 1,
92
+ cellRenderer: QueryResultEnterpriseCellRenderer,
93
+ cellRendererParams: {
94
+ resultState: resultState,
95
+ tdsExecutionResult: executionResult,
96
+ },
97
+ }) as DataGridColumnDefinition,
98
+ );
99
+
100
+ export const QueryBuilderTDSGridResult = observer(
101
+ (props: {
102
+ executionResult: TDSExecutionResult;
103
+ queryBuilderState: QueryBuilderState;
104
+ }) => {
105
+ const { executionResult, queryBuilderState } = props;
106
+
107
+ const [columnAPi, setColumnApi] = useState<DataGridColumnApi | undefined>(
108
+ undefined,
109
+ );
110
+ const resultState = queryBuilderState.resultState;
111
+ const isAdvancedModeEnabled = queryBuilderState.isAdvancedModeEnabled;
112
+ const colDefs = isAdvancedModeEnabled
113
+ ? getAdvancedColDefs(executionResult, resultState)
114
+ : getEnterpriseModeColDefs(executionResult, resultState);
115
+
116
+ const onSaveGridColumnState = (): void => {
117
+ if (!columnAPi) {
118
+ return;
119
+ }
120
+ resultState.setGridConfig({
121
+ columns: columnAPi.getColumnState(),
122
+ isPivotModeEnabled: columnAPi.isPivotMode(),
123
+ });
124
+ };
125
+
126
+ const getSelectedCells = (
127
+ api: DataGridApi<QueryBuilderTDSRowDataType>,
128
+ ): QueryBuilderTDSResultCellData[] => {
129
+ const seletcedRanges: DataGridCellRange[] | null = api.getCellRanges();
130
+ const nodes = api.getRenderedNodes();
131
+ const columns = api.getColumnDefs() as DataGridColumnDefinition[];
132
+ const selectedCells = [];
133
+ if (seletcedRanges) {
134
+ for (const seletcedRange of seletcedRanges) {
135
+ const startRow: number = seletcedRange.startRow?.rowIndex ?? 0;
136
+ const endRow: number = seletcedRange.endRow?.rowIndex ?? 0;
137
+ const selectedColumns: string[] = seletcedRange.columns.map((col) =>
138
+ col.getColId(),
139
+ );
140
+ for (let x: number = startRow; x <= endRow; x++) {
141
+ const curRowData = nodes.find(
142
+ (n) => (n as DataGridIRowNode).rowIndex === x,
143
+ )?.data;
144
+ if (curRowData) {
145
+ for (const col of selectedColumns) {
146
+ const valueAndColumnId = {
147
+ value: Object.entries(curRowData)
148
+ .find((rData) => rData[0] === col)
149
+ ?.at(1),
150
+ columnName: col,
151
+ coordinates: {
152
+ rowIndex: x,
153
+ colIndex: columns.findIndex(
154
+ (colDef) => colDef.colId === col,
155
+ ),
156
+ },
157
+ } as QueryBuilderTDSResultCellData;
158
+ selectedCells.push(valueAndColumnId);
159
+ }
160
+ }
161
+ }
162
+ }
163
+ }
164
+ return selectedCells;
165
+ };
166
+
167
+ return (
168
+ <div className="query-builder__result__values__table">
169
+ <div
170
+ className={clsx(
171
+ 'ag-theme-balham-dark query-builder__result__tds-grid',
172
+ )}
173
+ >
174
+ {isAdvancedModeEnabled ? (
175
+ <DataGrid
176
+ rowData={getRowDataFromExecutionResult(executionResult)}
177
+ onGridReady={(params): void => {
178
+ setColumnApi(params.columnApi);
179
+ params.columnApi.setPivotMode(
180
+ resultState.gridConfig.isPivotModeEnabled,
181
+ );
182
+ }}
183
+ gridOptions={{
184
+ suppressScrollOnNewData: true,
185
+ getRowId: (data) => data.data.rowNumber,
186
+ rowSelection: 'multiple',
187
+ pivotPanelShow: 'always',
188
+ rowGroupPanelShow: 'always',
189
+ enableRangeSelection: true,
190
+ }}
191
+ // NOTE: when column definition changed, we need to force refresh the cell to make sure the cell renderer is updated
192
+ // See https://stackoverflow.com/questions/56341073/how-to-refresh-an-ag-grid-when-a-change-occurs-inside-a-custom-cell-renderer-com
193
+ onRowDataUpdated={(params) => {
194
+ params.api.refreshCells({ force: true });
195
+ }}
196
+ suppressFieldDotNotation={true}
197
+ suppressContextMenu={false}
198
+ columnDefs={colDefs}
199
+ sideBar={['columns', 'filters']}
200
+ onColumnVisible={onSaveGridColumnState}
201
+ onColumnPinned={onSaveGridColumnState}
202
+ onColumnResized={onSaveGridColumnState}
203
+ onColumnRowGroupChanged={onSaveGridColumnState}
204
+ onColumnValueChanged={onSaveGridColumnState}
205
+ onColumnPivotChanged={onSaveGridColumnState}
206
+ onColumnPivotModeChanged={onSaveGridColumnState}
207
+ />
208
+ ) : (
209
+ <DataGrid
210
+ rowData={getRowDataFromExecutionResult(executionResult)}
211
+ gridOptions={{
212
+ suppressScrollOnNewData: true,
213
+ getRowId: (data) => data.data.rowNumber,
214
+ rowSelection: 'multiple',
215
+ enableRangeSelection: true,
216
+ }}
217
+ // NOTE: when column definition changed, we need to force refresh the cell to make sure the cell renderer is updated
218
+ // See https://stackoverflow.com/questions/56341073/how-to-refresh-an-ag-grid-when-a-change-occurs-inside-a-custom-cell-renderer-com
219
+ onRowDataUpdated={(params) => {
220
+ params.api.refreshCells({ force: true });
221
+ }}
222
+ onRangeSelectionChanged={(event) => {
223
+ const selectedCells = getSelectedCells(event.api);
224
+ resultState.setSelectedCells([]);
225
+ selectedCells.forEach((cell) =>
226
+ resultState.addSelectedCell(cell),
227
+ );
228
+ }}
229
+ suppressFieldDotNotation={true}
230
+ suppressClipboardPaste={false}
231
+ suppressContextMenu={!isAdvancedModeEnabled}
232
+ columnDefs={colDefs}
233
+ />
234
+ )}
235
+ </div>
236
+ </div>
237
+ );
238
+ },
239
+ );