@finos/legend-query-builder 0.6.15 → 0.6.16

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