@finos/legend-query-builder 4.0.8 → 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/__lib__/QueryBuilderColorTheme.js +1 -1
- package/lib/__lib__/QueryBuilderColorTheme.js.map +1 -1
- package/lib/__lib__/QueryBuilderDocumentation.js +1 -1
- package/lib/__lib__/QueryBuilderDocumentation.js.map +1 -1
- package/lib/__lib__/QueryBuilderEvent.js +3 -3
- package/lib/__lib__/QueryBuilderEvent.js.map +1 -1
- package/lib/__lib__/QueryBuilderSetting.js +1 -1
- package/lib/__lib__/QueryBuilderSetting.js.map +1 -1
- package/lib/__lib__/QueryBuilderTesting.js +1 -1
- package/lib/__lib__/QueryBuilderTesting.js.map +1 -1
- package/lib/components/QueryBuilderComponentElement.js +1 -1
- package/lib/components/QueryBuilderComponentElement.js.map +1 -1
- package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
- package/lib/components/QueryBuilderResultPanel.js +210 -69
- package/lib/components/QueryBuilderResultPanel.js.map +1 -1
- package/lib/components/QueryBuilder_LegendApplicationPlugin.js +1 -2
- package/lib/components/QueryBuilder_LegendApplicationPlugin.js.map +1 -1
- package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts.map +1 -1
- package/lib/components/explorer/QueryBuilderExplorerPanel.js +3 -3
- package/lib/components/explorer/QueryBuilderExplorerPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderFetchStructurePanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderFetchStructurePanel.js +3 -3
- package/lib/components/fetch-structure/QueryBuilderFetchStructurePanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +60 -21
- package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +10 -2
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js +2 -2
- package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js.map +1 -1
- package/lib/components/filter/QueryBuilderFilterPanel.d.ts +4 -0
- package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
- package/lib/components/filter/QueryBuilderFilterPanel.js +69 -31
- package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
- package/lib/components/shared/CustomDatePicker.js +1 -1
- package/lib/components/shared/CustomDatePicker.js.map +1 -1
- package/lib/graph/QueryBuilderMetaModelConst.js +3 -3
- package/lib/graph/QueryBuilderMetaModelConst.js.map +1 -1
- package/lib/graph-manager/QueryBuilderConst.js +1 -1
- package/lib/graph-manager/QueryBuilderConst.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/V1_QueryBuilder_PureGraphManagerExtension.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/V1_QueryBuilder_PureGraphManagerExtension.js +4 -4
- package/lib/graph-manager/protocol/pure/v1/V1_QueryBuilder_PureGraphManagerExtension.js.map +1 -1
- package/lib/index.css +17 -1
- package/lib/index.css.map +1 -1
- package/lib/package.json +7 -7
- package/lib/stores/QueryBuilderChangeDetectionState.js +1 -1
- package/lib/stores/QueryBuilderChangeDetectionState.js.map +1 -1
- package/lib/stores/QueryBuilderCommand.js +1 -1
- package/lib/stores/QueryBuilderCommand.js.map +1 -1
- package/lib/stores/QueryBuilderConfig.js +2 -2
- package/lib/stores/QueryBuilderConfig.js.map +1 -1
- package/lib/stores/QueryBuilderGroupOperationHelper.js +1 -1
- package/lib/stores/QueryBuilderGroupOperationHelper.js.map +1 -1
- 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/QueryBuilderStateHashUtils.js +1 -1
- package/lib/stores/QueryBuilderStateHashUtils.js.map +1 -1
- package/lib/stores/QueryBuilderTextEditorState.js +1 -1
- package/lib/stores/QueryBuilderTextEditorState.js.map +1 -1
- package/lib/stores/execution-plan/ExecutionPlanState.js +1 -1
- package/lib/stores/execution-plan/ExecutionPlanState.js.map +1 -1
- package/lib/stores/explorer/QueryBuilderExplorerState.js +1 -1
- package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
- package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.js +1 -1
- package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.js.map +1 -1
- package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js +2 -2
- package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js.map +1 -1
- package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js +1 -1
- package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js.map +1 -1
- package/lib/stores/fetch-structure/tds/QueryResultSetModifierState.js +1 -1
- package/lib/stores/fetch-structure/tds/QueryResultSetModifierState.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 +2 -2
- package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.js +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
- package/lib/stores/shared/LambdaParameterState.d.ts.map +1 -1
- package/lib/stores/shared/LambdaParameterState.js +2 -2
- 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 +15 -15
- package/src/components/QueryBuilderResultPanel.tsx +358 -93
- package/src/components/explorer/QueryBuilderExplorerPanel.tsx +10 -14
- package/src/components/fetch-structure/QueryBuilderFetchStructurePanel.tsx +6 -4
- package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +103 -14
- package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +18 -1
- package/src/components/fetch-structure/QueryBuilderTDSWindowPanel.tsx +12 -10
- package/src/components/filter/QueryBuilderFilterPanel.tsx +134 -42
- package/src/graph-manager/protocol/pure/v1/V1_QueryBuilder_PureGraphManagerExtension.ts +4 -5
- 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
|
@@ -66,10 +66,9 @@ import {
|
|
|
66
66
|
isBoolean,
|
|
67
67
|
type PlainObject,
|
|
68
68
|
prettyDuration,
|
|
69
|
-
prettyCONSTName,
|
|
70
69
|
filterByType,
|
|
71
70
|
} from '@finos/legend-shared';
|
|
72
|
-
import {
|
|
71
|
+
import { forwardRef, useState } from 'react';
|
|
73
72
|
import {
|
|
74
73
|
QueryBuilderDerivationProjectionColumnState,
|
|
75
74
|
QueryBuilderProjectionColumnState,
|
|
@@ -97,13 +96,22 @@ import { PARAMETER_SUBMIT_ACTION } from '../stores/shared/LambdaParameterState.j
|
|
|
97
96
|
import { QUERY_BUILDER_TEST_ID } from '../__lib__/QueryBuilderTesting.js';
|
|
98
97
|
import {
|
|
99
98
|
DataGrid,
|
|
100
|
-
type
|
|
99
|
+
type DataGridCellRendererParams,
|
|
101
100
|
} from '@finos/legend-lego/data-grid';
|
|
102
101
|
import {
|
|
103
102
|
CODE_EDITOR_LANGUAGE,
|
|
104
103
|
CodeEditor,
|
|
105
104
|
} from '@finos/legend-lego/code-editor';
|
|
106
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';
|
|
107
115
|
|
|
108
116
|
export const tryToFormatSql = (sql: string): string => {
|
|
109
117
|
try {
|
|
@@ -118,7 +126,7 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
|
118
126
|
forwardRef<
|
|
119
127
|
HTMLDivElement,
|
|
120
128
|
{
|
|
121
|
-
event:
|
|
129
|
+
event: QueryBuilderTDSResultCellData | null;
|
|
122
130
|
tdsState: QueryBuilderTDSState;
|
|
123
131
|
}
|
|
124
132
|
>(function QueryBuilderResultContextMenu(props, ref) {
|
|
@@ -126,20 +134,26 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
|
126
134
|
const applicationStore = useApplicationStore();
|
|
127
135
|
const postFilterEqualOperator = new QueryBuilderPostFilterOperator_Equal();
|
|
128
136
|
const postFilterInOperator = new QueryBuilderPostFilterOperator_In();
|
|
137
|
+
const postFilterEmptyOperator =
|
|
138
|
+
new QueryBuilderPostFilterOperator_IsEmpty();
|
|
139
|
+
const postFilterNotEmptyOperator =
|
|
140
|
+
new QueryBuilderPostFilterOperator_IsNotEmpty();
|
|
141
|
+
|
|
129
142
|
const postFilterNotEqualOperator =
|
|
130
143
|
new QueryBuilderPostFilterOperator_NotEqual();
|
|
131
144
|
const postFilterNotInOperator = new QueryBuilderPostFilterOperator_NotIn();
|
|
132
145
|
const postFilterState = tdsState.postFilterState;
|
|
133
|
-
|
|
134
|
-
|
|
146
|
+
|
|
147
|
+
const projectionColumnState = tdsState.projectionColumns
|
|
148
|
+
.filter((c) => c.columnName === event?.columnName)
|
|
135
149
|
.concat(
|
|
136
150
|
tdsState.aggregationState.columns
|
|
137
|
-
.filter((c) => c.columnName === event
|
|
151
|
+
.filter((c) => c.columnName === event?.columnName)
|
|
138
152
|
.map((ag) => ag.projectionColumnState),
|
|
139
153
|
)[0];
|
|
140
|
-
|
|
141
154
|
const getExistingPostFilterNode = (
|
|
142
155
|
operators: QueryBuilderPostFilterOperator[],
|
|
156
|
+
projectionColumnName: string | undefined,
|
|
143
157
|
): QueryBuilderPostFilterTreeNodeData | undefined =>
|
|
144
158
|
Array.from(postFilterState.nodes.values())
|
|
145
159
|
.filter(
|
|
@@ -151,7 +165,8 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
|
151
165
|
.filter(
|
|
152
166
|
(n) =>
|
|
153
167
|
(n as QueryBuilderPostFilterTreeConditionNodeData).condition
|
|
154
|
-
.columnState.columnName ===
|
|
168
|
+
.columnState.columnName ===
|
|
169
|
+
(projectionColumnName ?? projectionColumnState?.columnName) &&
|
|
155
170
|
operators
|
|
156
171
|
.map((op) => op.getLabel())
|
|
157
172
|
.includes(
|
|
@@ -163,8 +178,9 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
|
163
178
|
|
|
164
179
|
const updateFilterConditionValue = (
|
|
165
180
|
conditionValue: InstanceValue,
|
|
181
|
+
cellData: QueryBuilderTDSResultCellData,
|
|
166
182
|
): void => {
|
|
167
|
-
if (
|
|
183
|
+
if (cellData.value) {
|
|
168
184
|
instanceValue_setValue(
|
|
169
185
|
conditionValue,
|
|
170
186
|
conditionValue instanceof EnumValueInstanceValue
|
|
@@ -173,10 +189,10 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
|
173
189
|
(
|
|
174
190
|
conditionValue.genericType?.ownerReference
|
|
175
191
|
.value as Enumeration
|
|
176
|
-
).values.filter((v) => v.name ===
|
|
192
|
+
).values.filter((v) => v.name === cellData.value)[0],
|
|
177
193
|
),
|
|
178
194
|
)
|
|
179
|
-
:
|
|
195
|
+
: cellData.value,
|
|
180
196
|
0,
|
|
181
197
|
tdsState.queryBuilderState.observerContext,
|
|
182
198
|
);
|
|
@@ -185,15 +201,28 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
|
185
201
|
|
|
186
202
|
const generateNewPostFilterConditionNodeData = async (
|
|
187
203
|
operator: QueryBuilderPostFilterOperator,
|
|
204
|
+
cellData: QueryBuilderTDSResultCellData,
|
|
188
205
|
): Promise<void> => {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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(
|
|
192
220
|
postFilterState,
|
|
193
|
-
|
|
221
|
+
possibleProjectionColumnState,
|
|
194
222
|
undefined,
|
|
195
223
|
operator,
|
|
196
224
|
);
|
|
225
|
+
|
|
197
226
|
if (
|
|
198
227
|
projectionColumnState instanceof
|
|
199
228
|
QueryBuilderDerivationProjectionColumnState
|
|
@@ -202,13 +231,16 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
|
202
231
|
projectionColumnState.fetchDerivationLambdaReturnType(),
|
|
203
232
|
);
|
|
204
233
|
}
|
|
234
|
+
|
|
205
235
|
const defaultFilterConditionValue =
|
|
206
236
|
postFilterConditionState.operator.getDefaultFilterConditionValue(
|
|
207
237
|
postFilterConditionState,
|
|
208
238
|
);
|
|
239
|
+
|
|
209
240
|
postFilterConditionState.setValue(defaultFilterConditionValue);
|
|
210
241
|
updateFilterConditionValue(
|
|
211
242
|
defaultFilterConditionValue as InstanceValue,
|
|
243
|
+
cellData,
|
|
212
244
|
);
|
|
213
245
|
postFilterState.addNodeFromNode(
|
|
214
246
|
new QueryBuilderPostFilterTreeConditionNodeData(
|
|
@@ -217,41 +249,56 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
|
217
249
|
),
|
|
218
250
|
undefined,
|
|
219
251
|
);
|
|
220
|
-
} catch (error) {
|
|
221
|
-
assertErrorThrown(error);
|
|
222
|
-
applicationStore.notificationService.notifyWarning(error.message);
|
|
223
|
-
return;
|
|
224
252
|
}
|
|
253
|
+
} catch (error) {
|
|
254
|
+
assertErrorThrown(error);
|
|
255
|
+
applicationStore.notificationService.notifyWarning(error.message);
|
|
256
|
+
return;
|
|
225
257
|
}
|
|
226
258
|
};
|
|
227
259
|
|
|
228
260
|
const updateExistingPostFilterConditionNodeData = (
|
|
229
261
|
existingPostFilterNode: QueryBuilderPostFilterTreeNodeData,
|
|
230
262
|
isFilterBy: boolean,
|
|
263
|
+
cellData: QueryBuilderTDSResultCellData,
|
|
264
|
+
operator: QueryBuilderPostFilterOperator,
|
|
231
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
|
+
}
|
|
232
280
|
const conditionState = (
|
|
233
281
|
existingPostFilterNode as QueryBuilderPostFilterTreeConditionNodeData
|
|
234
282
|
).condition;
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
(isFilterBy
|
|
238
|
-
? postFilterEqualOperator
|
|
239
|
-
: postFilterNotEqualOperator
|
|
240
|
-
).getLabel()
|
|
241
|
-
) {
|
|
283
|
+
|
|
284
|
+
if (conditionState.operator.getLabel() === operator.getLabel()) {
|
|
242
285
|
const doesValueAlreadyExist =
|
|
243
286
|
conditionState.value instanceof InstanceValue &&
|
|
244
287
|
(conditionState.value instanceof EnumValueInstanceValue
|
|
245
288
|
? conditionState.value.values.map((ef) => ef.value.name)
|
|
246
289
|
: conditionState.value.values
|
|
247
|
-
).includes(
|
|
290
|
+
).includes(cellData.value);
|
|
291
|
+
|
|
248
292
|
if (!doesValueAlreadyExist) {
|
|
249
293
|
const currentValueSpecificaton = conditionState.value;
|
|
250
294
|
const newValueSpecification =
|
|
251
295
|
conditionState.operator.getDefaultFilterConditionValue(
|
|
252
296
|
conditionState,
|
|
253
297
|
);
|
|
254
|
-
updateFilterConditionValue(
|
|
298
|
+
updateFilterConditionValue(
|
|
299
|
+
newValueSpecification as InstanceValue,
|
|
300
|
+
cellData,
|
|
301
|
+
);
|
|
255
302
|
conditionState.changeOperator(
|
|
256
303
|
isFilterBy ? postFilterInOperator : postFilterNotInOperator,
|
|
257
304
|
);
|
|
@@ -272,12 +319,16 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
|
272
319
|
: (v as InstanceValue).values,
|
|
273
320
|
)
|
|
274
321
|
.flat()
|
|
275
|
-
.includes(event
|
|
322
|
+
.includes(cellData.value ?? event?.value);
|
|
323
|
+
|
|
276
324
|
if (!doesValueAlreadyExist) {
|
|
277
325
|
const newValueSpecification = (
|
|
278
326
|
isFilterBy ? postFilterEqualOperator : postFilterNotEqualOperator
|
|
279
327
|
).getDefaultFilterConditionValue(conditionState);
|
|
280
|
-
updateFilterConditionValue(
|
|
328
|
+
updateFilterConditionValue(
|
|
329
|
+
newValueSpecification as InstanceValue,
|
|
330
|
+
cellData,
|
|
331
|
+
);
|
|
281
332
|
instanceValue_setValues(
|
|
282
333
|
conditionState.value as InstanceValue,
|
|
283
334
|
[
|
|
@@ -290,32 +341,76 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
|
290
341
|
}
|
|
291
342
|
};
|
|
292
343
|
|
|
293
|
-
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 => {
|
|
294
367
|
tdsState.setShowPostFilterPanel(true);
|
|
368
|
+
|
|
369
|
+
const operator = getFilterOperator(isFilterBy, cellData);
|
|
370
|
+
|
|
295
371
|
const existingPostFilterNode = getExistingPostFilterNode(
|
|
296
|
-
|
|
372
|
+
cellData.value === null
|
|
373
|
+
? [postFilterEmptyOperator, postFilterNotEmptyOperator]
|
|
374
|
+
: isFilterBy
|
|
297
375
|
? [postFilterEqualOperator, postFilterInOperator]
|
|
298
376
|
: [postFilterNotEqualOperator, postFilterNotInOperator],
|
|
377
|
+
cellData.columnName,
|
|
299
378
|
);
|
|
379
|
+
|
|
300
380
|
existingPostFilterNode === undefined
|
|
301
|
-
? generateNewPostFilterConditionNodeData(
|
|
302
|
-
|
|
303
|
-
)
|
|
381
|
+
? generateNewPostFilterConditionNodeData(operator, cellData).catch(
|
|
382
|
+
applicationStore.alertUnhandledError,
|
|
383
|
+
)
|
|
304
384
|
: updateExistingPostFilterConditionNodeData(
|
|
305
385
|
existingPostFilterNode,
|
|
306
386
|
isFilterBy,
|
|
387
|
+
cellData,
|
|
388
|
+
operator,
|
|
307
389
|
);
|
|
308
390
|
};
|
|
309
391
|
|
|
392
|
+
const filterByOrOutValues = (isFilterBy: boolean): void => {
|
|
393
|
+
tdsState.queryBuilderState.resultState.selectedCells.forEach(
|
|
394
|
+
(cellData) => {
|
|
395
|
+
filterByOrOutValue(isFilterBy, cellData);
|
|
396
|
+
},
|
|
397
|
+
);
|
|
398
|
+
};
|
|
399
|
+
|
|
310
400
|
const handleCopyCellValue = applicationStore.guardUnhandledError(() =>
|
|
311
401
|
applicationStore.clipboardService.copyTextToClipboard(
|
|
312
|
-
event
|
|
402
|
+
event?.value?.toString() ?? '',
|
|
313
403
|
),
|
|
314
404
|
);
|
|
315
405
|
|
|
316
406
|
const handleCopyRowValue = applicationStore.guardUnhandledError(() =>
|
|
317
407
|
applicationStore.clipboardService.copyTextToClipboard(
|
|
318
|
-
|
|
408
|
+
tdsState.queryBuilderState.resultState
|
|
409
|
+
.findRowFromRowIndex(
|
|
410
|
+
tdsState.queryBuilderState.resultState.selectedCells[0]?.coordinates
|
|
411
|
+
.rowIndex ?? 0,
|
|
412
|
+
)
|
|
413
|
+
.toString(),
|
|
319
414
|
),
|
|
320
415
|
);
|
|
321
416
|
|
|
@@ -324,7 +419,7 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
|
324
419
|
<MenuContentItem
|
|
325
420
|
disabled={!projectionColumnState}
|
|
326
421
|
onClick={(): void => {
|
|
327
|
-
|
|
422
|
+
filterByOrOutValues(true);
|
|
328
423
|
}}
|
|
329
424
|
>
|
|
330
425
|
Filter By
|
|
@@ -332,7 +427,7 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
|
332
427
|
<MenuContentItem
|
|
333
428
|
disabled={!projectionColumnState}
|
|
334
429
|
onClick={(): void => {
|
|
335
|
-
|
|
430
|
+
filterByOrOutValues(false);
|
|
336
431
|
}}
|
|
337
432
|
>
|
|
338
433
|
Filter Out
|
|
@@ -349,18 +444,201 @@ const QueryBuilderGridResultContextMenu = observer(
|
|
|
349
444
|
}),
|
|
350
445
|
);
|
|
351
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
|
+
|
|
352
633
|
const QueryBuilderGridResult = observer(
|
|
353
634
|
(props: {
|
|
354
635
|
executionResult: TDSExecutionResult;
|
|
355
636
|
queryBuilderState: QueryBuilderState;
|
|
356
637
|
}) => {
|
|
357
638
|
const { executionResult, queryBuilderState } = props;
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
null,
|
|
362
|
-
);
|
|
363
|
-
const columns = executionResult.result.columns;
|
|
639
|
+
|
|
640
|
+
const resultState = queryBuilderState.resultState;
|
|
641
|
+
|
|
364
642
|
const rowData = executionResult.result.rows.map((_row, rowIdx) => {
|
|
365
643
|
const row: PlainObject = {};
|
|
366
644
|
const cols = executionResult.result.columns;
|
|
@@ -370,57 +648,42 @@ const QueryBuilderGridResult = observer(
|
|
|
370
648
|
// See https://github.com/finos/legend-studio/issues/1008
|
|
371
649
|
row[cols[colIdx] as string] = isBoolean(value) ? String(value) : value;
|
|
372
650
|
});
|
|
651
|
+
|
|
373
652
|
row.rowNumber = rowIdx;
|
|
374
653
|
return row;
|
|
375
654
|
});
|
|
376
655
|
|
|
377
656
|
return (
|
|
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
|
-
|
|
408
|
-
// options use the data belonging to the row that they are
|
|
409
|
-
// in. hence why we set the cell every time we mouse over
|
|
410
|
-
// rather than making user click multiple times.
|
|
411
|
-
onCellMouseOver={(event): void => {
|
|
412
|
-
cellDoubleClickedEvent.current = event;
|
|
413
|
-
}}
|
|
414
|
-
suppressFieldDotNotation={true}
|
|
415
|
-
columnDefs={columns.map((colName) => ({
|
|
416
|
-
minWidth: 50,
|
|
417
|
-
sortable: true,
|
|
418
|
-
resizable: true,
|
|
419
|
-
field: colName,
|
|
420
|
-
flex: 1,
|
|
421
|
-
}))}
|
|
422
|
-
/>
|
|
423
|
-
</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>
|
|
424
687
|
);
|
|
425
688
|
},
|
|
426
689
|
);
|
|
@@ -532,6 +795,7 @@ export const QueryBuilderResultPanel = observer(
|
|
|
532
795
|
!queryBuilderState.isQuerySupported || isSupportedQueryValid;
|
|
533
796
|
|
|
534
797
|
const runQuery = (): void => {
|
|
798
|
+
resultState.setSelectedCells([]);
|
|
535
799
|
resultState.pressedRunQuery.inProgress();
|
|
536
800
|
if (queryParametersState.parameterStates.length) {
|
|
537
801
|
queryParametersState.parameterValuesEditorState.open(
|
|
@@ -565,6 +829,7 @@ export const QueryBuilderResultPanel = observer(
|
|
|
565
829
|
val === '' ? 0 : parseInt(val, 10),
|
|
566
830
|
);
|
|
567
831
|
};
|
|
832
|
+
|
|
568
833
|
const allowSettingPreviewLimit = queryBuilderState.isQuerySupported;
|
|
569
834
|
|
|
570
835
|
const copyExpression = (value: string): void => {
|
|
@@ -773,7 +1038,7 @@ export const QueryBuilderResultPanel = observer(
|
|
|
773
1038
|
className="query-builder__result__export__dropdown__menu__item"
|
|
774
1039
|
onClick={(): void => confirmExport(format)}
|
|
775
1040
|
>
|
|
776
|
-
{
|
|
1041
|
+
{format}
|
|
777
1042
|
</MenuContentItem>
|
|
778
1043
|
))}
|
|
779
1044
|
</MenuContent>
|