@finos/legend-query-builder 4.7.4 → 4.8.0

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.
Files changed (83) hide show
  1. package/lib/components/QueryBuilderConstantExpressionPanel.d.ts.map +1 -1
  2. package/lib/components/QueryBuilderConstantExpressionPanel.js +24 -8
  3. package/lib/components/QueryBuilderConstantExpressionPanel.js.map +1 -1
  4. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  5. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +5 -3
  6. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  7. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  8. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +8 -1
  9. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  10. package/lib/components/shared/LambdaEditor.d.ts +1 -11
  11. package/lib/components/shared/LambdaEditor.d.ts.map +1 -1
  12. package/lib/components/shared/LambdaEditor.js +11 -4
  13. package/lib/components/shared/LambdaEditor.js.map +1 -1
  14. package/lib/index.css +2 -2
  15. package/lib/index.css.map +1 -1
  16. package/lib/package.json +1 -1
  17. package/lib/stores/QueryBuilderConstantsState.d.ts +2 -1
  18. package/lib/stores/QueryBuilderConstantsState.d.ts.map +1 -1
  19. package/lib/stores/QueryBuilderConstantsState.js +9 -1
  20. package/lib/stores/QueryBuilderConstantsState.js.map +1 -1
  21. package/lib/stores/QueryBuilderState.d.ts.map +1 -1
  22. package/lib/stores/QueryBuilderState.js +1 -0
  23. package/lib/stores/QueryBuilderState.js.map +1 -1
  24. package/lib/stores/QueryBuilderTypeaheadHelper.d.ts +1 -1
  25. package/lib/stores/QueryBuilderTypeaheadHelper.d.ts.map +1 -1
  26. package/lib/stores/QueryBuilderTypeaheadHelper.js +190 -30
  27. package/lib/stores/QueryBuilderTypeaheadHelper.js.map +1 -1
  28. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.d.ts +1 -0
  29. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.d.ts.map +1 -1
  30. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.js.map +1 -1
  31. package/lib/stores/fetch-structure/QueryBuilderFetchStructureState.d.ts +1 -0
  32. package/lib/stores/fetch-structure/QueryBuilderFetchStructureState.d.ts.map +1 -1
  33. package/lib/stores/fetch-structure/QueryBuilderFetchStructureState.js +4 -0
  34. package/lib/stores/fetch-structure/QueryBuilderFetchStructureState.js.map +1 -1
  35. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts +1 -0
  36. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts.map +1 -1
  37. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js +3 -0
  38. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js.map +1 -1
  39. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts +2 -0
  40. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts.map +1 -1
  41. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js +25 -1
  42. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js.map +1 -1
  43. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts +3 -1
  44. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts.map +1 -1
  45. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js +6 -0
  46. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
  47. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.d.ts +9 -2
  48. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.d.ts.map +1 -1
  49. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.js +40 -6
  50. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.js.map +1 -1
  51. package/lib/stores/milestoning/QueryBuilderBitemporalMilestoningImplementation.d.ts +1 -0
  52. package/lib/stores/milestoning/QueryBuilderBitemporalMilestoningImplementation.d.ts.map +1 -1
  53. package/lib/stores/milestoning/QueryBuilderBitemporalMilestoningImplementation.js +8 -1
  54. package/lib/stores/milestoning/QueryBuilderBitemporalMilestoningImplementation.js.map +1 -1
  55. package/lib/stores/milestoning/QueryBuilderBusinessTemporalMilestoningImplementation.d.ts +1 -0
  56. package/lib/stores/milestoning/QueryBuilderBusinessTemporalMilestoningImplementation.d.ts.map +1 -1
  57. package/lib/stores/milestoning/QueryBuilderBusinessTemporalMilestoningImplementation.js +7 -1
  58. package/lib/stores/milestoning/QueryBuilderBusinessTemporalMilestoningImplementation.js.map +1 -1
  59. package/lib/stores/milestoning/QueryBuilderMilestoningImplementation.d.ts +4 -0
  60. package/lib/stores/milestoning/QueryBuilderMilestoningImplementation.d.ts.map +1 -1
  61. package/lib/stores/milestoning/QueryBuilderMilestoningImplementation.js.map +1 -1
  62. package/lib/stores/milestoning/QueryBuilderProcessingTemporalMilestoningImplementation.d.ts +1 -0
  63. package/lib/stores/milestoning/QueryBuilderProcessingTemporalMilestoningImplementation.d.ts.map +1 -1
  64. package/lib/stores/milestoning/QueryBuilderProcessingTemporalMilestoningImplementation.js +7 -1
  65. package/lib/stores/milestoning/QueryBuilderProcessingTemporalMilestoningImplementation.js.map +1 -1
  66. package/package.json +3 -3
  67. package/src/components/QueryBuilderConstantExpressionPanel.tsx +81 -24
  68. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +11 -1
  69. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +12 -1
  70. package/src/components/shared/LambdaEditor.tsx +15 -2
  71. package/src/stores/QueryBuilderConstantsState.ts +12 -0
  72. package/src/stores/QueryBuilderState.ts +1 -0
  73. package/src/stores/QueryBuilderTypeaheadHelper.ts +382 -54
  74. package/src/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.ts +1 -0
  75. package/src/stores/fetch-structure/QueryBuilderFetchStructureState.ts +5 -0
  76. package/src/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.ts +4 -0
  77. package/src/stores/fetch-structure/tds/QueryBuilderTDSState.ts +43 -1
  78. package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +11 -0
  79. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.ts +66 -9
  80. package/src/stores/milestoning/QueryBuilderBitemporalMilestoningImplementation.ts +14 -0
  81. package/src/stores/milestoning/QueryBuilderBusinessTemporalMilestoningImplementation.ts +13 -0
  82. package/src/stores/milestoning/QueryBuilderMilestoningImplementation.ts +7 -0
  83. 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,84 @@ 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
