@finos/legend-query-builder 0.6.26 → 0.6.28
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/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",
|