@finos/legend-query-builder 4.0.9 → 4.0.10
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/QueryBuilderResultPanel.d.ts.map +1 -1
- package/lib/components/QueryBuilderResultPanel.js +208 -67
- package/lib/components/QueryBuilderResultPanel.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +4 -4
- package/lib/stores/QueryBuilderResultState.d.ts +19 -0
- package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
- package/lib/stores/QueryBuilderResultState.js +48 -1
- package/lib/stores/QueryBuilderResultState.js.map +1 -1
- package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts.map +1 -1
- package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
- package/lib/stores/shared/LambdaParameterState.d.ts.map +1 -1
- package/lib/stores/shared/LambdaParameterState.js +1 -1
- package/lib/stores/shared/LambdaParameterState.js.map +1 -1
- package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts +5 -2
- package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts.map +1 -1
- package/lib/stores/shared/ValueSpecificationEditorHelper.js +30 -40
- package/lib/stores/shared/ValueSpecificationEditorHelper.js.map +1 -1
- package/package.json +12 -12
- package/src/components/QueryBuilderResultPanel.tsx +357 -91
- package/src/stores/QueryBuilderResultState.ts +82 -0
- package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +1 -0
- package/src/stores/shared/LambdaParameterState.ts +1 -0
- package/src/stores/shared/ValueSpecificationEditorHelper.ts +80 -57
@@ -68,7 +68,7 @@ import {
|
|
68
68
|
prettyDuration,
|
69
69
|
filterByType,
|
70
70
|
} from '@finos/legend-shared';
|
71
|
-
import {
|
71
|
+
import { forwardRef, useState } from 'react';
|
72
72
|
import {
|
73
73
|
QueryBuilderDerivationProjectionColumnState,
|
74
74
|
QueryBuilderProjectionColumnState,
|
@@ -96,13 +96,22 @@ import { PARAMETER_SUBMIT_ACTION } from '../stores/shared/LambdaParameterState.j
|
|
96
96
|
import { QUERY_BUILDER_TEST_ID } from '../__lib__/QueryBuilderTesting.js';
|
97
97
|
import {
|
98
98
|
DataGrid,
|
99
|
-
type
|
99
|
+
type DataGridCellRendererParams,
|
100
100
|
} from '@finos/legend-lego/data-grid';
|
101
101
|
import {
|
102
102
|
CODE_EDITOR_LANGUAGE,
|
103
103
|
CodeEditor,
|
104
104
|
} from '@finos/legend-lego/code-editor';
|
105
105
|
import { ExecutionPlanViewer } from './execution-plan/ExecutionPlanViewer.js';
|
106
|
+
import type {
|
107
|
+
QueryBuilderTDSResultCellCoordinate,
|
108
|
+
QueryBuilderResultState,
|
109
|
+
QueryBuilderTDSResultCellData,
|
110
|
+
} from '../stores/QueryBuilderResultState.js';
|
111
|
+
import {
|
112
|
+
QueryBuilderPostFilterOperator_IsEmpty,
|
113
|
+
QueryBuilderPostFilterOperator_IsNotEmpty,
|
114
|
+
} from '../stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_IsEmpty.js';
|
106
115
|
|
107
116
|
export const tryToFormatSql = (sql: string): string => {
|
108
117
|
try {
|
@@ -117,7 +126,7 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
117
126
|
forwardRef<
|
118
127
|
HTMLDivElement,
|
119
128
|
{
|
120
|
-
event:
|
129
|
+
event: QueryBuilderTDSResultCellData | null;
|
121
130
|
tdsState: QueryBuilderTDSState;
|
122
131
|
}
|
123
132
|
>(function QueryBuilderResultContextMenu(props, ref) {
|
@@ -125,20 +134,26 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
125
134
|
const applicationStore = useApplicationStore();
|
126
135
|
const postFilterEqualOperator = new QueryBuilderPostFilterOperator_Equal();
|
127
136
|
const postFilterInOperator = new QueryBuilderPostFilterOperator_In();
|
137
|
+
const postFilterEmptyOperator =
|
138
|
+
new QueryBuilderPostFilterOperator_IsEmpty();
|
139
|
+
const postFilterNotEmptyOperator =
|
140
|
+
new QueryBuilderPostFilterOperator_IsNotEmpty();
|
141
|
+
|
128
142
|
const postFilterNotEqualOperator =
|
129
143
|
new QueryBuilderPostFilterOperator_NotEqual();
|
130
144
|
const postFilterNotInOperator = new QueryBuilderPostFilterOperator_NotIn();
|
131
145
|
const postFilterState = tdsState.postFilterState;
|
132
|
-
|
133
|
-
|
146
|
+
|
147
|
+
const projectionColumnState = tdsState.projectionColumns
|
148
|
+
.filter((c) => c.columnName === event?.columnName)
|
134
149
|
.concat(
|
135
150
|
tdsState.aggregationState.columns
|
136
|
-
.filter((c) => c.columnName === event
|
151
|
+
.filter((c) => c.columnName === event?.columnName)
|
137
152
|
.map((ag) => ag.projectionColumnState),
|
138
153
|
)[0];
|
139
|
-
|
140
154
|
const getExistingPostFilterNode = (
|
141
155
|
operators: QueryBuilderPostFilterOperator[],
|
156
|
+
projectionColumnName: string | undefined,
|
142
157
|
): QueryBuilderPostFilterTreeNodeData | undefined =>
|
143
158
|
Array.from(postFilterState.nodes.values())
|
144
159
|
.filter(
|
@@ -150,7 +165,8 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
150
165
|
.filter(
|
151
166
|
(n) =>
|
152
167
|
(n as QueryBuilderPostFilterTreeConditionNodeData).condition
|
153
|
-
.columnState.columnName ===
|
168
|
+
.columnState.columnName ===
|
169
|
+
(projectionColumnName ?? projectionColumnState?.columnName) &&
|
154
170
|
operators
|
155
171
|
.map((op) => op.getLabel())
|
156
172
|
.includes(
|
@@ -162,8 +178,9 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
162
178
|
|
163
179
|
const updateFilterConditionValue = (
|
164
180
|
conditionValue: InstanceValue,
|
181
|
+
cellData: QueryBuilderTDSResultCellData,
|
165
182
|
): void => {
|
166
|
-
if (
|
183
|
+
if (cellData.value) {
|
167
184
|
instanceValue_setValue(
|
168
185
|
conditionValue,
|
169
186
|
conditionValue instanceof EnumValueInstanceValue
|
@@ -172,10 +189,10 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
172
189
|
(
|
173
190
|
conditionValue.genericType?.ownerReference
|
174
191
|
.value as Enumeration
|
175
|
-
).values.filter((v) => v.name ===
|
192
|
+
).values.filter((v) => v.name === cellData.value)[0],
|
176
193
|
),
|
177
194
|
)
|
178
|
-
:
|
195
|
+
: cellData.value,
|
179
196
|
0,
|
180
197
|
tdsState.queryBuilderState.observerContext,
|
181
198
|
);
|
@@ -184,15 +201,28 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
184
201
|
|
185
202
|
const generateNewPostFilterConditionNodeData = async (
|
186
203
|
operator: QueryBuilderPostFilterOperator,
|
204
|
+
cellData: QueryBuilderTDSResultCellData,
|
187
205
|
): Promise<void> => {
|
188
|
-
|
189
|
-
|
190
|
-
|
206
|
+
let postFilterConditionState: PostFilterConditionState;
|
207
|
+
try {
|
208
|
+
const possibleProjectionColumnState = cellData.columnName
|
209
|
+
? tdsState.projectionColumns
|
210
|
+
.filter((c) => c.columnName === cellData.columnName)
|
211
|
+
.concat(
|
212
|
+
tdsState.aggregationState.columns
|
213
|
+
.filter((c) => c.columnName === cellData.columnName)
|
214
|
+
.map((ag) => ag.projectionColumnState),
|
215
|
+
)[0]
|
216
|
+
: projectionColumnState;
|
217
|
+
|
218
|
+
if (possibleProjectionColumnState) {
|
219
|
+
postFilterConditionState = new PostFilterConditionState(
|
191
220
|
postFilterState,
|
192
|
-
|
221
|
+
possibleProjectionColumnState,
|
193
222
|
undefined,
|
194
223
|
operator,
|
195
224
|
);
|
225
|
+
|
196
226
|
if (
|
197
227
|
projectionColumnState instanceof
|
198
228
|
QueryBuilderDerivationProjectionColumnState
|
@@ -201,13 +231,16 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
201
231
|
projectionColumnState.fetchDerivationLambdaReturnType(),
|
202
232
|
);
|
203
233
|
}
|
234
|
+
|
204
235
|
const defaultFilterConditionValue =
|
205
236
|
postFilterConditionState.operator.getDefaultFilterConditionValue(
|
206
237
|
postFilterConditionState,
|
207
238
|
);
|
239
|
+
|
208
240
|
postFilterConditionState.setValue(defaultFilterConditionValue);
|
209
241
|
updateFilterConditionValue(
|
210
242
|
defaultFilterConditionValue as InstanceValue,
|
243
|
+
cellData,
|
211
244
|
);
|
212
245
|
postFilterState.addNodeFromNode(
|
213
246
|
new QueryBuilderPostFilterTreeConditionNodeData(
|
@@ -216,41 +249,56 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
216
249
|
),
|
217
250
|
undefined,
|
218
251
|
);
|
219
|
-
} catch (error) {
|
220
|
-
assertErrorThrown(error);
|
221
|
-
applicationStore.notificationService.notifyWarning(error.message);
|
222
|
-
return;
|
223
252
|
}
|
253
|
+
} catch (error) {
|
254
|
+
assertErrorThrown(error);
|
255
|
+
applicationStore.notificationService.notifyWarning(error.message);
|
256
|
+
return;
|
224
257
|
}
|
225
258
|
};
|
226
259
|
|
227
260
|
const updateExistingPostFilterConditionNodeData = (
|
228
261
|
existingPostFilterNode: QueryBuilderPostFilterTreeNodeData,
|
229
262
|
isFilterBy: boolean,
|
263
|
+
cellData: QueryBuilderTDSResultCellData,
|
264
|
+
operator: QueryBuilderPostFilterOperator,
|
230
265
|
): void => {
|
266
|
+
if (
|
267
|
+
operator === postFilterEmptyOperator ||
|
268
|
+
operator === postFilterNotEmptyOperator
|
269
|
+
) {
|
270
|
+
const conditionState = (
|
271
|
+
existingPostFilterNode as QueryBuilderPostFilterTreeConditionNodeData
|
272
|
+
).condition;
|
273
|
+
if (conditionState.operator.getLabel() !== operator.getLabel()) {
|
274
|
+
conditionState.changeOperator(
|
275
|
+
isFilterBy ? postFilterEmptyOperator : postFilterNotEmptyOperator,
|
276
|
+
);
|
277
|
+
}
|
278
|
+
return;
|
279
|
+
}
|
231
280
|
const conditionState = (
|
232
281
|
existingPostFilterNode as QueryBuilderPostFilterTreeConditionNodeData
|
233
282
|
).condition;
|
234
|
-
|
235
|
-
|
236
|
-
(isFilterBy
|
237
|
-
? postFilterEqualOperator
|
238
|
-
: postFilterNotEqualOperator
|
239
|
-
).getLabel()
|
240
|
-
) {
|
283
|
+
|
284
|
+
if (conditionState.operator.getLabel() === operator.getLabel()) {
|
241
285
|
const doesValueAlreadyExist =
|
242
286
|
conditionState.value instanceof InstanceValue &&
|
243
287
|
(conditionState.value instanceof EnumValueInstanceValue
|
244
288
|
? conditionState.value.values.map((ef) => ef.value.name)
|
245
289
|
: conditionState.value.values
|
246
|
-
).includes(
|
290
|
+
).includes(cellData.value);
|
291
|
+
|
247
292
|
if (!doesValueAlreadyExist) {
|
248
293
|
const currentValueSpecificaton = conditionState.value;
|
249
294
|
const newValueSpecification =
|
250
295
|
conditionState.operator.getDefaultFilterConditionValue(
|
251
296
|
conditionState,
|
252
297
|
);
|
253
|
-
updateFilterConditionValue(
|
298
|
+
updateFilterConditionValue(
|
299
|
+
newValueSpecification as InstanceValue,
|
300
|
+
cellData,
|
301
|
+
);
|
254
302
|
conditionState.changeOperator(
|
255
303
|
isFilterBy ? postFilterInOperator : postFilterNotInOperator,
|
256
304
|
);
|
@@ -271,12 +319,16 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
271
319
|
: (v as InstanceValue).values,
|
272
320
|
)
|
273
321
|
.flat()
|
274
|
-
.includes(event
|
322
|
+
.includes(cellData.value ?? event?.value);
|
323
|
+
|
275
324
|
if (!doesValueAlreadyExist) {
|
276
325
|
const newValueSpecification = (
|
277
326
|
isFilterBy ? postFilterEqualOperator : postFilterNotEqualOperator
|
278
327
|
).getDefaultFilterConditionValue(conditionState);
|
279
|
-
updateFilterConditionValue(
|
328
|
+
updateFilterConditionValue(
|
329
|
+
newValueSpecification as InstanceValue,
|
330
|
+
cellData,
|
331
|
+
);
|
280
332
|
instanceValue_setValues(
|
281
333
|
conditionState.value as InstanceValue,
|
282
334
|
[
|
@@ -289,32 +341,76 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
289
341
|
}
|
290
342
|
};
|
291
343
|
|
292
|
-
const
|
344
|
+
const getFilterOperator = (
|
345
|
+
isFilterBy: boolean,
|
346
|
+
cellData: QueryBuilderTDSResultCellData,
|
347
|
+
): QueryBuilderPostFilterOperator => {
|
348
|
+
if (isFilterBy === true) {
|
349
|
+
if (cellData.value === null) {
|
350
|
+
return postFilterEmptyOperator;
|
351
|
+
} else {
|
352
|
+
return postFilterEqualOperator;
|
353
|
+
}
|
354
|
+
} else {
|
355
|
+
if (cellData.value === null) {
|
356
|
+
return postFilterNotEmptyOperator;
|
357
|
+
} else {
|
358
|
+
return postFilterNotEqualOperator;
|
359
|
+
}
|
360
|
+
}
|
361
|
+
};
|
362
|
+
|
363
|
+
const filterByOrOutValue = (
|
364
|
+
isFilterBy: boolean,
|
365
|
+
cellData: QueryBuilderTDSResultCellData,
|
366
|
+
): void => {
|
293
367
|
tdsState.setShowPostFilterPanel(true);
|
368
|
+
|
369
|
+
const operator = getFilterOperator(isFilterBy, cellData);
|
370
|
+
|
294
371
|
const existingPostFilterNode = getExistingPostFilterNode(
|
295
|
-
|
372
|
+
cellData.value === null
|
373
|
+
? [postFilterEmptyOperator, postFilterNotEmptyOperator]
|
374
|
+
: isFilterBy
|
296
375
|
? [postFilterEqualOperator, postFilterInOperator]
|
297
376
|
: [postFilterNotEqualOperator, postFilterNotInOperator],
|
377
|
+
cellData.columnName,
|
298
378
|
);
|
379
|
+
|
299
380
|
existingPostFilterNode === undefined
|
300
|
-
? generateNewPostFilterConditionNodeData(
|
301
|
-
|
302
|
-
)
|
381
|
+
? generateNewPostFilterConditionNodeData(operator, cellData).catch(
|
382
|
+
applicationStore.alertUnhandledError,
|
383
|
+
)
|
303
384
|
: updateExistingPostFilterConditionNodeData(
|
304
385
|
existingPostFilterNode,
|
305
386
|
isFilterBy,
|
387
|
+
cellData,
|
388
|
+
operator,
|
306
389
|
);
|
307
390
|
};
|
308
391
|
|
392
|
+
const filterByOrOutValues = (isFilterBy: boolean): void => {
|
393
|
+
tdsState.queryBuilderState.resultState.selectedCells.forEach(
|
394
|
+
(cellData) => {
|
395
|
+
filterByOrOutValue(isFilterBy, cellData);
|
396
|
+
},
|
397
|
+
);
|
398
|
+
};
|
399
|
+
|
309
400
|
const handleCopyCellValue = applicationStore.guardUnhandledError(() =>
|
310
401
|
applicationStore.clipboardService.copyTextToClipboard(
|
311
|
-
event
|
402
|
+
event?.value?.toString() ?? '',
|
312
403
|
),
|
313
404
|
);
|
314
405
|
|
315
406
|
const handleCopyRowValue = applicationStore.guardUnhandledError(() =>
|
316
407
|
applicationStore.clipboardService.copyTextToClipboard(
|
317
|
-
|
408
|
+
tdsState.queryBuilderState.resultState
|
409
|
+
.findRowFromRowIndex(
|
410
|
+
tdsState.queryBuilderState.resultState.selectedCells[0]?.coordinates
|
411
|
+
.rowIndex ?? 0,
|
412
|
+
)
|
413
|
+
.toString(),
|
318
414
|
),
|
319
415
|
);
|
320
416
|
|
@@ -323,7 +419,7 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
323
419
|
<MenuContentItem
|
324
420
|
disabled={!projectionColumnState}
|
325
421
|
onClick={(): void => {
|
326
|
-
|
422
|
+
filterByOrOutValues(true);
|
327
423
|
}}
|
328
424
|
>
|
329
425
|
Filter By
|
@@ -331,7 +427,7 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
331
427
|
<MenuContentItem
|
332
428
|
disabled={!projectionColumnState}
|
333
429
|
onClick={(): void => {
|
334
|
-
|
430
|
+
filterByOrOutValues(false);
|
335
431
|
}}
|
336
432
|
>
|
337
433
|
Filter Out
|
@@ -348,18 +444,201 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
348
444
|
}),
|
349
445
|
);
|
350
446
|
|
447
|
+
type IQueryRendererParamsWithGridType = DataGridCellRendererParams & {
|
448
|
+
resultState: QueryBuilderResultState;
|
449
|
+
tdsExecutionResult: TDSExecutionResult;
|
450
|
+
};
|
451
|
+
|
452
|
+
const QueryResultCellRenderer = observer(
|
453
|
+
(params: IQueryRendererParamsWithGridType) => {
|
454
|
+
const resultState = params.resultState;
|
455
|
+
const tdsExecutionResult = params.tdsExecutionResult;
|
456
|
+
|
457
|
+
const cellValue = params.value as string;
|
458
|
+
const columnName = params.column?.getColId() ?? '';
|
459
|
+
|
460
|
+
const findCoordinatesFromResultValue = (
|
461
|
+
colId: string,
|
462
|
+
rowNumber: number,
|
463
|
+
): QueryBuilderTDSResultCellCoordinate => {
|
464
|
+
const colIndex = tdsExecutionResult.result.columns.findIndex(
|
465
|
+
(col) => col === colId,
|
466
|
+
);
|
467
|
+
|
468
|
+
return { rowIndex: rowNumber, colIndex: colIndex };
|
469
|
+
};
|
470
|
+
|
471
|
+
const currentCellCoordinates = findCoordinatesFromResultValue(
|
472
|
+
columnName,
|
473
|
+
params.rowIndex,
|
474
|
+
);
|
475
|
+
|
476
|
+
const cellInFilteredResults = resultState.selectedCells.some(
|
477
|
+
(result) =>
|
478
|
+
result.coordinates.colIndex === currentCellCoordinates.colIndex &&
|
479
|
+
result.coordinates.rowIndex === currentCellCoordinates.rowIndex,
|
480
|
+
);
|
481
|
+
|
482
|
+
const mouseDown: React.MouseEventHandler = (event) => {
|
483
|
+
event.preventDefault();
|
484
|
+
|
485
|
+
if (event.shiftKey) {
|
486
|
+
const coordinates = findCoordinatesFromResultValue(
|
487
|
+
columnName,
|
488
|
+
params.rowIndex,
|
489
|
+
);
|
490
|
+
const actualValue = resultState.findResultValueFromCoordinates([
|
491
|
+
coordinates.rowIndex,
|
492
|
+
coordinates.colIndex,
|
493
|
+
]);
|
494
|
+
resultState.addCellData({
|
495
|
+
value: actualValue,
|
496
|
+
columnName: columnName,
|
497
|
+
coordinates: coordinates,
|
498
|
+
});
|
499
|
+
return;
|
500
|
+
}
|
501
|
+
|
502
|
+
if (event.button === 0) {
|
503
|
+
resultState.setIsSelectingCells(true);
|
504
|
+
resultState.setSelectedCells([]);
|
505
|
+
const coordinates = findCoordinatesFromResultValue(
|
506
|
+
columnName,
|
507
|
+
params.rowIndex,
|
508
|
+
);
|
509
|
+
const actualValue = resultState.findResultValueFromCoordinates([
|
510
|
+
coordinates.rowIndex,
|
511
|
+
coordinates.colIndex,
|
512
|
+
]);
|
513
|
+
|
514
|
+
const rowNode = params.api.getRowNode(params.rowIndex.toString());
|
515
|
+
|
516
|
+
if (rowNode) {
|
517
|
+
params.api.refreshCells({
|
518
|
+
force: true,
|
519
|
+
columns: [columnName],
|
520
|
+
rowNodes: [rowNode],
|
521
|
+
});
|
522
|
+
}
|
523
|
+
resultState.setSelectedCells([
|
524
|
+
{
|
525
|
+
value: actualValue,
|
526
|
+
columnName: columnName,
|
527
|
+
coordinates: coordinates,
|
528
|
+
},
|
529
|
+
]);
|
530
|
+
}
|
531
|
+
};
|
532
|
+
const mouseUp: React.MouseEventHandler = (event) => {
|
533
|
+
resultState.setIsSelectingCells(false);
|
534
|
+
};
|
535
|
+
|
536
|
+
const mouseOver: React.MouseEventHandler = (event) => {
|
537
|
+
if (resultState.isSelectingCells) {
|
538
|
+
if (resultState.selectedCells.length < 1) {
|
539
|
+
return;
|
540
|
+
}
|
541
|
+
const results = resultState.selectedCells[0];
|
542
|
+
if (!results) {
|
543
|
+
return;
|
544
|
+
}
|
545
|
+
|
546
|
+
const firstCorner = results.coordinates;
|
547
|
+
const secondCorner = findCoordinatesFromResultValue(
|
548
|
+
columnName,
|
549
|
+
params.rowIndex,
|
550
|
+
);
|
551
|
+
|
552
|
+
resultState.setSelectedCells([results]);
|
553
|
+
|
554
|
+
const minRow = Math.min(firstCorner.rowIndex, secondCorner.rowIndex);
|
555
|
+
const minCol = Math.min(firstCorner.colIndex, secondCorner.colIndex);
|
556
|
+
const maxRow = Math.max(firstCorner.rowIndex, secondCorner.rowIndex);
|
557
|
+
const maxCol = Math.max(firstCorner.colIndex, secondCorner.colIndex);
|
558
|
+
|
559
|
+
for (let x = minRow; x <= maxRow; x++) {
|
560
|
+
for (let y = minCol; y <= maxCol; y++) {
|
561
|
+
const actualValue = resultState.findResultValueFromCoordinates([
|
562
|
+
x,
|
563
|
+
y,
|
564
|
+
]);
|
565
|
+
|
566
|
+
const valueAndColumnId = {
|
567
|
+
value: actualValue,
|
568
|
+
columnName: resultState.findColumnFromCoordinates(y),
|
569
|
+
coordinates: {
|
570
|
+
rowIndex: x,
|
571
|
+
colIndex: y,
|
572
|
+
},
|
573
|
+
} as QueryBuilderTDSResultCellData;
|
574
|
+
|
575
|
+
if (
|
576
|
+
!resultState.selectedCells.find(
|
577
|
+
(result) =>
|
578
|
+
result.coordinates.colIndex === y &&
|
579
|
+
result.coordinates.rowIndex === x,
|
580
|
+
)
|
581
|
+
) {
|
582
|
+
resultState.addCellData(valueAndColumnId);
|
583
|
+
}
|
584
|
+
}
|
585
|
+
}
|
586
|
+
}
|
587
|
+
|
588
|
+
resultState.setMouseOverCell(resultState.selectedCells[0] ?? null);
|
589
|
+
};
|
590
|
+
|
591
|
+
const fetchStructureImplementation =
|
592
|
+
resultState.queryBuilderState.fetchStructureState.implementation;
|
593
|
+
|
594
|
+
return (
|
595
|
+
<ContextMenu
|
596
|
+
content={
|
597
|
+
// NOTE: we only support this functionality for grid result with a projection fetch-structure
|
598
|
+
fetchStructureImplementation instanceof QueryBuilderTDSState ? (
|
599
|
+
<QueryBuilderGridResultContextMenu
|
600
|
+
event={resultState.mousedOverCell}
|
601
|
+
tdsState={fetchStructureImplementation}
|
602
|
+
/>
|
603
|
+
) : null
|
604
|
+
}
|
605
|
+
disabled={
|
606
|
+
!(
|
607
|
+
resultState.queryBuilderState.fetchStructureState
|
608
|
+
.implementation instanceof QueryBuilderTDSState
|
609
|
+
) ||
|
610
|
+
!resultState.queryBuilderState.isQuerySupported ||
|
611
|
+
!resultState.mousedOverCell
|
612
|
+
}
|
613
|
+
menuProps={{ elevation: 7 }}
|
614
|
+
key={params.value as string}
|
615
|
+
className={clsx('ag-theme-balham-dark query-builder__result__tds-grid')}
|
616
|
+
>
|
617
|
+
<div
|
618
|
+
className={clsx('query-builder__result__values__table__cell', {
|
619
|
+
'query-builder__result__values__table__cell--active':
|
620
|
+
cellInFilteredResults,
|
621
|
+
})}
|
622
|
+
onMouseDown={(event) => mouseDown(event)}
|
623
|
+
onMouseUp={(event) => mouseUp(event)}
|
624
|
+
onMouseOver={(event) => mouseOver(event)}
|
625
|
+
>
|
626
|
+
<span>{cellValue}</span>
|
627
|
+
</div>
|
628
|
+
</ContextMenu>
|
629
|
+
);
|
630
|
+
},
|
631
|
+
);
|
632
|
+
|
351
633
|
const QueryBuilderGridResult = observer(
|
352
634
|
(props: {
|
353
635
|
executionResult: TDSExecutionResult;
|
354
636
|
queryBuilderState: QueryBuilderState;
|
355
637
|
}) => {
|
356
638
|
const { executionResult, queryBuilderState } = props;
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
null,
|
361
|
-
);
|
362
|
-
const columns = executionResult.result.columns;
|
639
|
+
|
640
|
+
const resultState = queryBuilderState.resultState;
|
641
|
+
|
363
642
|
const rowData = executionResult.result.rows.map((_row, rowIdx) => {
|
364
643
|
const row: PlainObject = {};
|
365
644
|
const cols = executionResult.result.columns;
|
@@ -369,57 +648,42 @@ const QueryBuilderGridResult = observer(
|
|
369
648
|
// See https://github.com/finos/legend-studio/issues/1008
|
370
649
|
row[cols[colIdx] as string] = isBoolean(value) ? String(value) : value;
|
371
650
|
});
|
651
|
+
|
372
652
|
row.rowNumber = rowIdx;
|
373
653
|
return row;
|
374
654
|
});
|
375
655
|
|
376
656
|
return (
|
377
|
-
<
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
// options use the data belonging to the row that they are
|
408
|
-
// in. hence why we set the cell every time we mouse over
|
409
|
-
// rather than making user click multiple times.
|
410
|
-
onCellMouseOver={(event): void => {
|
411
|
-
cellDoubleClickedEvent.current = event;
|
412
|
-
}}
|
413
|
-
suppressFieldDotNotation={true}
|
414
|
-
columnDefs={columns.map((colName) => ({
|
415
|
-
minWidth: 50,
|
416
|
-
sortable: true,
|
417
|
-
resizable: true,
|
418
|
-
field: colName,
|
419
|
-
flex: 1,
|
420
|
-
}))}
|
421
|
-
/>
|
422
|
-
</ContextMenu>
|
657
|
+
<div className="query-builder__result__values__table">
|
658
|
+
<div
|
659
|
+
className={clsx(
|
660
|
+
'ag-theme-balham-dark query-builder__result__tds-grid',
|
661
|
+
)}
|
662
|
+
>
|
663
|
+
<DataGrid
|
664
|
+
rowData={rowData}
|
665
|
+
gridOptions={{
|
666
|
+
suppressScrollOnNewData: true,
|
667
|
+
getRowId: function (data) {
|
668
|
+
return data.data.rowNumber as string;
|
669
|
+
},
|
670
|
+
}}
|
671
|
+
suppressFieldDotNotation={true}
|
672
|
+
columnDefs={executionResult.result.columns.map((colName) => ({
|
673
|
+
minWidth: 50,
|
674
|
+
sortable: true,
|
675
|
+
resizable: true,
|
676
|
+
field: colName,
|
677
|
+
flex: 1,
|
678
|
+
cellRenderer: QueryResultCellRenderer,
|
679
|
+
cellRendererParams: {
|
680
|
+
resultState: resultState,
|
681
|
+
tdsExecutionResult: executionResult,
|
682
|
+
},
|
683
|
+
}))}
|
684
|
+
/>
|
685
|
+
</div>
|
686
|
+
</div>
|
423
687
|
);
|
424
688
|
},
|
425
689
|
);
|
@@ -531,6 +795,7 @@ export const QueryBuilderResultPanel = observer(
|
|
531
795
|
!queryBuilderState.isQuerySupported || isSupportedQueryValid;
|
532
796
|
|
533
797
|
const runQuery = (): void => {
|
798
|
+
resultState.setSelectedCells([]);
|
534
799
|
resultState.pressedRunQuery.inProgress();
|
535
800
|
if (queryParametersState.parameterStates.length) {
|
536
801
|
queryParametersState.parameterValuesEditorState.open(
|
@@ -564,6 +829,7 @@ export const QueryBuilderResultPanel = observer(
|
|
564
829
|
val === '' ? 0 : parseInt(val, 10),
|
565
830
|
);
|
566
831
|
};
|
832
|
+
|
567
833
|
const allowSettingPreviewLimit = queryBuilderState.isQuerySupported;
|
568
834
|
|
569
835
|
const copyExpression = (value: string): void => {
|