+ const applicationStore = queryBuilderState.applicationStore;
224
+ const changeConstantName: React.ChangeEventHandler<HTMLInputElement> = (
225
+ event,
226
+ ) => {
227
+ variableExpression_setName(constantState.variable, event.target.value);
228
+ };
229
+ useEffect(() => {
230
+ flowResult(
231
+ lambdaState.convertLambdaObjectToGrammarString({
232
+ pretty: true,
233
+ }),
234
+ ).catch(applicationStore.alertUnhandledError);
235
+ }, [applicationStore, lambdaState]);
230
236
  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
- </>
237
+ <Dialog
238
+ open={true}
239
+ onClose={close}
240
+ classes={{
241
+ root: 'editor-modal__root-container',
242
+ container: 'editor-modal__container',
243
+ paper: 'editor-modal__content',
244
+ }}
245
+ >
246
+ <Modal
247
+ darkMode={true}
248
+ className={clsx('editor-modal query-builder__constants__modal', {
249
+ 'query-builder__constants__modal--has-error': Boolean(
250
+ lambdaState.parserError,
251
+ ),
252
+ })}
253
+ >
254
+ <ModalHeader>
255
+ <div className="modal__title">Update Calculated Constants</div>
256
+ {lambdaState.parserError && (
257
+ <div className="modal__title__error-badge">
258
+ Failed to parse query
259
+ </div>
260
+ )}
261
+ </ModalHeader>
262
+ <ModalBody>
263
+ <div
264
+ className={clsx('query-builder__constants__modal__content', {
265
+ backdrop__element: Boolean(lambdaState.parserError),
266
+ })}
267
+ >
268
+ <div className="query-builder__constants__modal__name">
269
+ <InputWithInlineValidation
270
+ className="query-builder__constants__modal__name__input input--dark"
271
+ spellCheck={false}
272
+ value={constantState.variable.name}
273
+ onChange={changeConstantName}
274
+ placeholder="Constant Name"
275
+ />
276
+ </div>
277
+ <LambdaEditor
278
+ className="query-builder__constants__lambda-editor"
279
+ disabled={
280
+ lambdaState.convertingLambdaToStringState.isInProgress
281
+ }
282
+ lambdaEditorState={lambdaState}
283
+ forceBackdrop={false}
284
+ autoFocus={true}
285
+ />
286
+ </div>
287
+ </ModalBody>
288
+ <ModalFooter>
289
+ <button
290
+ className="btn btn--dark"
291
+ onClick={close}
292
+ disabled={Boolean(lambdaState.parserError)}
293
+ >
294
+ Close
295
+ </button>
296
+ </ModalFooter>
297
+ </Modal>
298
+ </Dialog>
242
299
  );
243
300
  },
244
301
  );
@@ -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
@@ -38,6 +38,7 @@ import {
38
38
  LogEvent,
39
39
  changeEntry,
40
40
  assertTrue,
41
+ ActionState,
41
42
  } from '@finos/legend-shared';
42
43
  import { action, makeObservable, observable } from 'mobx';
43
44
  import { QUERY_BUILDER_STATE_HASH_STRUCTURE } from './QueryBuilderStateHashUtils.js';
@@ -152,10 +153,13 @@ export class QueryBuilderSimpleConstantExpressionState
152
153
  export class QueryBuilderConstantLambdaEditorState extends LambdaEditorState {
153
154
  readonly queryBuilderState: QueryBuilderState;
154
155
  calculatedState: QueryBuilderCalculatedConstantExpressionState;
156
+ convertingLambdaToStringState = ActionState.create();
157
+
155
158
  constructor(calculatedState: QueryBuilderCalculatedConstantExpressionState) {
156
159
  super('', '');
157
160
  makeObservable(this, {
158
161
  calculatedState: observable,
162
+ convertingLambdaToStringState: observable,
159
163
  buildEmptyValueSpec: observable,
160
164
  });
161
165
  this.calculatedState = calculatedState;
@@ -184,6 +188,7 @@ export class QueryBuilderConstantLambdaEditorState extends LambdaEditorState {
184
188
  override *convertLambdaGrammarStringToObject(): GeneratorFn<void> {
185
189
  if (this.lambdaString) {
186
190
  try {
191
+ this.convertingLambdaToStringState.inProgress();
187
192
  const valSpec =
188
193
  (yield this.queryBuilderState.graphManagerState.graphManager.pureCodeToValueSpecification(
189
194
  this.fullLambdaString,
@@ -199,10 +204,13 @@ export class QueryBuilderConstantLambdaEditorState extends LambdaEditorState {
199
204
  LogEvent.create(GRAPH_MANAGER_EVENT.PARSING_FAILURE),
200
205
  error,
201
206
  );
207
+ } finally {
208
+ this.convertingLambdaToStringState.complete();
202
209
  }
203
210
  } else {
204
211
  this.clearErrors();
205
212
  this.calculatedState.setValue(this.buildEmptyValueSpec());
213
+ this.convertingLambdaToStringState.complete();
206
214
  }
207
215
  }
208
216
  override *convertLambdaObjectToGrammarString(
@@ -255,6 +263,10 @@ export class QueryBuilderCalculatedConstantExpressionState
255
263
  });
256
264
  this.value = value;
257
265
  this.lambdaState = new QueryBuilderConstantLambdaEditorState(this);
266
+ observe_ValueSpecification(
267
+ variable,
268
+ this.queryBuilderState.observerContext,
269
+ );
258
270
  }
259
271
 
260
272
  setValue(val: PlainObject): void {
@@ -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 });