@finos/legend-query-builder 4.7.4 → 4.8.0

Sign up to get free protection for your applications and to get access to all the features.
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 });