@finos/legend-query-builder 4.7.4 → 4.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. package/lib/components/QueryBuilderConstantExpressionPanel.d.ts.map +1 -1
  2. package/lib/components/QueryBuilderConstantExpressionPanel.js +27 -8
  3. package/lib/components/QueryBuilderConstantExpressionPanel.js.map +1 -1
  4. package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
  5. package/lib/components/QueryBuilderResultPanel.js +11 -5
  6. package/lib/components/QueryBuilderResultPanel.js.map +1 -1
  7. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  8. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +5 -3
  9. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  10. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  11. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +8 -1
  12. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  13. package/lib/components/shared/LambdaEditor.d.ts +1 -11
  14. package/lib/components/shared/LambdaEditor.d.ts.map +1 -1
  15. package/lib/components/shared/LambdaEditor.js +11 -4
  16. package/lib/components/shared/LambdaEditor.js.map +1 -1
  17. package/lib/index.css +2 -2
  18. package/lib/index.css.map +1 -1
  19. package/lib/package.json +1 -1
  20. package/lib/stores/QueryBuilderConstantsState.d.ts +3 -1
  21. package/lib/stores/QueryBuilderConstantsState.d.ts.map +1 -1
  22. package/lib/stores/QueryBuilderConstantsState.js +27 -3
  23. package/lib/stores/QueryBuilderConstantsState.js.map +1 -1
  24. package/lib/stores/QueryBuilderState.d.ts.map +1 -1
  25. package/lib/stores/QueryBuilderState.js +1 -0
  26. package/lib/stores/QueryBuilderState.js.map +1 -1
  27. package/lib/stores/QueryBuilderTypeaheadHelper.d.ts +1 -1
  28. package/lib/stores/QueryBuilderTypeaheadHelper.d.ts.map +1 -1
  29. package/lib/stores/QueryBuilderTypeaheadHelper.js +190 -30
  30. package/lib/stores/QueryBuilderTypeaheadHelper.js.map +1 -1
  31. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.d.ts +1 -0
  32. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.d.ts.map +1 -1
  33. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.js.map +1 -1
  34. package/lib/stores/fetch-structure/QueryBuilderFetchStructureState.d.ts +1 -0
  35. package/lib/stores/fetch-structure/QueryBuilderFetchStructureState.d.ts.map +1 -1
  36. package/lib/stores/fetch-structure/QueryBuilderFetchStructureState.js +4 -0
  37. package/lib/stores/fetch-structure/QueryBuilderFetchStructureState.js.map +1 -1
  38. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts +1 -0
  39. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts.map +1 -1
  40. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js +3 -0
  41. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js.map +1 -1
  42. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts +2 -0
  43. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts.map +1 -1
  44. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js +25 -1
  45. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js.map +1 -1
  46. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts +3 -1
  47. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts.map +1 -1
  48. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js +6 -0
  49. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
  50. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.d.ts +9 -2
  51. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.d.ts.map +1 -1
  52. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.js +40 -6
  53. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.js.map +1 -1
  54. package/lib/stores/milestoning/QueryBuilderBitemporalMilestoningImplementation.d.ts +1 -0
  55. package/lib/stores/milestoning/QueryBuilderBitemporalMilestoningImplementation.d.ts.map +1 -1
  56. package/lib/stores/milestoning/QueryBuilderBitemporalMilestoningImplementation.js +8 -1
  57. package/lib/stores/milestoning/QueryBuilderBitemporalMilestoningImplementation.js.map +1 -1
  58. package/lib/stores/milestoning/QueryBuilderBusinessTemporalMilestoningImplementation.d.ts +1 -0
  59. package/lib/stores/milestoning/QueryBuilderBusinessTemporalMilestoningImplementation.d.ts.map +1 -1
  60. package/lib/stores/milestoning/QueryBuilderBusinessTemporalMilestoningImplementation.js +7 -1
  61. package/lib/stores/milestoning/QueryBuilderBusinessTemporalMilestoningImplementation.js.map +1 -1
  62. package/lib/stores/milestoning/QueryBuilderMilestoningImplementation.d.ts +4 -0
  63. package/lib/stores/milestoning/QueryBuilderMilestoningImplementation.d.ts.map +1 -1
  64. package/lib/stores/milestoning/QueryBuilderMilestoningImplementation.js.map +1 -1
  65. package/lib/stores/milestoning/QueryBuilderProcessingTemporalMilestoningImplementation.d.ts +1 -0
  66. package/lib/stores/milestoning/QueryBuilderProcessingTemporalMilestoningImplementation.d.ts.map +1 -1
  67. package/lib/stores/milestoning/QueryBuilderProcessingTemporalMilestoningImplementation.js +7 -1
  68. package/lib/stores/milestoning/QueryBuilderProcessingTemporalMilestoningImplementation.js.map +1 -1
  69. package/package.json +3 -3
  70. package/src/components/QueryBuilderConstantExpressionPanel.tsx +85 -24
  71. package/src/components/QueryBuilderResultPanel.tsx +17 -13
  72. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +11 -1
  73. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +12 -1
  74. package/src/components/shared/LambdaEditor.tsx +15 -2
  75. package/src/stores/QueryBuilderConstantsState.ts +44 -1
  76. package/src/stores/QueryBuilderState.ts +1 -0
  77. package/src/stores/QueryBuilderTypeaheadHelper.ts +382 -54
  78. package/src/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.ts +1 -0
  79. package/src/stores/fetch-structure/QueryBuilderFetchStructureState.ts +5 -0
  80. package/src/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.ts +4 -0
  81. package/src/stores/fetch-structure/tds/QueryBuilderTDSState.ts +43 -1
  82. package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +11 -0
  83. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.ts +66 -9
  84. package/src/stores/milestoning/QueryBuilderBitemporalMilestoningImplementation.ts +14 -0
  85. package/src/stores/milestoning/QueryBuilderBusinessTemporalMilestoningImplementation.ts +13 -0
  86. package/src/stores/milestoning/QueryBuilderMilestoningImplementation.ts +7 -0
  87. package/src/stores/milestoning/QueryBuilderProcessingTemporalMilestoningImplementation.ts +13 -0
