@finos/legend-query-builder 0.6.26 → 0.6.28
Sign up to get free protection for your applications and to get access to all the features.
- package/lib/components/QueryBuilder.d.ts.map +1 -1
- package/lib/components/QueryBuilder.js +29 -28
- package/lib/components/QueryBuilder.js.map +1 -1
- package/lib/components/QueryBuilderComponentTestUtils.d.ts.map +1 -1
- package/lib/components/QueryBuilderComponentTestUtils.js +4 -5
- package/lib/components/QueryBuilderComponentTestUtils.js.map +1 -1
- package/lib/components/QueryBuilderConstantExpressionPanel.d.ts.map +1 -1
- package/lib/components/QueryBuilderConstantExpressionPanel.js +5 -4
- package/lib/components/QueryBuilderConstantExpressionPanel.js.map +1 -1
- package/lib/components/QueryBuilderDiffPanel.d.ts.map +1 -1
- package/lib/components/QueryBuilderDiffPanel.js +2 -2
- package/lib/components/QueryBuilderDiffPanel.js.map +1 -1
- package/lib/components/QueryBuilderParametersPanel.d.ts.map +1 -1
- package/lib/components/QueryBuilderParametersPanel.js +13 -8
- package/lib/components/QueryBuilderParametersPanel.js.map +1 -1
- package/lib/components/QueryBuilderPropertyExpressionEditor.d.ts.map +1 -1
- package/lib/components/QueryBuilderPropertyExpressionEditor.js +10 -2
- package/lib/components/QueryBuilderPropertyExpressionEditor.js.map +1 -1
- package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
- package/lib/components/QueryBuilderResultPanel.js +17 -1
- package/lib/components/QueryBuilderResultPanel.js.map +1 -1
- package/lib/components/QueryBuilder_TestID.d.ts +3 -1
- package/lib/components/QueryBuilder_TestID.d.ts.map +1 -1
- package/lib/components/QueryBuilder_TestID.js +2 -0
- package/lib/components/QueryBuilder_TestID.js.map +1 -1
- package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts.map +1 -1
- package/lib/components/explorer/QueryBuilderExplorerPanel.js +2 -2
- package/lib/components/explorer/QueryBuilderExplorerPanel.js.map +1 -1
- package/lib/components/explorer/QueryBuilderMilestoningEditor.d.ts.map +1 -1
- package/lib/components/explorer/QueryBuilderMilestoningEditor.js +2 -2
- package/lib/components/explorer/QueryBuilderMilestoningEditor.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/shared/CustomDatePicker.d.ts +33 -0
- package/lib/components/shared/CustomDatePicker.d.ts.map +1 -1
- package/lib/components/shared/CustomDatePicker.js +4 -4
- package/lib/components/shared/CustomDatePicker.js.map +1 -1
- package/lib/components/shared/QueryBuilderVariableSelector.d.ts +1 -1
- package/lib/components/shared/QueryBuilderVariableSelector.d.ts.map +1 -1
- package/lib/components/shared/QueryBuilderVariableSelector.js +12 -1
- package/lib/components/shared/QueryBuilderVariableSelector.js.map +1 -1
- package/lib/components/watermark/QueryBuilderWatermark.d.ts.map +1 -1
- package/lib/components/watermark/QueryBuilderWatermark.js +2 -2
- package/lib/components/watermark/QueryBuilderWatermark.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/package.json +9 -9
- package/lib/stores/QueryBuilderEvent.d.ts +25 -0
- package/lib/stores/QueryBuilderEvent.d.ts.map +1 -0
- package/lib/stores/QueryBuilderEvent.js +26 -0
- package/lib/stores/QueryBuilderEvent.js.map +1 -0
- package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
- package/lib/stores/QueryBuilderResultState.js +44 -6
- package/lib/stores/QueryBuilderResultState.js.map +1 -1
- package/lib/stores/QueryBuilderState.d.ts +3 -0
- package/lib/stores/QueryBuilderState.d.ts.map +1 -1
- package/lib/stores/QueryBuilderState.js +7 -0
- package/lib/stores/QueryBuilderState.js.map +1 -1
- package/lib/stores/QueryBuilderTelemetry.d.ts +33 -0
- package/lib/stores/QueryBuilderTelemetry.d.ts.map +1 -0
- package/lib/stores/QueryBuilderTelemetry.js +37 -0
- package/lib/stores/QueryBuilderTelemetry.js.map +1 -0
- package/package.json +16 -16
- package/src/components/QueryBuilder.tsx +25 -22
- package/src/components/QueryBuilderComponentTestUtils.tsx +6 -5
- package/src/components/QueryBuilderConstantExpressionPanel.tsx +12 -11
- package/src/components/QueryBuilderDiffPanel.tsx +2 -3
- package/src/components/QueryBuilderParametersPanel.tsx +13 -7
- package/src/components/QueryBuilderPropertyExpressionEditor.tsx +27 -7
- package/src/components/QueryBuilderResultPanel.tsx +17 -1
- package/src/components/QueryBuilder_TestID.ts +2 -0
- package/src/components/explorer/QueryBuilderExplorerPanel.tsx +2 -3
- package/src/components/explorer/QueryBuilderMilestoningEditor.tsx +2 -3
- package/src/components/fetch-structure/QueryBuilderTDSWindowPanel.tsx +3 -6
- package/src/components/shared/CustomDatePicker.tsx +3 -3
- package/src/components/shared/QueryBuilderVariableSelector.tsx +18 -4
- package/src/components/watermark/QueryBuilderWatermark.tsx +2 -6
- package/src/index.ts +2 -0
- package/src/stores/QueryBuilderEvent.ts +26 -0
- package/src/stores/QueryBuilderResultState.ts +74 -2
- package/src/stores/QueryBuilderState.ts +10 -0
- package/src/stores/QueryBuilderTelemetry.ts +83 -0
- package/tsconfig.json +2 -0
@@ -52,6 +52,7 @@ import { variableExpression_setName } from '../stores/shared/ValueSpecificationM
|
|
52
52
|
import { LambdaParameterState } from '../stores/shared/LambdaParameterState.js';
|
53
53
|
import { LambdaParameterValuesEditor } from './shared/LambdaParameterValuesEditor.js';
|
54
54
|
import { VariableViewer } from './shared/QueryBuilderVariableSelector.js';
|
55
|
+
import { QUERY_BUILDER_TEST_ID } from './QueryBuilder_TestID.js';
|
55
56
|
|
56
57
|
type MultiplicityOption = { label: string; value: Multiplicity };
|
57
58
|
|
@@ -71,12 +72,16 @@ const VariableExpressionEditor = observer(
|
|
71
72
|
const { queryBuilderState, lambdaParameterState } = props;
|
72
73
|
const applicationStore = useApplicationStore();
|
73
74
|
const queryParametersState = queryBuilderState.parametersState;
|
75
|
+
const allVariableNames = queryBuilderState.allVariableNames;
|
74
76
|
const isCreating =
|
75
77
|
!queryParametersState.parameterStates.includes(lambdaParameterState);
|
76
78
|
const varState = lambdaParameterState.parameter;
|
77
79
|
const multiplity = varState.multiplicity;
|
78
80
|
const validationMessage = !varState.name
|
79
81
|
? `Parameter name can't be empty`
|
82
|
+
: allVariableNames.filter((e) => e === varState.name).length >
|
83
|
+
(isCreating ? 0 : 1)
|
84
|
+
? 'Parameter Name Already Exists'
|
80
85
|
: (isCreating &&
|
81
86
|
queryParametersState.parameterStates.find(
|
82
87
|
(p) => p.parameter.name === varState.name,
|
@@ -200,13 +205,11 @@ const VariableExpressionEditor = observer(
|
|
200
205
|
</ModalBody>
|
201
206
|
<ModalFooter>
|
202
207
|
{isCreating && (
|
203
|
-
<
|
204
|
-
|
208
|
+
<ModalFooterButton
|
209
|
+
text="Create"
|
210
|
+
inProgress={Boolean(validationMessage)}
|
205
211
|
onClick={onAction}
|
206
|
-
|
207
|
-
>
|
208
|
-
Create
|
209
|
-
</button>
|
212
|
+
/>
|
210
213
|
)}
|
211
214
|
<ModalFooterButton onClick={close} text="Close" />
|
212
215
|
</ModalFooter>
|
@@ -247,7 +250,10 @@ export const QueryBuilderParametersPanel = observer(
|
|
247
250
|
};
|
248
251
|
|
249
252
|
return (
|
250
|
-
<div
|
253
|
+
<div
|
254
|
+
data-testid={QUERY_BUILDER_TEST_ID.QUERY_BUILDER_PARAMETERS}
|
255
|
+
className="panel query-builder__variables"
|
256
|
+
>
|
251
257
|
<div className="panel__header">
|
252
258
|
<div className="panel__header__title">
|
253
259
|
<div className="panel__header__title__label">parameters</div>
|
@@ -25,6 +25,7 @@ import {
|
|
25
25
|
ModalHeader,
|
26
26
|
ModalBody,
|
27
27
|
ModalFooter,
|
28
|
+
ModalFooterButton,
|
28
29
|
} from '@finos/legend-art';
|
29
30
|
import { observer } from 'mobx-react-lite';
|
30
31
|
import {
|
@@ -304,7 +305,25 @@ export const QueryBuilderPropertyExpressionEditor = observer(
|
|
304
305
|
const { propertyExpressionState } = props;
|
305
306
|
const handleClose = (): void =>
|
306
307
|
propertyExpressionState.setIsEditingDerivedProperty(false);
|
307
|
-
|
308
|
+
const isParameterCompatibleWithDerivedProperty = (
|
309
|
+
variable: VariableExpression,
|
310
|
+
derivedProperties: QueryBuilderDerivedPropertyExpressionState[],
|
311
|
+
): boolean =>
|
312
|
+
Boolean(
|
313
|
+
derivedProperties.find((dp) => {
|
314
|
+
if (!variable.genericType?.value.rawType) {
|
315
|
+
return false;
|
316
|
+
}
|
317
|
+
return (
|
318
|
+
isSuperType(
|
319
|
+
dp.derivedProperty.genericType.value.rawType,
|
320
|
+
variable.genericType.value.rawType,
|
321
|
+
) ||
|
322
|
+
dp.derivedProperty.genericType.value.rawType.name ===
|
323
|
+
variable.genericType.value.rawType.name
|
324
|
+
);
|
325
|
+
}),
|
326
|
+
);
|
308
327
|
return (
|
309
328
|
<Dialog
|
310
329
|
open={Boolean(
|
@@ -334,16 +353,17 @@ export const QueryBuilderPropertyExpressionEditor = observer(
|
|
334
353
|
<ModalBody className="query-builder__variables__modal__body">
|
335
354
|
<VariableSelector
|
336
355
|
queryBuilderState={propertyExpressionState.queryBuilderState}
|
356
|
+
filterBy={(v: VariableExpression) =>
|
357
|
+
isParameterCompatibleWithDerivedProperty(
|
358
|
+
v,
|
359
|
+
propertyExpressionState.derivedPropertyExpressionStates,
|
360
|
+
)
|
361
|
+
}
|
337
362
|
/>
|
338
363
|
</ModalBody>
|
339
364
|
</ModalBody>
|
340
365
|
<ModalFooter>
|
341
|
-
<
|
342
|
-
className="btn modal__footer__close-btn"
|
343
|
-
onClick={handleClose}
|
344
|
-
>
|
345
|
-
Done
|
346
|
-
</button>
|
366
|
+
<ModalFooterButton text="Done" onClick={handleClose} />
|
347
367
|
</ModalFooter>
|
348
368
|
</Modal>
|
349
369
|
</Dialog>
|
@@ -326,6 +326,7 @@ const QueryBuilderGridResult = observer(
|
|
326
326
|
const [cellDoubleClickedEvent, setCellDoubleClickedEvent] =
|
327
327
|
useState<CellMouseOverEvent | null>(null);
|
328
328
|
const columns = executionResult.result.columns;
|
329
|
+
let rowNumber = 1;
|
329
330
|
const rowData = executionResult.result.rows.map((_row) => {
|
330
331
|
const row: PlainObject = {};
|
331
332
|
const cols = executionResult.result.columns;
|
@@ -334,7 +335,9 @@ const QueryBuilderGridResult = observer(
|
|
334
335
|
// call `.toString()` to avoid this behavior.
|
335
336
|
// See https://github.com/finos/legend-studio/issues/1008
|
336
337
|
row[cols[idx] as string] = isBoolean(value) ? String(value) : value;
|
338
|
+
row.rowNumber = rowNumber;
|
337
339
|
});
|
340
|
+
rowNumber += 1;
|
338
341
|
return row;
|
339
342
|
});
|
340
343
|
|
@@ -351,7 +354,8 @@ const QueryBuilderGridResult = observer(
|
|
351
354
|
}
|
352
355
|
disabled={
|
353
356
|
!(fetchStructureImplementation instanceof QueryBuilderTDSState) ||
|
354
|
-
!queryBuilderState.isQuerySupported
|
357
|
+
!queryBuilderState.isQuerySupported ||
|
358
|
+
!cellDoubleClickedEvent
|
355
359
|
}
|
356
360
|
menuProps={{ elevation: 7 }}
|
357
361
|
key={executionResult._UUID}
|
@@ -359,7 +363,19 @@ const QueryBuilderGridResult = observer(
|
|
359
363
|
>
|
360
364
|
<AgGridReact
|
361
365
|
rowData={rowData}
|
366
|
+
gridOptions={{
|
367
|
+
suppressScrollOnNewData: true,
|
368
|
+
getRowId: function (data) {
|
369
|
+
return data.data.rowNumber as string;
|
370
|
+
},
|
371
|
+
}}
|
362
372
|
modules={[ClientSideRowModelModule]}
|
373
|
+
// Note: we use onCellMouseOver as a bit of a workaround
|
374
|
+
// since we use the context menu so we want the user to be
|
375
|
+
// able to right click any cell and have the context menu
|
376
|
+
// options use the data belonging to the row that they are
|
377
|
+
// in. hence why we set the cell every time we mouse over
|
378
|
+
// rather than making user click multiple times.
|
363
379
|
onCellMouseOver={(event): void => {
|
364
380
|
setCellDoubleClickedEvent(event);
|
365
381
|
}}
|
@@ -27,4 +27,6 @@ export enum QUERY_BUILDER_TEST_ID {
|
|
27
27
|
QUERY_BUILDER_EXPLORER = 'query__builder__explorer',
|
28
28
|
QUERY_BUILDER_PROPERTY_SEARCH_PANEL = 'query__builder__property__search__panel',
|
29
29
|
QUERY_BUILDER_RESULT_PANEL = 'query__builder__result__panel',
|
30
|
+
QUERY_BUILDER_PARAMETERS = 'query-builder__parameters',
|
31
|
+
QUERY_BUILDER_CONSTANTS = 'query-builder__constants',
|
30
32
|
}
|
@@ -52,6 +52,7 @@ import {
|
|
52
52
|
ModalBody,
|
53
53
|
ModalFooter,
|
54
54
|
ModalHeader,
|
55
|
+
ModalFooterButton,
|
55
56
|
} from '@finos/legend-art';
|
56
57
|
import {
|
57
58
|
type QueryBuilderExplorerTreeDragSource,
|
@@ -266,9 +267,7 @@ const QueryBuilderExplorerPreviewDataModal = observer(
|
|
266
267
|
)}
|
267
268
|
</ModalBody>
|
268
269
|
<ModalFooter>
|
269
|
-
<
|
270
|
-
Close
|
271
|
-
</button>
|
270
|
+
<ModalFooterButton text="Close" onClick={close} />
|
272
271
|
</ModalFooter>
|
273
272
|
</Modal>
|
274
273
|
</Dialog>
|
@@ -35,6 +35,7 @@ import {
|
|
35
35
|
Modal,
|
36
36
|
ModalBody,
|
37
37
|
ModalFooter,
|
38
|
+
ModalFooterButton,
|
38
39
|
ModalHeader,
|
39
40
|
PanelEntryDropZonePlaceholder,
|
40
41
|
PanelFormSection,
|
@@ -279,9 +280,7 @@ export const MilestoningParametersEditor = observer(
|
|
279
280
|
</div>
|
280
281
|
</ModalBody>
|
281
282
|
<ModalFooter>
|
282
|
-
<
|
283
|
-
Close
|
284
|
-
</button>
|
283
|
+
<ModalFooterButton text="Close" onClick={close} />
|
285
284
|
</ModalFooter>
|
286
285
|
</Modal>
|
287
286
|
</Dialog>
|
@@ -42,6 +42,7 @@ import {
|
|
42
42
|
Modal,
|
43
43
|
ModalFooter,
|
44
44
|
PanelFormSection,
|
45
|
+
ModalFooterButton,
|
45
46
|
} from '@finos/legend-art';
|
46
47
|
import { assertErrorThrown, guaranteeNonNullable } from '@finos/legend-shared';
|
47
48
|
import { observer } from 'mobx-react-lite';
|
@@ -513,13 +514,9 @@ const QueryBuilderWindowColumnModalEditor = observer(
|
|
513
514
|
</div>
|
514
515
|
<ModalFooter>
|
515
516
|
{createNewWindow ? (
|
516
|
-
<
|
517
|
-
Create
|
518
|
-
</button>
|
517
|
+
<ModalFooterButton text="Create" onClick={create} />
|
519
518
|
) : (
|
520
|
-
<
|
521
|
-
Close
|
522
|
-
</button>
|
519
|
+
<ModalFooterButton text="Close" onClick={close} />
|
523
520
|
)}
|
524
521
|
</ModalFooter>
|
525
522
|
</Modal>
|
@@ -56,7 +56,7 @@ import {
|
|
56
56
|
valueSpecification_setGenericType,
|
57
57
|
} from '../../stores/shared/ValueSpecificationModifierHelper.js';
|
58
58
|
|
59
|
-
enum CUSTOM_DATE_PICKER_OPTION {
|
59
|
+
export enum CUSTOM_DATE_PICKER_OPTION {
|
60
60
|
ABSOLUTE_DATE = 'Absolute Date',
|
61
61
|
ABSOLUTE_TIME = 'Absolute Time',
|
62
62
|
TODAY = 'Today',
|
@@ -431,7 +431,7 @@ const buildPureDurationEnumValue = (
|
|
431
431
|
};
|
432
432
|
|
433
433
|
/**
|
434
|
-
* Generate the pure date
|
434
|
+
* Generate the pure date adjust() function based on the CustomDateOption.
|
435
435
|
*/
|
436
436
|
const buildPureAdjustDateFunction = (
|
437
437
|
customDateOption: CustomDateOption,
|
@@ -634,7 +634,7 @@ const buildCustomDateOption = (
|
|
634
634
|
/**
|
635
635
|
* Build DatePickerOption from pure date functions or PrimitiveInstanceValue
|
636
636
|
*/
|
637
|
-
const buildDatePickerOption = (
|
637
|
+
export const buildDatePickerOption = (
|
638
638
|
valueSpecification: SimpleFunctionExpression | PrimitiveInstanceValue,
|
639
639
|
): DatePickerOption => {
|
640
640
|
if (valueSpecification instanceof SimpleFunctionExpression) {
|
@@ -23,9 +23,10 @@ import {
|
|
23
23
|
TimesIcon,
|
24
24
|
useDragPreviewLayer,
|
25
25
|
} from '@finos/legend-art';
|
26
|
-
import
|
27
|
-
|
28
|
-
|
26
|
+
import {
|
27
|
+
SimpleFunctionExpression,
|
28
|
+
type ValueSpecification,
|
29
|
+
type VariableExpression,
|
29
30
|
} from '@finos/legend-graph';
|
30
31
|
import { observer } from 'mobx-react-lite';
|
31
32
|
import { useDrag } from 'react-dnd';
|
@@ -36,6 +37,7 @@ import {
|
|
36
37
|
QUERY_BUILDER_VARIABLE_DND_TYPE,
|
37
38
|
VariableInfoTooltip,
|
38
39
|
} from './BasicValueSpecificationEditor.js';
|
40
|
+
import { buildDatePickerOption } from './CustomDatePicker.js';
|
39
41
|
|
40
42
|
export const VariableViewer = observer(
|
41
43
|
(props: {
|
@@ -50,8 +52,19 @@ export const VariableViewer = observer(
|
|
50
52
|
}) => {
|
51
53
|
const { variable, constantValue, actions, isReadOnly, queryBuilderState } =
|
52
54
|
props;
|
55
|
+
|
56
|
+
const getNameOfValue = (value: ValueSpecification): string | undefined => {
|
57
|
+
if (value instanceof SimpleFunctionExpression) {
|
58
|
+
const possibleDateLabel = buildDatePickerOption(value).label;
|
59
|
+
if (possibleDateLabel) {
|
60
|
+
return possibleDateLabel;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
return getValueSpecificationStringValue(value);
|
64
|
+
};
|
65
|
+
|
53
66
|
const valueString = constantValue
|
54
|
-
?
|
67
|
+
? getNameOfValue(constantValue)
|
55
68
|
: undefined;
|
56
69
|
const name = variable.name;
|
57
70
|
const variableType = variable.genericType?.value.rawType;
|
@@ -159,6 +172,7 @@ export const VariableSelector = observer(
|
|
159
172
|
queryBuilderState.constantState.constants.filter((c) =>
|
160
173
|
filterBy ? filterBy(c.variable) : true,
|
161
174
|
);
|
175
|
+
|
162
176
|
return (
|
163
177
|
<>
|
164
178
|
<PanelFormListItems title="Available parameters">
|
@@ -25,6 +25,7 @@ import {
|
|
25
25
|
ModalFooter,
|
26
26
|
ModalHeader,
|
27
27
|
PanelFormSection,
|
28
|
+
ModalFooterButton,
|
28
29
|
} from '@finos/legend-art';
|
29
30
|
import {
|
30
31
|
areMultiplicitiesEqual,
|
@@ -169,12 +170,7 @@ export const QueryBuilderWatermarkEditor = observer(
|
|
169
170
|
</PanelForm>
|
170
171
|
</ModalBody>
|
171
172
|
<ModalFooter>
|
172
|
-
<
|
173
|
-
className="btn modal__footer__close-btn"
|
174
|
-
onClick={handleClose}
|
175
|
-
>
|
176
|
-
Done
|
177
|
-
</button>
|
173
|
+
<ModalFooterButton text="Done" onClick={handleClose} />
|
178
174
|
</ModalFooter>
|
179
175
|
</Modal>
|
180
176
|
</Dialog>
|
package/src/index.ts
CHANGED
@@ -49,6 +49,8 @@ export * from './stores/ServiceInfo.js';
|
|
49
49
|
export * from './components/ServiceQuerySetupUtils.js';
|
50
50
|
export * from './components/QuerySetupUtils.js';
|
51
51
|
export * from './components/QueryBuilderTextEditor.js';
|
52
|
+
export * from './stores/QueryBuilderTelemetry.js';
|
53
|
+
export * from './stores/QueryBuilderEvent.js';
|
52
54
|
|
53
55
|
export { TEST__setUpQueryBuilder } from './components/QueryBuilderComponentTestUtils.js';
|
54
56
|
|
@@ -0,0 +1,26 @@
|
|
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
|
+
export enum QUERY_BUILDER_EVENT {
|
18
|
+
RUN_QUERY__LAUNCH = 'editor.execution.run-query.launch',
|
19
|
+
GENERATE_EXECUTION_PLAN__LAUNCH = 'editor.execution.generate-plan.launch',
|
20
|
+
DEBUG_EXECUTION_PLAN__LAUNCH = 'editor.execution.debug-plan.launch',
|
21
|
+
|
22
|
+
RUN_QUERY__SUCCESS = 'editor.execution.run-query.success',
|
23
|
+
GENERATE_EXECUTION_PLAN__SUCCESS = 'editor.execution.generate-plan.success',
|
24
|
+
DEBUG_EXECUTION_PLAN__SUCCESS = 'editor.execution.debug-plan.success',
|
25
|
+
BUILD_EXECUTION_PLAN__SUCCESS = 'graph-manager.execution.build-plan.success',
|
26
|
+
}
|
@@ -25,6 +25,7 @@ import {
|
|
25
25
|
downloadFileUsingDataURI,
|
26
26
|
UnsupportedOperationError,
|
27
27
|
ActionState,
|
28
|
+
StopWatch,
|
28
29
|
} from '@finos/legend-shared';
|
29
30
|
import type { QueryBuilderState } from './QueryBuilderState.js';
|
30
31
|
import {
|
@@ -35,6 +36,7 @@ import {
|
|
35
36
|
EXECUTION_SERIALIZATION_FORMAT,
|
36
37
|
RawExecutionResult,
|
37
38
|
buildRawLambdaFromLambdaFunction,
|
39
|
+
reportGraphAnalytics,
|
38
40
|
} from '@finos/legend-graph';
|
39
41
|
import { buildLambdaFunction } from './QueryBuilderValueSpecificationBuilder.js';
|
40
42
|
import { ExecutionPlanState } from '@finos/legend-application';
|
@@ -43,6 +45,8 @@ import {
|
|
43
45
|
getExecutionQueryFromRawLambda,
|
44
46
|
} from './shared/LambdaParameterState.js';
|
45
47
|
import type { LambdaFunctionBuilderOption } from './QueryBuilderValueSpecificationBuilderHelper.js';
|
48
|
+
import { QueryBuilderTelemetry } from './QueryBuilderTelemetry.js';
|
49
|
+
import { QUERY_BUILDER_EVENT } from './QueryBuilderEvent.js';
|
46
50
|
|
47
51
|
const DEFAULT_LIMIT = 1000;
|
48
52
|
|
@@ -219,7 +223,21 @@ export class QueryBuilderResultState {
|
|
219
223
|
this.queryBuilderState.parametersState.parameterStates,
|
220
224
|
this.queryBuilderState.graphManagerState,
|
221
225
|
);
|
222
|
-
|
226
|
+
|
227
|
+
QueryBuilderTelemetry.logEvent_QueryRunLaunched(
|
228
|
+
this.queryBuilderState.applicationStore.telemetryService,
|
229
|
+
this.queryBuilderState.applicationContext
|
230
|
+
? {
|
231
|
+
applicationContext: this.queryBuilderState.applicationContext,
|
232
|
+
}
|
233
|
+
: {},
|
234
|
+
);
|
235
|
+
|
236
|
+
const stopWatch = new StopWatch();
|
237
|
+
const report = reportGraphAnalytics(
|
238
|
+
this.queryBuilderState.graphManagerState.graph,
|
239
|
+
);
|
240
|
+
|
223
241
|
const promise =
|
224
242
|
this.queryBuilderState.graphManagerState.graphManager.runQuery(
|
225
243
|
query,
|
@@ -230,12 +248,22 @@ export class QueryBuilderResultState {
|
|
230
248
|
parameterValues,
|
231
249
|
},
|
232
250
|
);
|
251
|
+
|
233
252
|
this.setQueryRunPromise(promise);
|
234
253
|
const result = (yield promise) as ExecutionResult;
|
235
254
|
if (this.queryRunPromise === promise) {
|
236
255
|
this.setExecutionResult(result);
|
237
256
|
this.latestRunHashCode = currentHashCode;
|
238
|
-
this.setExecutionDuration(
|
257
|
+
this.setExecutionDuration(stopWatch.elapsed);
|
258
|
+
|
259
|
+
report.timings = {
|
260
|
+
...report.timings,
|
261
|
+
total: stopWatch.elapsed,
|
262
|
+
};
|
263
|
+
QueryBuilderTelemetry.logEvent_QueryRunSucceeded(
|
264
|
+
this.queryBuilderState.applicationStore.telemetryService,
|
265
|
+
report,
|
266
|
+
);
|
239
267
|
}
|
240
268
|
} catch (error) {
|
241
269
|
assertErrorThrown(error);
|
@@ -263,25 +291,51 @@ export class QueryBuilderResultState {
|
|
263
291
|
);
|
264
292
|
const query = this.queryBuilderState.buildQuery();
|
265
293
|
let rawPlan: RawExecutionPlan;
|
294
|
+
|
295
|
+
const stopWatch = new StopWatch();
|
296
|
+
const report = reportGraphAnalytics(
|
297
|
+
this.queryBuilderState.graphManagerState.graph,
|
298
|
+
);
|
299
|
+
|
266
300
|
if (debug) {
|
301
|
+
QueryBuilderTelemetry.logEvent_ExecutionPlanDebugLaunched(
|
302
|
+
this.queryBuilderState.applicationStore.telemetryService,
|
303
|
+
this.queryBuilderState.applicationContext
|
304
|
+
? {
|
305
|
+
applicationContext: this.queryBuilderState.applicationContext,
|
306
|
+
}
|
307
|
+
: {},
|
308
|
+
);
|
267
309
|
const debugResult =
|
268
310
|
(yield this.queryBuilderState.graphManagerState.graphManager.debugExecutionPlanGeneration(
|
269
311
|
query,
|
270
312
|
mapping,
|
271
313
|
runtime,
|
272
314
|
this.queryBuilderState.graphManagerState.graph,
|
315
|
+
report,
|
273
316
|
)) as { plan: RawExecutionPlan; debug: string };
|
274
317
|
rawPlan = debugResult.plan;
|
275
318
|
this.executionPlanState.setDebugText(debugResult.debug);
|
276
319
|
} else {
|
320
|
+
QueryBuilderTelemetry.logEvent_ExecutionPlanGenerationLaunched(
|
321
|
+
this.queryBuilderState.applicationStore.telemetryService,
|
322
|
+
this.queryBuilderState.applicationContext
|
323
|
+
? {
|
324
|
+
applicationContext: this.queryBuilderState.applicationContext,
|
325
|
+
}
|
326
|
+
: {},
|
327
|
+
);
|
277
328
|
rawPlan =
|
278
329
|
(yield this.queryBuilderState.graphManagerState.graphManager.generateExecutionPlan(
|
279
330
|
query,
|
280
331
|
mapping,
|
281
332
|
runtime,
|
282
333
|
this.queryBuilderState.graphManagerState.graph,
|
334
|
+
report,
|
283
335
|
)) as object;
|
284
336
|
}
|
337
|
+
|
338
|
+
stopWatch.record();
|
285
339
|
try {
|
286
340
|
this.executionPlanState.setRawPlan(rawPlan);
|
287
341
|
const plan =
|
@@ -293,6 +347,24 @@ export class QueryBuilderResultState {
|
|
293
347
|
} catch {
|
294
348
|
// do nothing
|
295
349
|
}
|
350
|
+
stopWatch.record(QUERY_BUILDER_EVENT.BUILD_EXECUTION_PLAN__SUCCESS);
|
351
|
+
|
352
|
+
report.timings = {
|
353
|
+
...report.timings,
|
354
|
+
...Object.fromEntries(stopWatch.records),
|
355
|
+
total: stopWatch.elapsed,
|
356
|
+
};
|
357
|
+
if (debug) {
|
358
|
+
QueryBuilderTelemetry.logEvent_ExecutionPlanDebugSucceeded(
|
359
|
+
this.queryBuilderState.applicationStore.telemetryService,
|
360
|
+
report,
|
361
|
+
);
|
362
|
+
} else {
|
363
|
+
QueryBuilderTelemetry.logEvent_ExecutionPlanGenerationSucceeded(
|
364
|
+
this.queryBuilderState.applicationStore.telemetryService,
|
365
|
+
report,
|
366
|
+
);
|
367
|
+
}
|
296
368
|
} catch (error) {
|
297
369
|
assertErrorThrown(error);
|
298
370
|
this.queryBuilderState.applicationStore.log.error(
|
@@ -99,6 +99,7 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
99
99
|
textEditorState: QueryBuilderTextEditorState;
|
100
100
|
unsupportedQueryState: QueryBuilderUnsupportedQueryState;
|
101
101
|
observableContext: ObserverContext;
|
102
|
+
titleOfQuery: string | undefined;
|
102
103
|
|
103
104
|
queryCompileState = ActionState.create();
|
104
105
|
showFunctionsExplorerPanel = false;
|
@@ -110,6 +111,8 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
110
111
|
mapping?: Mapping | undefined;
|
111
112
|
runtimeValue?: Runtime | undefined;
|
112
113
|
|
114
|
+
applicationContext?: string | undefined;
|
115
|
+
|
113
116
|
// NOTE: this makes it so that we need to import components in stores code,
|
114
117
|
// we probably want to refactor to an extension mechanism
|
115
118
|
TEMPORARY__setupPanelContentRenderer?: (() => React.ReactNode) | undefined;
|
@@ -126,6 +129,7 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
126
129
|
fetchStructureState: observable,
|
127
130
|
filterState: observable,
|
128
131
|
watermarkState: observable,
|
132
|
+
titleOfQuery: observable,
|
129
133
|
checkEntitlementsState: observable,
|
130
134
|
resultState: observable,
|
131
135
|
textEditorState: observable,
|
@@ -151,6 +155,8 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
151
155
|
setMapping: action,
|
152
156
|
setRuntimeValue: action,
|
153
157
|
|
158
|
+
setTitleOfQuery: action,
|
159
|
+
|
154
160
|
resetQueryResult: action,
|
155
161
|
resetQueryContent: action,
|
156
162
|
changeClass: action,
|
@@ -253,6 +259,10 @@ export abstract class QueryBuilderState implements CommandRegistrar {
|
|
253
259
|
this.runtimeValue = val;
|
254
260
|
}
|
255
261
|
|
262
|
+
setTitleOfQuery(val: string | undefined): void {
|
263
|
+
this.titleOfQuery = val;
|
264
|
+
}
|
265
|
+
|
256
266
|
get isQuerySupported(): boolean {
|
257
267
|
return !this.unsupportedQueryState.rawLambda;
|
258
268
|
}
|
@@ -0,0 +1,83 @@
|
|
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 type { GraphManagerOperationReport } from '@finos/legend-graph';
|
18
|
+
import type { TelemetryService } from '@finos/legend-shared';
|
19
|
+
import { QUERY_BUILDER_EVENT } from './QueryBuilderEvent.js';
|
20
|
+
|
21
|
+
type LaunchQueryExecution_TelemteryData = {
|
22
|
+
applicationContext?: string | undefined;
|
23
|
+
};
|
24
|
+
|
25
|
+
type QueryExecution_TelemetryData = GraphManagerOperationReport & {
|
26
|
+
dependenciesCount: number;
|
27
|
+
};
|
28
|
+
|
29
|
+
export class QueryBuilderTelemetry {
|
30
|
+
static logEvent_QueryRunLaunched(
|
31
|
+
telemetryService: TelemetryService,
|
32
|
+
data: LaunchQueryExecution_TelemteryData,
|
33
|
+
): void {
|
34
|
+
telemetryService.logEvent(QUERY_BUILDER_EVENT.RUN_QUERY__LAUNCH, data);
|
35
|
+
}
|
36
|
+
|
37
|
+
static logEvent_ExecutionPlanGenerationLaunched(
|
38
|
+
telemetryService: TelemetryService,
|
39
|
+
data: LaunchQueryExecution_TelemteryData,
|
40
|
+
): void {
|
41
|
+
telemetryService.logEvent(
|
42
|
+
QUERY_BUILDER_EVENT.GENERATE_EXECUTION_PLAN__LAUNCH,
|
43
|
+
data,
|
44
|
+
);
|
45
|
+
}
|
46
|
+
|
47
|
+
static logEvent_ExecutionPlanDebugLaunched(
|
48
|
+
telemetryService: TelemetryService,
|
49
|
+
data: LaunchQueryExecution_TelemteryData,
|
50
|
+
): void {
|
51
|
+
telemetryService.logEvent(
|
52
|
+
QUERY_BUILDER_EVENT.DEBUG_EXECUTION_PLAN__LAUNCH,
|
53
|
+
data,
|
54
|
+
);
|
55
|
+
}
|
56
|
+
|
57
|
+
static logEvent_QueryRunSucceeded(
|
58
|
+
telemetryService: TelemetryService,
|
59
|
+
data: QueryExecution_TelemetryData,
|
60
|
+
): void {
|
61
|
+
telemetryService.logEvent(QUERY_BUILDER_EVENT.RUN_QUERY__SUCCESS, data);
|
62
|
+
}
|
63
|
+
|
64
|
+
static logEvent_ExecutionPlanGenerationSucceeded(
|
65
|
+
telemetryService: TelemetryService,
|
66
|
+
data: QueryExecution_TelemetryData,
|
67
|
+
): void {
|
68
|
+
telemetryService.logEvent(
|
69
|
+
QUERY_BUILDER_EVENT.GENERATE_EXECUTION_PLAN__SUCCESS,
|
70
|
+
data,
|
71
|
+
);
|
72
|
+
}
|
73
|
+
|
74
|
+
static logEvent_ExecutionPlanDebugSucceeded(
|
75
|
+
telemetryService: TelemetryService,
|
76
|
+
data: QueryExecution_TelemetryData,
|
77
|
+
): void {
|
78
|
+
telemetryService.logEvent(
|
79
|
+
QUERY_BUILDER_EVENT.DEBUG_EXECUTION_PLAN__SUCCESS,
|
80
|
+
data,
|
81
|
+
);
|
82
|
+
}
|
83
|
+
}
|
package/tsconfig.json
CHANGED
@@ -53,6 +53,7 @@
|
|
53
53
|
"./src/stores/QueryBuilderCommand.ts",
|
54
54
|
"./src/stores/QueryBuilderConfig.ts",
|
55
55
|
"./src/stores/QueryBuilderConstantsState.ts",
|
56
|
+
"./src/stores/QueryBuilderEvent.ts",
|
56
57
|
"./src/stores/QueryBuilderGroupOperationHelper.ts",
|
57
58
|
"./src/stores/QueryBuilderParametersState.ts",
|
58
59
|
"./src/stores/QueryBuilderPreviewDataHelper.ts",
|
@@ -61,6 +62,7 @@
|
|
61
62
|
"./src/stores/QueryBuilderState.ts",
|
62
63
|
"./src/stores/QueryBuilderStateBuilder.ts",
|
63
64
|
"./src/stores/QueryBuilderStateTestUtils.ts",
|
65
|
+
"./src/stores/QueryBuilderTelemetry.ts",
|
64
66
|
"./src/stores/QueryBuilderTextEditorState.ts",
|
65
67
|
"./src/stores/QueryBuilderTypeaheadHelper.ts",
|
66
68
|
"./src/stores/QueryBuilderUnsupportedQueryState.ts",
|