@finos/legend-query-builder 0.6.15 → 0.6.16

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 (70) hide show
  1. package/lib/components/QueryBuilder.js +2 -2
  2. package/lib/components/QueryBuilderConstantExpressionPanel.d.ts.map +1 -1
  3. package/lib/components/QueryBuilderConstantExpressionPanel.js +1 -0
  4. package/lib/components/QueryBuilderConstantExpressionPanel.js.map +1 -1
  5. package/lib/components/QueryBuilderParametersPanel.d.ts.map +1 -1
  6. package/lib/components/QueryBuilderParametersPanel.js +1 -0
  7. package/lib/components/QueryBuilderParametersPanel.js.map +1 -1
  8. package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
  9. package/lib/components/QueryBuilderResultPanel.js +4 -2
  10. package/lib/components/QueryBuilderResultPanel.js.map +1 -1
  11. package/lib/components/QueryBuilderSideBar.d.ts +2 -1
  12. package/lib/components/QueryBuilderSideBar.d.ts.map +1 -1
  13. package/lib/components/QueryBuilderSideBar.js +3 -0
  14. package/lib/components/QueryBuilderSideBar.js.map +1 -1
  15. package/lib/components/QueryBuilder_TestID.d.ts +2 -1
  16. package/lib/components/QueryBuilder_TestID.d.ts.map +1 -1
  17. package/lib/components/QueryBuilder_TestID.js +1 -0
  18. package/lib/components/QueryBuilder_TestID.js.map +1 -1
  19. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.d.ts.map +1 -1
  20. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js +2 -2
  21. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js.map +1 -1
  22. package/lib/components/shared/BasicValueSpecificationEditor.d.ts.map +1 -1
  23. package/lib/components/shared/BasicValueSpecificationEditor.js +19 -23
  24. package/lib/components/shared/BasicValueSpecificationEditor.js.map +1 -1
  25. package/lib/components/shared/LambdaEditor.d.ts.map +1 -1
  26. package/lib/components/shared/LambdaEditor.js +5 -1
  27. package/lib/components/shared/LambdaEditor.js.map +1 -1
  28. package/lib/components/workflows/ClassQueryBuilder.d.ts.map +1 -1
  29. package/lib/components/workflows/ClassQueryBuilder.js +2 -0
  30. package/lib/components/workflows/ClassQueryBuilder.js.map +1 -1
  31. package/lib/components/workflows/MappingQueryBuilder.d.ts.map +1 -1
  32. package/lib/components/workflows/MappingQueryBuilder.js +2 -0
  33. package/lib/components/workflows/MappingQueryBuilder.js.map +1 -1
  34. package/lib/index.css +1 -1
  35. package/lib/index.css.map +1 -1
  36. package/lib/index.d.ts +3 -0
  37. package/lib/index.d.ts.map +1 -1
  38. package/lib/index.js +3 -0
  39. package/lib/index.js.map +1 -1
  40. package/lib/package.json +4 -4
  41. package/lib/stores/QueryBuilderResultState.js +2 -2
  42. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  43. package/lib/stores/explorer/QueryBuilderExplorerState.js +2 -2
  44. package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
  45. package/lib/stores/explorer/QueryFunctionsExplorerState.d.ts +1 -1
  46. package/lib/stores/explorer/QueryFunctionsExplorerState.d.ts.map +1 -1
  47. package/lib/stores/explorer/QueryFunctionsExplorerState.js +15 -13
  48. package/lib/stores/explorer/QueryFunctionsExplorerState.js.map +1 -1
  49. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js +1 -1
  50. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
  51. package/lib/stores/filter/QueryBuilderFilterState.js +1 -1
  52. package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
  53. package/package.json +11 -11
  54. package/src/components/QueryBuilder.tsx +2 -2
  55. package/src/components/QueryBuilderConstantExpressionPanel.tsx +1 -0
  56. package/src/components/QueryBuilderParametersPanel.tsx +1 -0
  57. package/src/components/QueryBuilderResultPanel.tsx +7 -1
  58. package/src/components/QueryBuilderSideBar.tsx +5 -0
  59. package/src/components/QueryBuilder_TestID.ts +1 -0
  60. package/src/components/fetch-structure/QueryBuilderResultModifierPanel.tsx +2 -7
  61. package/src/components/shared/BasicValueSpecificationEditor.tsx +82 -44
  62. package/src/components/shared/LambdaEditor.tsx +15 -6
  63. package/src/components/workflows/ClassQueryBuilder.tsx +2 -0
  64. package/src/components/workflows/MappingQueryBuilder.tsx +2 -0
  65. package/src/index.ts +4 -0
  66. package/src/stores/QueryBuilderResultState.ts +2 -2
  67. package/src/stores/explorer/QueryBuilderExplorerState.ts +2 -2
  68. package/src/stores/explorer/QueryFunctionsExplorerState.ts +26 -23
  69. package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +1 -1
  70. package/src/stores/filter/QueryBuilderFilterState.ts +1 -1