@@ -25,6 +25,7 @@ import {
25
25
  CustomSelectorInput,
26
26
  Dialog,
27
27
  InfoCircleIcon,
28
+ InputWithInlineValidation,
28
29
  Modal,
29
30
  ModalBody,
30
31
  ModalFooter,
@@ -42,10 +43,7 @@ import {
42
43
  Multiplicity,
43
44
  isValidIdentifier,
44
45
  } from '@finos/legend-graph';
45
- import {
46
- debounce,
47
- generateEnumerableNameFromToken,
48
- } from '@finos/legend-shared';
46
+ import { generateEnumerableNameFromToken } from '@finos/legend-shared';
49
47
  import { observer } from 'mobx-react-lite';
50
48
  import { DEFAULT_CONSTANT_VARIABLE_NAME } from '../stores/QueryBuilderConfig.js';
51
49
  import type { QueryBuilderState } from '../stores/QueryBuilderState.js';
@@ -58,10 +56,11 @@ import { buildDefaultInstanceValue } from '../stores/shared/ValueSpecificationEd
58
56
  import { BasicValueSpecificationEditor } from './shared/BasicValueSpecificationEditor.js';
59
57
  import { QUERY_BUILDER_TEST_ID } from '../__lib__/QueryBuilderTesting.js';
60
58
  import { QUERY_BUILDER_DOCUMENTATION_KEY } from '../__lib__/QueryBuilderDocumentation.js';
61
- import React, { useMemo, useState } from 'react';
59
+ import React, { useEffect, useState } from 'react';
62
60
  import { variableExpression_setName } from '../stores/shared/ValueSpecificationModifierHelper.js';
63
- import { LambdaEditor_PopUp } from './shared/LambdaEditor.js';
61
+ import { LambdaEditor } from './shared/LambdaEditor.js';
64
62
  import { VariableViewer } from './shared/QueryBuilderVariableSelector.js';
63
+ import { flowResult } from 'mobx';
65
64
 
66
65
  // NOTE: We currently only allow constant variables for primitive types of multiplicity ONE.
67
66
  // This is why we don't show multiplicity in the editor.
@@ -219,26 +218,88 @@ const QuerryBuilderCalculatedConstantExpressionEditor = observer(
219
218
  const { constantState } = props;
220
219
  const queryBuilderState = constantState.queryBuilderState;
221
220
  const lambdaState = constantState.lambdaState;
222
- const closePopUp = (): void =>
221
+ const close = (): void => {
223
222
  queryBuilderState.constantState.setSelectedConstant(undefined);
224
- const debouncedTransformStringToLambda = useMemo(
225
- () =>
226
- debounce(() => lambdaState.convertLambdaGrammarStringToObject(), 1000),
227
- [lambdaState],
228
- );
229
- const canDrop = true;
223
+ flowResult(constantState.updateVariableExpressionType()).catch(
224
+ queryBuilderState.applicationStore.alertUnhandledError,
225
+ );
226
+ };
227
+ const applicationStore = queryBuilderState.applicationStore;
228
+ const changeConstantName: React.ChangeEventHandler<HTMLInputElement> = (
229
+ event,
230
+ ) => {
231
+ variableExpression_setName(constantState.variable, event.target.value);
232
+ };
233
+ useEffect(() => {
234
+ flowResult(
235
+ lambdaState.convertLambdaObjectToGrammarString({
236
+ pretty: true,
237
+ }),
238
+ ).catch(applicationStore.alertUnhandledError);
239
+ }, [applicationStore, lambdaState]);
230
240
  return (
231
- <>
232
- <div className="lambda-editor" />
233
- <LambdaEditor_PopUp
234
- title={`Edit Constant ${constantState.variable.name}`}
235
- className={clsx({ 'lambda-editor--dnd-match': canDrop })}
236
- disabled={false}
237
- lambdaEditorState={lambdaState}
238
- transformStringToLambda={debouncedTransformStringToLambda}
239
- onClose={closePopUp}
240
- />
241
- </>
241
+ <Dialog
242
+ open={true}
243
+ onClose={close}
244
+ classes={{
245
+ root: 'editor-modal__root-container',
246
+ container: 'editor-modal__container',
247
+ paper: 'editor-modal__content',
248
+ }}
249
+ >
250
+ <Modal
251
+ darkMode={true}
252
+ className={clsx('editor-modal query-builder__constants__modal', {
253
+ 'query-builder__constants__modal--has-error': Boolean(
254
+ lambdaState.parserError,
255
+ ),
256
+ })}
257
+ >
258
+ <ModalHeader>
259
+ <div className="modal__title">Update Calculated Constants</div>
260
+ {lambdaState.parserError && (
261
+ <div className="modal__title__error-badge">
262
+ Failed to parse query
263
+ </div>
264
+ )}
265
+ </ModalHeader>
266
+ <ModalBody>
267
+ <div
268
+ className={clsx('query-builder__constants__modal__content', {
269
+ backdrop__element: Boolean(lambdaState.parserError),
270
+ })}
271
+ >
272
+ <div className="query-builder__constants__modal__name">
273
+ <InputWithInlineValidation
274
+ className="query-builder__constants__modal__name__input input--dark"
275
+ spellCheck={false}
276
+ value={constantState.variable.name}
277
+ onChange={changeConstantName}
278
+ placeholder="Constant Name"
279
+ />
280
+ </div>
281
+ <LambdaEditor
282
+ className="query-builder__constants__lambda-editor"
283
+ disabled={
284
+ lambdaState.convertingLambdaToStringState.isInProgress
285
+ }
286
+ lambdaEditorState={lambdaState}
287
+ forceBackdrop={false}
288
+ autoFocus={true}
289
+ />
290
+ </div>
291
+ </ModalBody>
292
+ <ModalFooter>
293
+ <button
294
+ className="btn btn--dark"
295
+ onClick={close}
296
+ disabled={Boolean(lambdaState.parserError)}
297
+ >
298
+ Close
299
+ </button>
300
+ </ModalFooter>
301
+ </Modal>
302
+ </Dialog>
242
303
  );
243
304
  },
244
305
  );
@@ -68,6 +68,8 @@ import {
68
68
  prettyDuration,
69
69
  filterByType,
70
70
  isValidURL,
71
+ isString,
72
+ isNumber,
71
73
  } from '@finos/legend-shared';
72
74
  import { forwardRef, useRef, useState } from 'react';
73
75
  import {
@@ -482,15 +484,18 @@ const QueryResultCellRenderer = observer(
482
484
  const tdsExecutionResult = params.tdsExecutionResult;
483
485
  const fetchStructureImplementation =
484
486
  resultState.queryBuilderState.fetchStructureState.implementation;
485
-
486
- const cellValue = params.value as string;
487
- const formattedCellValue = !isNaN(Number(cellValue))
488
- ? Intl.NumberFormat(DEFAULT_LOCALE, { maximumFractionDigits: 4 }).format(
489
- Number(cellValue),
490
- )
491
- : cellValue;
487
+ const cellValue = params.value as string | null | number | undefined;
488
+ const formattedCellValue = (): string | null | number | undefined => {
489
+ if (isNumber(cellValue)) {
490
+ return Intl.NumberFormat(DEFAULT_LOCALE, {
491
+ maximumFractionDigits: 4,
492
+ }).format(Number(cellValue));
493
+ }
494
+ return cellValue;
495
+ };
496
+ const cellValueUrlLink =
497
+ isString(cellValue) && isValidURL(cellValue) ? cellValue : undefined;
492
498
  const columnName = params.column?.getColId() ?? '';
493
-
494
499
  const findCoordinatesFromResultValue = (
495
500
  colId: string,
496
501
  rowNumber: number,
@@ -498,7 +503,6 @@ const QueryResultCellRenderer = observer(
498
503
  const colIndex = tdsExecutionResult.result.columns.findIndex(
499
504
  (col) => col === colId,
500
505
  );
501
-
502
506
  return { rowIndex: rowNumber, colIndex: colIndex };
503
507
  };
504
508
 
@@ -710,12 +714,12 @@ const QueryResultCellRenderer = observer(
710
714
  onMouseUp={(event) => mouseUp(event)}
711
715
  onMouseOver={(event) => mouseOver(event)}
712
716
  >
713
- {isValidURL(cellValue) ? (
714
- <a href={cellValue} target="_blank" rel="noreferrer">
715
- {cellValue}
717
+ {cellValueUrlLink ? (
718
+ <a href={cellValueUrlLink} target="_blank" rel="noreferrer">
719
+ {cellValueUrlLink}
716
720
  </a>
717
721
  ) : (
718
- <span>{formattedCellValue}</span>
722
+ <span>{formattedCellValue()}</span>
719
723
  )}
720
724
  </div>
721
725
  </ContextMenu>
@@ -46,6 +46,7 @@ import {
46
46
  MoreVerticalIcon,
47
47
  MenuContentItemIcon,
48
48
  MenuContentItemLabel,
49
+ PanelLoadingIndicator,
49
50
  } from '@finos/legend-art';
50
51
  import {
51
52
  type ValueSpecification,
@@ -883,7 +884,11 @@ const QueryBuilderPostFilterPanelContent = observer(
883
884
  !aggregateColumnState &&
884
885
  columnState instanceof QueryBuilderDerivationProjectionColumnState
885
886
  ) {
886
- await flowResult(columnState.fetchDerivationLambdaReturnType());
887
+ await flowResult(
888
+ columnState.fetchDerivationLambdaReturnType({
889
+ isBeingDropped: true,
890
+ }),
891
+ );
887
892
  }
888
893
  postFilterConditionState = new PostFilterConditionState(
889
894
  postFilterState,
@@ -1034,6 +1039,11 @@ const QueryBuilderPostFilterPanelContent = observer(
1034
1039
  isDroppable={isDroppable && postFilterState.isEmpty}
1035
1040
  dropTargetConnector={dropTargetConnector}
1036
1041
  >
1042
+ {
1043
+ <PanelLoadingIndicator
1044
+ isLoading={Boolean(postFilterState.derivedColumnBeingDropped)}
1045
+ />
1046
+ }
1037
1047
  {postFilterState.isEmpty && (
1038
1048
  <BlankPanelPlaceholder
1039
1049
  text="Add a post-filter condition"
@@ -174,7 +174,17 @@ const QueryBuilderDerivationProjectionColumnEditor = observer(
174
174
  }) => {
175
175
  const { projectionColumnState } = props;
176
176
  const hasParserError = projectionColumnState.tdsState.hasParserError;
177
-
177
+ const onEditorBlur = (): void => {
178
+ flowResult(
179
+ projectionColumnState.fetchDerivationLambdaReturnType({
180
+ forceConversionStringToLambda: true,
181
+ forceRefresh: true,
182
+ }),
183
+ ).catch(
184
+ projectionColumnState.tdsState.queryBuilderState.applicationStore
185
+ .alertUnhandledError,
186
+ );
187
+ };
178
188
  const handleDrop = useCallback(
179
189
  (
180
190
  item:
@@ -247,6 +257,7 @@ const QueryBuilderDerivationProjectionColumnEditor = observer(
247
257
  }
248
258
  lambdaEditorState={projectionColumnState.derivationLambdaEditorState}
249
259
  forceBackdrop={hasParserError}
260
+ onEditorBlur={onEditorBlur}
250
261
  />
251
262
  </div>
252
263
  );
@@ -99,6 +99,7 @@ const LambdaEditor_Inner = observer(
99
99
  autoFocus?: boolean | undefined;
100
100
  openInPopUp?: (() => void) | undefined;
101
101
  onEditorFocus?: (() => void) | undefined;
102
+ onEditorBlur?: (() => void) | undefined;
102
103
  disableExpansion?: boolean | undefined;
103
104
  forceExpansion?: boolean | undefined;
104
105
  }) => {
@@ -119,6 +120,7 @@ const LambdaEditor_Inner = observer(
119
120
  autoFocus,
120
121
  openInPopUp,
121
122
  onEditorFocus,
123
+ onEditorBlur,
122
124
  } = props;
123
125
  const applicationStore = useApplicationStore();
124
126
  const onDidChangeModelContentEventDisposer = useRef<
@@ -127,6 +129,9 @@ const LambdaEditor_Inner = observer(
127
129
  const onDidFocusEditorWidgetDisposer = useRef<IDisposable | undefined>(
128
130
  undefined,
129
131
  );
132
+ const onDidBlurEditorTextDisposer = useRef<IDisposable | undefined>(
133
+ undefined,
134
+ );
130
135
  const value = normalizeLineEnding(lambdaEditorState.lambdaString);
131
136
  const parserError = lambdaEditorState.parserError;
132
137
  const compilationError = lambdaEditorState.compilationError;
@@ -285,7 +290,12 @@ const LambdaEditor_Inner = observer(
285
290
  onEditorFocus?.();
286
291
  },
287
292
  );
288
-
293
+ if (onEditorBlur) {
294
+ onDidBlurEditorTextDisposer.current = editor.onDidBlurEditorText(() => {
295
+ transformStringToLambda?.cancel();
296
+ onEditorBlur();
297
+ });
298
+ }
289
299
  // Set the text value
290
300
  const currentValue = getCodeEditorValue(editor);
291
301
  const editorModel = editor.getModel();
@@ -419,7 +429,7 @@ const LambdaEditor_Inner = observer(
419
429
  },
420
430
  );
421
431
 
422
- export const LambdaEditor_PopUp = observer(
432
+ const LambdaEditor_PopUp = observer(
423
433
  (props: {
424
434
  title?: string | undefined;
425
435
  className?: string | undefined;
@@ -668,6 +678,7 @@ type LambdaEditorBaseProps = {
668
678
  forceBackdrop: boolean;
669
679
  autoFocus?: boolean | undefined;
670
680
  onEditorFocus?: (() => void) | undefined;
681
+ onEditorBlur?: (() => void) | undefined;
671
682
  };
672
683
 
673
684
  export const InlineLambdaEditor = observer(
@@ -716,6 +727,7 @@ export const InlineLambdaEditor = observer(
716
727
  hideErrorBar,
717
728
  autoFocus,
718
729
  onEditorFocus,
730
+ onEditorBlur,
719
731
  } = props;
720
732
  const [showPopUp, setShowPopUp] = useState(false);
721
733
  const openInPopUp = (): void => setShowPopUp(true);
@@ -786,6 +798,7 @@ export const InlineLambdaEditor = observer(
786
798
  autoFocus={autoFocus}
787
799
  openInPopUp={openInPopUp}
788
800
  onEditorFocus={onEditorFocus}
801
+ onEditorBlur={onEditorBlur}
789
802
  hideErrorBar={hideErrorBar}
790
803
  forceExpansion={
791
804
  disableExpansion !== undefined
@@ -24,6 +24,10 @@ import {
24
24
  buildSourceInformationSourceId,
25
25
  ParserError,
26
26
  GRAPH_MANAGER_EVENT,
27
+ RawLambda,
28
+ PureModel,
29
+ CoreModel,
30
+ SystemModel,
27
31
  } from '@finos/legend-graph';
28
32
  import {
29
33
  type Hashable,
@@ -38,8 +42,9 @@ import {
38
42
  LogEvent,
39
43
  changeEntry,
40
44
  assertTrue,
45
+ ActionState,
41
46
  } from '@finos/legend-shared';
42
- import { action, makeObservable, observable } from 'mobx';
47
+ import { action, flow, flowResult, makeObservable, observable } from 'mobx';
43
48
  import { QUERY_BUILDER_STATE_HASH_STRUCTURE } from './QueryBuilderStateHashUtils.js';
44
49
  import type { QueryBuilderState } from './QueryBuilderState.js';
45
50
  import {
@@ -152,10 +157,13 @@ export class QueryBuilderSimpleConstantExpressionState
152
157
  export class QueryBuilderConstantLambdaEditorState extends LambdaEditorState {
153
158
  readonly queryBuilderState: QueryBuilderState;
154
159
  calculatedState: QueryBuilderCalculatedConstantExpressionState;
160
+ convertingLambdaToStringState = ActionState.create();
161
+
155
162
  constructor(calculatedState: QueryBuilderCalculatedConstantExpressionState) {
156
163
  super('', '');
157
164
  makeObservable(this, {
158
165
  calculatedState: observable,
166
+ convertingLambdaToStringState: observable,
159
167
  buildEmptyValueSpec: observable,
160
168
  });
161
169
  this.calculatedState = calculatedState;
@@ -184,6 +192,7 @@ export class QueryBuilderConstantLambdaEditorState extends LambdaEditorState {
184
192
  override *convertLambdaGrammarStringToObject(): GeneratorFn<void> {
185
193
  if (this.lambdaString) {
186
194
  try {
195
+ this.convertingLambdaToStringState.inProgress();
187
196
  const valSpec =
188
197
  (yield this.queryBuilderState.graphManagerState.graphManager.pureCodeToValueSpecification(
189
198
  this.fullLambdaString,
@@ -199,10 +208,13 @@ export class QueryBuilderConstantLambdaEditorState extends LambdaEditorState {
199
208
  LogEvent.create(GRAPH_MANAGER_EVENT.PARSING_FAILURE),
200
209
  error,
201
210
  );
211
+ } finally {
212
+ this.convertingLambdaToStringState.complete();
202
213
  }
203
214
  } else {
204
215
  this.clearErrors();
205
216
  this.calculatedState.setValue(this.buildEmptyValueSpec());
217
+ this.convertingLambdaToStringState.complete();
206
218
  }
207
219
  }
208
220
  override *convertLambdaObjectToGrammarString(
@@ -252,14 +264,45 @@ export class QueryBuilderCalculatedConstantExpressionState
252
264
  lambdaState: observable,
253
265
  value: observable,
254
266
  setValue: action,
267
+ updateVariableExpressionType: flow,
255
268
  });
256
269
  this.value = value;
257
270
  this.lambdaState = new QueryBuilderConstantLambdaEditorState(this);
271
+ observe_ValueSpecification(
272
+ variable,
273
+ this.queryBuilderState.observerContext,
274
+ );
258
275
  }
259
276
 
260
277
  setValue(val: PlainObject): void {
261
278
  this.value = val;
262
279
  }
280
+
281
+ *updateVariableExpressionType(): GeneratorFn<void> {
282
+ try {
283
+ if (this.lambdaState.lambdaString) {
284
+ yield flowResult(this.lambdaState.convertLambdaGrammarStringToObject());
285
+ }
286
+ const rawLambda = new RawLambda([], [this.value]);
287
+ const type =
288
+ (yield this.queryBuilderState.graphManagerState.graphManager.getLambdaReturnType(
289
+ rawLambda,
290
+ new PureModel(new CoreModel([]), new SystemModel([]), []),
291
+ )) as string;
292
+ const resolvedType =
293
+ this.queryBuilderState.graphManagerState.graph.getType(type);
294
+ valueSpecification_setGenericType(
295
+ this.variable,
296
+ GenericTypeExplicitReference.create(new GenericType(resolvedType)),
297
+ );
298
+ } catch (error) {
299
+ assertErrorThrown(error);
300
+ this.queryBuilderState.applicationStore.logService.error(
301
+ LogEvent.create(GRAPH_MANAGER_EVENT.COMPILATION_FAILURE),
302
+ error,
303
+ );
304
+ }
305
+ }
263
306
  }
264
307
 
265
308
  export class QueryBuilderConstantsState implements Hashable {
@@ -552,6 +552,7 @@ export abstract class QueryBuilderState implements CommandRegistrar {
552
552
  if (this.parametersState.parameterStates.length > 0) {
553
553
  this.setShowParametersPanel(true);
554
554
  }
555
+ this.fetchStructureState.initializeWithQuery();
555
556
  } catch (error) {
556
557
  assertErrorThrown(error);
557
558
  this.resetQueryResult({ preserveResult: options?.preserveResult });