@@ -29,6 +29,9 @@ import {
29
29
  SaveIcon,
30
30
  PencilIcon,
31
31
  DragPreviewLayer,
32
+ FilledWindowMaximizeIcon,
33
+ BasePopover,
34
+ PanelFormSection,
32
35
  } from '@finos/legend-art';
33
36
  import {
34
37
  type Enum,
@@ -58,6 +61,7 @@ import {
58
61
  isNonNullable,
59
62
  returnUndefOnError,
60
63
  uniq,
64
+ parseCSVString,
61
65
  } from '@finos/legend-shared';
62
66
  import { flowResult } from 'mobx';
63
67
  import { observer } from 'mobx-react-lite';
@@ -465,26 +469,14 @@ const setCollectionValue = (
465
469
  return;
466
470
  }
467
471
  let result: unknown[] = [];
468
- const parseResult = CSVParser.parse<string[]>(value.trim(), {
469
- delimiter: ',',
470
- });
471
- const parseData = parseResult.data[0] as string[]; // only take the first line
472
- if (parseResult.errors.length) {
473
- if (
474
- parseResult.errors[0] &&
475
- parseResult.errors[0].code === 'UndetectableDelimiter' &&
476
- parseResult.errors[0].type === 'Delimiter' &&
477
- parseResult.data.length === 1
478
- ) {
479
- // NOTE: this happens when the user only put one item in the value input
480
- // we can go the other way by ensure the input has a comma but this is arguably neater
481
- // as it tinkers with the parser
482
- } else {
483
- // there were some parsing error, escape
484
- // NOTE: ideally, we could show a warning here
485
- return;
486
- }
487
- } else if (expectedType instanceof PrimitiveType) {
472
+
473
+ const parseData = parseCSVString(value);
474
+
475
+ if (!parseData) {
476
+ return;
477
+ }
478
+
479
+ if (expectedType instanceof PrimitiveType) {
488
480
  switch (expectedType.path) {
489
481
  case PRIMITIVE_TYPE.STRING: {
490
482
  result = uniq(parseData)
@@ -568,6 +560,8 @@ const CollectionValueInstanceValueEditor = observer(
568
560
  const inputRef = useRef<HTMLInputElement>(null);
569
561
  const [text, setText] = useState(stringifyValue(valueSpecification.values));
570
562
  const [editable, setEditable] = useState(false);
563
+ const [showAdvancedEditorPopover, setShowAdvancedEditorPopover] =
564
+ useState(false);
571
565
  const valueText = stringifyValue(valueSpecification.values);
572
566
  const previewText = `List(${
573
567
  valueSpecification.values.length === 0
@@ -585,12 +579,19 @@ const CollectionValueInstanceValueEditor = observer(
585
579
  const enableEdit = (): void => setEditable(true);
586
580
  const saveEdit = (): void => {
587
581
  setEditable(false);
582
+ setShowAdvancedEditorPopover(false);
588
583
  setCollectionValue(valueSpecification, expectedType, text);
589
584
  setText(stringifyValue(valueSpecification.values));
590
585
  setValueSpecification(valueSpecification);
591
586
  };
592
- const changeValue: React.ChangeEventHandler<HTMLInputElement> = (event) =>
587
+ const changeValue: React.ChangeEventHandler<HTMLInputElement> = (event) => {
588
+ setText(event.target.value);
589
+ };
590
+ const changeValueTextArea: React.ChangeEventHandler<HTMLTextAreaElement> = (
591
+ event,
592
+ ) => {
593
593
  setText(event.target.value);
594
+ };
594
595
 
595
596
  // focus the input box when edit is enabled
596
597
  useEffect(() => {
@@ -601,29 +602,66 @@ const CollectionValueInstanceValueEditor = observer(
601
602
 
602
603
  if (editable) {
603
604
  return (
604
- <div className={clsx('value-spec-editor', className)}>
605
- <input
606
- ref={inputRef}
607
- className="panel__content__form__section__input value-spec-editor__input"
608
- spellCheck={false}
609
- value={text}
610
- placeholder={text === '' ? '(empty)' : undefined}
611
- onChange={changeValue}
612
- />
613
- <button
614
- className="value-spec-editor__list-editor__save-button btn--dark"
615
- onClick={saveEdit}
616
- >
617
- <SaveIcon />
618
- </button>
619
- <button
620
- className="value-spec-editor__reset-btn"
621
- title="Reset"
622
- onClick={resetValue}
623
- >
624
- <RefreshIcon />
625
- </button>
626
- </div>
605
+ <>
606
+ {showAdvancedEditorPopover && (
607
+ <BasePopover
608
+ onClose={() => setShowAdvancedEditorPopover(false)}
609
+ open={showAdvancedEditorPopover}
610
+ anchorEl={inputRef.current}
611
+ >
612
+ <textarea
613
+ className="panel__content__form__section__input value-spec-editor__list-editor__textarea"
614
+ spellCheck={false}
615
+ value={text}
616
+ placeholder={text === '' ? '(empty)' : undefined}
617
+ onChange={changeValueTextArea}
618
+ onKeyDown={(event): void => {
619
+ if (event.key === 'Enter' && !event.shiftKey) {
620
+ saveEdit();
621
+ }
622
+ }}
623
+ />
624
+ <PanelFormSection>
625
+ <div className="value-spec-editor__list-editor__textarea__description">
626
+ Hit Enter to Apply Change
627
+ </div>
628
+ </PanelFormSection>
629
+ </BasePopover>
630
+ )}
631
+ <div className={clsx('value-spec-editor', className)}>
632
+ <input
633
+ ref={inputRef}
634
+ className={clsx(
635
+ 'panel__content__form__section__input value-spec-editor__input',
636
+ )}
637
+ spellCheck={false}
638
+ value={text}
639
+ placeholder={text === '' ? '(empty)' : undefined}
640
+ onChange={changeValue}
641
+ />
642
+ <button
643
+ className="value-spec-editor__list-editor__expand-button btn--dark"
644
+ onClick={() => setShowAdvancedEditorPopover(true)}
645
+ tabIndex={-1}
646
+ title="Expand window..."
647
+ >
648
+ <FilledWindowMaximizeIcon />
649
+ </button>
650
+ <button
651
+ className="value-spec-editor__list-editor__save-button btn--dark"
652
+ onClick={saveEdit}
653
+ >
654
+ <SaveIcon />
655
+ </button>
656
+ <button
657
+ className="value-spec-editor__reset-btn"
658
+ title="Reset"
659
+ onClick={resetValue}
660
+ >
661
+ <RefreshIcon />
662
+ </button>
663
+ </div>
664
+ </>
627
665
  );
628
666
  }
629
667
  return (
@@ -464,7 +464,9 @@ const LambdaEditorPopUp = observer(
464
464
  const _editor = monacoEditorAPI.create(element, {
465
465
  ...getBaseTextEditorOptions(),
466
466
  language: EDITOR_LANGUAGE.PURE,
467
- theme: EDITOR_THEME.LEGEND,
467
+ theme: applicationStore.TEMPORARY__isLightThemeEnabled
468
+ ? EDITOR_THEME.TEMPORARY__VSCODE_LIGHT
469
+ : EDITOR_THEME.LEGEND,
468
470
  });
469
471
  setEditor(_editor);
470
472
  }
@@ -584,11 +586,18 @@ const LambdaEditorPopUp = observer(
584
586
  >
585
587
  <Modal
586
588
  darkMode={true}
587
- className={clsx('editor-modal lambda-editor__popup__modal', {
588
- 'lambda-editor__popup__modal--has-error': Boolean(
589
- lambdaEditorState.parserError,
590
- ),
591
- })}
589
+ className={clsx(
590
+ 'editor-modal lambda-editor__popup__modal',
591
+ {
592
+ 'lambda-editor__popup__modal--has-error': Boolean(
593
+ lambdaEditorState.parserError,
594
+ ),
595
+ },
596
+ {
597
+ 'lambda-editor--light':
598
+ applicationStore.TEMPORARY__isLightThemeEnabled,
599
+ },
600
+ )}
592
601
  >
593
602
  <ModalHeader>
594
603
  <ModalTitle title="Edit Lambda" />
@@ -157,6 +157,7 @@ const ClassQueryBuilderSetupPanelContent = observer(
157
157
  filterOption={mappingFilterOption}
158
158
  formatOptionLabel={getPackageableElementOptionFormatter({
159
159
  darkMode: !applicationStore.TEMPORARY__isLightThemeEnabled,
160
+ pureModel: queryBuilderState.graphManagerState.graph,
160
161
  })}
161
162
  />
162
163
  </div>
@@ -181,6 +182,7 @@ const ClassQueryBuilderSetupPanelContent = observer(
181
182
  filterOption={runtimeFilterOption}
182
183
  formatOptionLabel={getRuntimeOptionFormatter({
183
184
  darkMode: !applicationStore.TEMPORARY__isLightThemeEnabled,
185
+ pureModel: queryBuilderState.graphManagerState.graph,
184
186
  })}
185
187
  />
186
188
  </div>
@@ -151,6 +151,7 @@ const MappingQueryBuilderSetupPanelContent = observer(
151
151
  filterOption={mappingFilterOption}
152
152
  formatOptionLabel={getPackageableElementOptionFormatter({
153
153
  darkMode: !applicationStore.TEMPORARY__isLightThemeEnabled,
154
+ pureModel: queryBuilderState.graphManagerState.graph,
154
155
  })}
155
156
  />
156
157
  </div>
@@ -173,6 +174,7 @@ const MappingQueryBuilderSetupPanelContent = observer(
173
174
  filterOption={runtimeFilterOption}
174
175
  formatOptionLabel={getRuntimeOptionFormatter({
175
176
  darkMode: !applicationStore.TEMPORARY__isLightThemeEnabled,
177
+ pureModel: queryBuilderState.graphManagerState.graph,
176
178
  })}
177
179
  />
178
180
  </div>
package/src/index.ts CHANGED
@@ -45,6 +45,9 @@ export type { MappingRuntimeCompatibilityAnalysisResult } from './graphManager/a
45
45
  export * from './stores/ServiceInfo.js';
46
46
  export * from './components/ServiceQuerySetupUtils.js';
47
47
  export * from './components/QuerySetupUtils.js';
48
+ export * from './components/QueryBuilderTextEditor.js';
49
+
50
+ export { TEST__setUpQueryBuilder } from './components/QueryBuilderComponentTestUtils.js';
48
51
 
49
52
  // ------------------------------------------- Shared components -------------------------------------------
50
53
 
@@ -56,3 +59,4 @@ export { LambdaEditorState } from './stores/shared/LambdaEditorState.js';
56
59
  export * from './stores/shared/LambdaParameterState.js';
57
60
  export * from './stores/shared/ValueSpecificationModifierHelper.js';
58
61
  export * from './stores/shared/ValueSpecificationEditorHelper.js';
62
+ export { QueryBuilderTextEditorMode } from './stores/QueryBuilderTextEditorState.js';
@@ -154,7 +154,7 @@ export class QueryBuilderResultState {
154
154
  );
155
155
  const query = this.buildExecutionRawLambda();
156
156
  const result =
157
- (yield this.queryBuilderState.graphManagerState.graphManager.executeMapping(
157
+ (yield this.queryBuilderState.graphManagerState.graphManager.runQuery(
158
158
  query,
159
159
  mapping,
160
160
  runtime,
@@ -212,7 +212,7 @@ export class QueryBuilderResultState {
212
212
  const query = this.buildExecutionRawLambda();
213
213
  const startTime = Date.now();
214
214
  const promise =
215
- this.queryBuilderState.graphManagerState.graphManager.executeMapping(
215
+ this.queryBuilderState.graphManagerState.graphManager.runQuery(
216
216
  query,
217
217
  mapping,
218
218
  runtime,
@@ -717,7 +717,7 @@ export class QueryBuilderExplorerState {
717
717
  case PRIMITIVE_TYPE.DECIMAL:
718
718
  case PRIMITIVE_TYPE.FLOAT: {
719
719
  const previewResult =
720
- (yield this.queryBuilderState.graphManagerState.graphManager.executeMapping(
720
+ (yield this.queryBuilderState.graphManagerState.graphManager.runQuery(
721
721
  buildNumericPreviewDataQuery(
722
722
  this.queryBuilderState,
723
723
  propertyExpression,
@@ -754,7 +754,7 @@ export class QueryBuilderExplorerState {
754
754
  case PRIMITIVE_TYPE.STRICTDATE:
755
755
  case PRIMITIVE_TYPE.DATETIME: {
756
756
  const previewResult =
757
- (yield this.queryBuilderState.graphManagerState.graphManager.executeMapping(
757
+ (yield this.queryBuilderState.graphManagerState.graphManager.runQuery(
758
758
  buildNonNumericPreviewDataQuery(
759
759
  this.queryBuilderState,
760
760
  propertyExpression,
@@ -139,7 +139,7 @@ const generateFunctionsExplorerTreeNodeChilrdren = (
139
139
  };
140
140
 
141
141
  export const getFunctionsExplorerTreeData = (
142
- root: Package,
142
+ roots: Package[],
143
143
  queryBuilderState: QueryBuilderState,
144
144
  rootPackageName = ROOT_PACKAGE_NAME.MAIN,
145
145
  ): TreeData<QueryBuilderFunctionsExplorerTreeNodeData> => {
@@ -164,26 +164,29 @@ export const getFunctionsExplorerTreeData = (
164
164
  }
165
165
  }
166
166
 
167
- root.children
168
- .slice()
169
- .filter((child) => !(child instanceof Unit))
170
- .filter(
171
- (child) =>
172
- child instanceof Package && validDisplayablePackageSet.has(child),
173
- )
174
- .sort((a, b) => a.name.localeCompare(b.name))
175
- .sort(
176
- (a, b) => (b instanceof Package ? 1 : 0) - (a instanceof Package ? 1 : 0),
177
- )
178
- .forEach((childPackage) => {
179
- const childTreeNodeData = generateFunctionsExplorerTreeNodeData(
180
- queryBuilderState,
181
- childPackage,
182
- rootPackageName,
183
- );
184
- addUniqueEntry(rootIds, childTreeNodeData.id);
185
- nodes.set(childTreeNodeData.id, childTreeNodeData);
186
- });
167
+ roots.forEach((root) => {
168
+ root.children
169
+ .slice()
170
+ .filter((child) => !(child instanceof Unit))
171
+ .filter(
172
+ (child) =>
173
+ child instanceof Package && validDisplayablePackageSet.has(child),
174
+ )
175
+ .sort((a, b) => a.name.localeCompare(b.name))
176
+ .sort(
177
+ (a, b) =>
178
+ (b instanceof Package ? 1 : 0) - (a instanceof Package ? 1 : 0),
179
+ )
180
+ .forEach((childPackage) => {
181
+ const childTreeNodeData = generateFunctionsExplorerTreeNodeData(
182
+ queryBuilderState,
183
+ childPackage,
184
+ rootPackageName,
185
+ );
186
+ addUniqueEntry(rootIds, childTreeNodeData.id);
187
+ nodes.set(childTreeNodeData.id, childTreeNodeData);
188
+ });
189
+ });
187
190
  return { rootIds, nodes };
188
191
  };
189
192
 
@@ -343,7 +346,7 @@ export class QueryFunctionsExplorerState {
343
346
  this.initializeDisplayablePackagesSet().finally(() => {
344
347
  this.setTreeData(
345
348
  getFunctionsExplorerTreeData(
346
- this.queryBuilderState.graphManagerState.graph.root,
349
+ [this.queryBuilderState.graphManagerState.graph.root],
347
350
  this.queryBuilderState,
348
351
  ),
349
352
  );
@@ -360,7 +363,7 @@ export class QueryFunctionsExplorerState {
360
363
  this.setDependencyTreeData(
361
364
  getFunctionsExplorerTreeData(
362
365
  this.queryBuilderState.graphManagerState.graph.dependencyManager
363
- .root,
366
+ .roots,
364
367
  this.queryBuilderState,
365
368
  ROOT_PACKAGE_NAME.PROJECT_DEPENDENCY_ROOT,
366
369
  ),
@@ -373,7 +373,7 @@ export class PostFilterConditionState implements Hashable {
373
373
  const columnState = guaranteeNonNullable(_columnState);
374
374
  if (performTypeahead(this.value)) {
375
375
  const result =
376
- (yield this.postFilterState.tdsState.queryBuilderState.graphManagerState.graphManager.executeMapping(
376
+ (yield this.postFilterState.tdsState.queryBuilderState.graphManagerState.graphManager.runQuery(
377
377
  buildProjectionColumnTypeaheadQuery(
378
378
  this.postFilterState.tdsState.queryBuilderState,
379
379
  columnState,
@@ -128,7 +128,7 @@ export class FilterConditionState implements Hashable {
128
128
  this.typeaheadSearchResults = undefined;
129
129
  if (performTypeahead(this.value)) {
130
130
  const result =
131
- (yield this.filterState.queryBuilderState.graphManagerState.graphManager.executeMapping(
131
+ (yield this.filterState.queryBuilderState.graphManagerState.graphManager.runQuery(
132
132
  buildPropertyTypeaheadQuery(
133
133
  this.filterState.queryBuilderState,
134
134
  this.propertyExpressionState.propertyExpression,