@finos/legend-query-builder 4.4.0 → 4.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
  2. package/lib/components/QueryBuilderResultPanel.js +8 -2
  3. package/lib/components/QueryBuilderResultPanel.js.map +1 -1
  4. package/lib/components/execution-plan/AllocationExecutionNodeViewer.js +1 -1
  5. package/lib/components/execution-plan/AllocationExecutionNodeViewer.js.map +1 -1
  6. package/lib/components/execution-plan/ExecutionPlanViewer.d.ts +7 -0
  7. package/lib/components/execution-plan/ExecutionPlanViewer.d.ts.map +1 -1
  8. package/lib/components/execution-plan/ExecutionPlanViewer.js +109 -27
  9. package/lib/components/execution-plan/ExecutionPlanViewer.js.map +1 -1
  10. package/lib/components/execution-plan/FunctionParametersValidationNodeViewer.d.ts.map +1 -1
  11. package/lib/components/execution-plan/FunctionParametersValidationNodeViewer.js.map +1 -1
  12. package/lib/components/execution-plan/ImplementationViewer.d.ts +23 -0
  13. package/lib/components/execution-plan/ImplementationViewer.d.ts.map +1 -0
  14. package/lib/components/execution-plan/ImplementationViewer.js +35 -0
  15. package/lib/components/execution-plan/ImplementationViewer.js.map +1 -0
  16. package/lib/components/execution-plan/PartialClassResultViewer.d.ts +21 -0
  17. package/lib/components/execution-plan/PartialClassResultViewer.d.ts.map +1 -0
  18. package/lib/components/execution-plan/PartialClassResultViewer.js +24 -0
  19. package/lib/components/execution-plan/PartialClassResultViewer.js.map +1 -0
  20. package/lib/components/execution-plan/RelationalClassQueryTempTableGraphFetchExecutionNodeViewer.d.ts +23 -0
  21. package/lib/components/execution-plan/RelationalClassQueryTempTableGraphFetchExecutionNodeViewer.d.ts.map +1 -0
  22. package/lib/components/execution-plan/RelationalClassQueryTempTableGraphFetchExecutionNodeViewer.js +43 -0
  23. package/lib/components/execution-plan/RelationalClassQueryTempTableGraphFetchExecutionNodeViewer.js.map +1 -0
  24. package/lib/components/execution-plan/RelationalCrossRootQueryTempTableGraphFetchExecutionNodeViewer.d.ts +23 -0
  25. package/lib/components/execution-plan/RelationalCrossRootQueryTempTableGraphFetchExecutionNodeViewer.d.ts.map +1 -0
  26. package/lib/components/execution-plan/RelationalCrossRootQueryTempTableGraphFetchExecutionNodeViewer.js +47 -0
  27. package/lib/components/execution-plan/RelationalCrossRootQueryTempTableGraphFetchExecutionNodeViewer.js.map +1 -0
  28. package/lib/components/execution-plan/RelationalRootQueryTempTableGraphFetchExecutionNodeViewer.d.ts +23 -0
  29. package/lib/components/execution-plan/RelationalRootQueryTempTableGraphFetchExecutionNodeViewer.d.ts.map +1 -0
  30. package/lib/components/execution-plan/RelationalRootQueryTempTableGraphFetchExecutionNodeViewer.js +43 -0
  31. package/lib/components/execution-plan/RelationalRootQueryTempTableGraphFetchExecutionNodeViewer.js.map +1 -0
  32. package/lib/components/execution-plan/ResultTypeViewer.d.ts.map +1 -1
  33. package/lib/components/execution-plan/ResultTypeViewer.js +5 -1
  34. package/lib/components/execution-plan/ResultTypeViewer.js.map +1 -1
  35. package/lib/components/execution-plan/SQLExecutionNodeViewer.d.ts +1 -1
  36. package/lib/components/execution-plan/SQLExecutionNodeViewer.d.ts.map +1 -1
  37. package/lib/components/execution-plan/SQLExecutionNodeViewer.js +16 -3
  38. package/lib/components/execution-plan/SQLExecutionNodeViewer.js.map +1 -1
  39. package/lib/components/execution-plan/SequenceExecutionNodeViewer.d.ts +6 -0
  40. package/lib/components/execution-plan/SequenceExecutionNodeViewer.d.ts.map +1 -1
  41. package/lib/components/execution-plan/SequenceExecutionNodeViewer.js +34 -12
  42. package/lib/components/execution-plan/SequenceExecutionNodeViewer.js.map +1 -1
  43. package/lib/components/execution-plan/StoreMappingGlobalGraphFetchExecutionNodeViewer.d.ts +23 -0
  44. package/lib/components/execution-plan/StoreMappingGlobalGraphFetchExecutionNodeViewer.d.ts.map +1 -0
  45. package/lib/components/execution-plan/StoreMappingGlobalGraphFetchExecutionNodeViewer.js +57 -0
  46. package/lib/components/execution-plan/StoreMappingGlobalGraphFetchExecutionNodeViewer.js.map +1 -0
  47. package/lib/components/execution-plan/TempTableStrategyViewer.d.ts +28 -0
  48. package/lib/components/execution-plan/TempTableStrategyViewer.d.ts.map +1 -0
  49. package/lib/components/execution-plan/TempTableStrategyViewer.js +42 -0
  50. package/lib/components/execution-plan/TempTableStrategyViewer.js.map +1 -0
  51. package/lib/components/fetch-structure/QueryBuilderGraphFetchTreePanel.d.ts +7 -1
  52. package/lib/components/fetch-structure/QueryBuilderGraphFetchTreePanel.d.ts.map +1 -1
  53. package/lib/components/fetch-structure/QueryBuilderGraphFetchTreePanel.js +16 -10
  54. package/lib/components/fetch-structure/QueryBuilderGraphFetchTreePanel.js.map +1 -1
  55. package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
  56. package/lib/components/filter/QueryBuilderFilterPanel.js +21 -8
  57. package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
  58. package/lib/components/shared/CustomDatePicker.d.ts +2 -1
  59. package/lib/components/shared/CustomDatePicker.d.ts.map +1 -1
  60. package/lib/components/shared/CustomDatePicker.js +31 -19
  61. package/lib/components/shared/CustomDatePicker.js.map +1 -1
  62. package/lib/components/shared/QueryBuilderVariableSelector.d.ts.map +1 -1
  63. package/lib/components/shared/QueryBuilderVariableSelector.js +1 -1
  64. package/lib/components/shared/QueryBuilderVariableSelector.js.map +1 -1
  65. package/lib/index.css +2 -2
  66. package/lib/index.css.map +1 -1
  67. package/lib/package.json +1 -1
  68. package/lib/stores/execution-plan/ExecutionPlanState.d.ts +15 -1
  69. package/lib/stores/execution-plan/ExecutionPlanState.d.ts.map +1 -1
  70. package/lib/stores/execution-plan/ExecutionPlanState.js +50 -3
  71. package/lib/stores/execution-plan/ExecutionPlanState.js.map +1 -1
  72. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts.map +1 -1
  73. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js +16 -4
  74. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js.map +1 -1
  75. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeUtil.d.ts +6 -4
  76. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeUtil.d.ts.map +1 -1
  77. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeUtil.js +43 -9
  78. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeUtil.js.map +1 -1
  79. package/lib/stores/filter/QueryBuilderFilterState.d.ts +3 -2
  80. package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
  81. package/lib/stores/filter/QueryBuilderFilterState.js +7 -5
  82. package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
  83. package/lib/stores/filter/QueryBuilderFilterStateBuilder.d.ts.map +1 -1
  84. package/lib/stores/filter/QueryBuilderFilterStateBuilder.js +1 -1
  85. package/lib/stores/filter/QueryBuilderFilterStateBuilder.js.map +1 -1
  86. package/lib/stores/filter/QueryBuilderFilterValueSpecificationBuilder.d.ts.map +1 -1
  87. package/lib/stores/filter/QueryBuilderFilterValueSpecificationBuilder.js +5 -1
  88. package/lib/stores/filter/QueryBuilderFilterValueSpecificationBuilder.js.map +1 -1
  89. package/package.json +5 -5
  90. package/src/components/QueryBuilderResultPanel.tsx +7 -2
  91. package/src/components/execution-plan/AllocationExecutionNodeViewer.tsx +1 -1
  92. package/src/components/execution-plan/ExecutionPlanViewer.tsx +233 -57
  93. package/src/components/execution-plan/FunctionParametersValidationNodeViewer.tsx +1 -0
  94. package/src/components/execution-plan/ImplementationViewer.tsx +76 -0
  95. package/src/components/execution-plan/PartialClassResultViewer.tsx +55 -0
  96. package/src/components/execution-plan/RelationalClassQueryTempTableGraphFetchExecutionNodeViewer.tsx +190 -0
  97. package/src/components/execution-plan/RelationalCrossRootQueryTempTableGraphFetchExecutionNodeViewer.tsx +219 -0
  98. package/src/components/execution-plan/RelationalRootQueryTempTableGraphFetchExecutionNodeViewer.tsx +204 -0
  99. package/src/components/execution-plan/ResultTypeViewer.tsx +4 -0
  100. package/src/components/execution-plan/SQLExecutionNodeViewer.tsx +66 -44
  101. package/src/components/execution-plan/SequenceExecutionNodeViewer.tsx +79 -15
  102. package/src/components/execution-plan/StoreMappingGlobalGraphFetchExecutionNodeViewer.tsx +264 -0
  103. package/src/components/execution-plan/TempTableStrategyViewer.tsx +97 -0
  104. package/src/components/fetch-structure/QueryBuilderGraphFetchTreePanel.tsx +23 -9
  105. package/src/components/filter/QueryBuilderFilterPanel.tsx +43 -7
  106. package/src/components/shared/CustomDatePicker.tsx +65 -27
  107. package/src/components/shared/QueryBuilderVariableSelector.tsx +4 -1
  108. package/src/stores/execution-plan/ExecutionPlanState.ts +64 -1
  109. package/src/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.ts +17 -7
  110. package/src/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeUtil.ts +73 -9
  111. package/src/stores/filter/QueryBuilderFilterState.ts +13 -5
  112. package/src/stores/filter/QueryBuilderFilterStateBuilder.ts +1 -0
  113. package/src/stores/filter/QueryBuilderFilterValueSpecificationBuilder.ts +14 -1
  114. package/tsconfig.json +7 -0
@@ -47,6 +47,7 @@ import {
47
47
  BufferIcon,
48
48
  CustomSelectorInput,
49
49
  FolderIcon,
50
+ PURE_UnknownElementTypeIcon,
50
51
  } from '@finos/legend-art';
51
52
  import { QUERY_BUILDER_TEST_ID } from '../../__lib__/QueryBuilderTesting.js';
52
53
  import {
@@ -80,6 +81,8 @@ import {
80
81
  Binding,
81
82
  Package,
82
83
  getDescendantsOfPackage,
84
+ PropertyGraphFetchTree,
85
+ RootGraphFetchTree,
83
86
  } from '@finos/legend-graph';
84
87
  import {
85
88
  ActionAlertActionType,
@@ -115,20 +118,26 @@ const getBindingFormatter = (props: {
115
118
  );
116
119
  };
117
120
 
118
- const QueryBuilderGraphFetchTreeNodeContainer: React.FC<
121
+ export const QueryBuilderGraphFetchTreeNodeContainer: React.FC<
119
122
  TreeNodeContainerProps<
120
123
  QueryBuilderGraphFetchTreeNodeData,
121
124
  {
122
125
  isReadOnly: boolean;
123
- removeNode: (node: QueryBuilderGraphFetchTreeNodeData) => void;
126
+ removeNode?: (node: QueryBuilderGraphFetchTreeNodeData) => void;
124
127
  }
125
128
  >
126
129
  > = (props) => {
127
130
  const { node, level, stepPaddingInRem, onNodeSelect, innerProps } = props;
128
- const { removeNode } = innerProps;
129
- const property = node.tree.property.value;
130
- const type = property.genericType.value.rawType;
131
- const subType = node.tree.subType?.value;
131
+ const { isReadOnly, removeNode } = innerProps;
132
+ let property, type, subType;
133
+ if (node.tree instanceof PropertyGraphFetchTree) {
134
+ property = node.tree.property.value;
135
+ type = property.genericType.value.rawType;
136
+ subType = node.tree.subType?.value;
137
+ } else if (node.tree instanceof RootGraphFetchTree) {
138
+ type = node.tree.class.value;
139
+ }
140
+
132
141
  const isExpandable = Boolean(node.childrenIds.length);
133
142
  const nodeExpandIcon = isExpandable ? (
134
143
  node.isOpen ? (
@@ -139,9 +148,13 @@ const QueryBuilderGraphFetchTreeNodeContainer: React.FC<
139
148
  ) : (
140
149
  <div />
141
150
  );
142
- const nodeTypeIcon = getClassPropertyIcon(type);
151
+ const nodeTypeIcon = type ? (
152
+ getClassPropertyIcon(type)
153
+ ) : (
154
+ <PURE_UnknownElementTypeIcon />
155
+ );
143
156
  const toggleExpandNode = (): void => onNodeSelect?.(node);
144
- const deleteNode = (): void => removeNode(node);
157
+ const deleteNode = (): void => removeNode?.(node);
145
158
 
146
159
  return (
147
160
  <div
@@ -184,7 +197,7 @@ const QueryBuilderGraphFetchTreeNodeContainer: React.FC<
184
197
  {
185
198
  <div className="query-builder-graph-fetch-tree__node__type">
186
199
  <div className="query-builder-graph-fetch-tree__node__type__label">
187
- {type.name}
200
+ {type?.name}
188
201
  </div>
189
202
  </div>
190
203
  }
@@ -196,6 +209,7 @@ const QueryBuilderGraphFetchTreeNodeContainer: React.FC<
196
209
  title="Remove"
197
210
  tabIndex={-1}
198
211
  onClick={deleteNode}
212
+ disabled={isReadOnly}
199
213
  >
200
214
  <TimesIcon />
201
215
  </button>
@@ -45,6 +45,7 @@ import {
45
45
  MoreVerticalIcon,
46
46
  MenuContentItemIcon,
47
47
  MenuContentItemLabel,
48
+ InfoCircleIcon,
48
49
  } from '@finos/legend-art';
49
50
  import {
50
51
  type QueryBuilderFilterConditionDragSource,
@@ -66,7 +67,10 @@ import {
66
67
  buildPropertyExpressionFromExplorerTreeNodeData,
67
68
  QUERY_BUILDER_EXPLORER_TREE_DND_TYPE,
68
69
  } from '../../stores/explorer/QueryBuilderExplorerState.js';
69
- import { QueryBuilderPropertyExpressionBadge } from '../QueryBuilderPropertyExpressionEditor.js';
70
+ import {
71
+ QueryBuilderPropertyExpressionBadge,
72
+ QueryBuilderPropertyExpressionEditor,
73
+ } from '../QueryBuilderPropertyExpressionEditor.js';
70
74
  import type { QueryBuilderState } from '../../stores/QueryBuilderState.js';
71
75
  import {
72
76
  assertErrorThrown,
@@ -242,9 +246,12 @@ export const buildFilterTreeWithExists = (
242
246
  const parentPropertyChainIndex = existsLambdaPropertyChains.findIndex(
243
247
  (p) =>
244
248
  p instanceof AbstractPropertyExpression &&
245
- p.func.value === targetDropNode.propertyExpression.func.value &&
249
+ p.func.value ===
250
+ targetDropNode.propertyExpressionState.propertyExpression.func
251
+ .value &&
246
252
  p.func.ownerReference.value.path ===
247
- targetDropNode.propertyExpression.func.ownerReference.value.path,
253
+ targetDropNode.propertyExpressionState.propertyExpression.func
254
+ .ownerReference.value.path,
248
255
  );
249
256
  if (parentPropertyChainIndex >= 0) {
250
257
  parentNode = targetDropNode;
@@ -281,9 +288,10 @@ export const buildFilterTreeWithExists = (
281
288
  cn instanceof QueryBuilderFilterTreeExistsNodeData &&
282
289
  p.func.value ===
283
290
  guaranteeType(cn, QueryBuilderFilterTreeExistsNodeData)
284
- .propertyExpression.func.value &&
291
+ .propertyExpressionState.propertyExpression.func.value &&
285
292
  p.func.ownerReference.value.path ===
286
- cn.propertyExpression.func.ownerReference.value.path,
293
+ cn.propertyExpressionState.propertyExpression.func.ownerReference
294
+ .value.path,
287
295
  );
288
296
  if (parentPropertyChainIndex >= 0) {
289
297
  parentNode = targetDropNode;
@@ -302,7 +310,7 @@ export const buildFilterTreeWithExists = (
302
310
  // 3. Create exists tree node for all the property chains and add them to the filter tree
303
311
  for (let i = 0; i < existsLambdaPropertyChains.length - 1; ++i) {
304
312
  const existsNode: QueryBuilderFilterTreeExistsNodeData =
305
- new QueryBuilderFilterTreeExistsNodeData(parentNode?.id);
313
+ new QueryBuilderFilterTreeExistsNodeData(filterState, parentNode?.id);
306
314
  existsNode.setPropertyExpression(
307
315
  existsLambdaPropertyChains[i] as AbstractPropertyExpression,
308
316
  );
@@ -456,6 +464,15 @@ const QueryBuilderFilterExistsConditionEditor = observer(
456
464
  isDroppable: boolean;
457
465
  }) => {
458
466
  const { node, humanizePropertyName, isDragOver, isDroppable } = props;
467
+ const hasDerivedPropertyInExpression = Boolean(
468
+ node.propertyExpressionState.derivedPropertyExpressionStates.length,
469
+ );
470
+ const isValid = node.propertyExpressionState.isValid;
471
+ const setDerivedPropertyArguments = (): void => {
472
+ if (hasDerivedPropertyInExpression) {
473
+ node.propertyExpressionState.setIsEditingDerivedProperty(true);
474
+ }
475
+ };
459
476
 
460
477
  return (
461
478
  <div className="query-builder-filter-tree__node__label__content dnd__entry__container">
@@ -470,13 +487,32 @@ const QueryBuilderFilterExistsConditionEditor = observer(
470
487
  >
471
488
  <div className="query-builder-filter-tree__exists-node__label">
472
489
  {getPropertyChainName(
473
- node.propertyExpression,
490
+ node.propertyExpressionState.propertyExpression,
474
491
  humanizePropertyName,
475
492
  )}
476
493
  </div>
477
494
  <div className="query-builder-filter-tree__exists-node__exists--label">
478
495
  exists
479
496
  </div>
497
+ {hasDerivedPropertyInExpression && (
498
+ <button
499
+ className={clsx(
500
+ 'query-builder-filter-tree__exists-node__exists--label__action',
501
+ {
502
+ 'query-builder-filter-tree__exists-node__exists--label__action--error':
503
+ !isValid,
504
+ },
505
+ )}
506
+ tabIndex={-1}
507
+ onClick={setDerivedPropertyArguments}
508
+ title="Set Derived Property Argument(s)..."
509
+ >
510
+ {!isValid && <InfoCircleIcon />} (...)
511
+ </button>
512
+ )}
513
+ <QueryBuilderPropertyExpressionEditor
514
+ propertyExpressionState={node.propertyExpressionState}
515
+ />
480
516
  </div>
481
517
  </PanelEntryDropZonePlaceholder>
482
518
  </div>
@@ -38,6 +38,7 @@ import {
38
38
  PrimitiveType,
39
39
  } from '@finos/legend-graph';
40
40
  import {
41
+ assertErrorThrown,
41
42
  guaranteeNonNullable,
42
43
  parseNumber,
43
44
  returnUndefOnError,
@@ -58,6 +59,13 @@ import {
58
59
  QUERY_BUILDER_PURE_PATH,
59
60
  QUERY_BUILDER_SUPPORTED_FUNCTIONS,
60
61
  } from '../../graph/QueryBuilderMetaModelConst.js';
62
+ import {
63
+ useApplicationStore,
64
+ type ApplicationStore,
65
+ type LegendApplicationConfig,
66
+ type LegendApplicationPlugin,
67
+ type LegendApplicationPluginManager,
68
+ } from '@finos/legend-application';
61
69
 
62
70
  export enum CUSTOM_DATE_PICKER_OPTION {
63
71
  ABSOLUTE_DATE = 'Absolute Date',
@@ -110,6 +118,7 @@ enum CUSTOM_DATE_OPTION_REFERENCE_MOMENT {
110
118
  FIRST_DAY_OF_QUARTER = 'Start of Quarter',
111
119
  FIRST_DAY_OF_MONTH = 'Start of Month',
112
120
  FIRST_DAY_OF_WEEK = 'Start of Week',
121
+ PERVIOUS_DAY_OF_WEEK = 'Previous Day of Week',
113
122
  }
114
123
 
115
124
  /**
@@ -599,6 +608,8 @@ const buildCustomDateOptionReferenceMomentValue = (
599
608
  return CUSTOM_DATE_OPTION_REFERENCE_MOMENT.FIRST_DAY_OF_MONTH;
600
609
  case QUERY_BUILDER_SUPPORTED_FUNCTIONS.FIRST_DAY_OF_WEEK:
601
610
  return CUSTOM_DATE_OPTION_REFERENCE_MOMENT.FIRST_DAY_OF_WEEK;
611
+ case QUERY_BUILDER_SUPPORTED_FUNCTIONS.PREVIOUS_DAY_OF_WEEK:
612
+ return CUSTOM_DATE_OPTION_REFERENCE_MOMENT.PERVIOUS_DAY_OF_WEEK;
602
613
  default:
603
614
  throw new UnsupportedOperationError(
604
615
  `Can't build custom date option reference moment '${funcName}'`,
@@ -612,6 +623,10 @@ const buildCustomDateOptionReferenceMomentValue = (
612
623
  */
613
624
  const buildCustomDateOption = (
614
625
  valueSpecification: SimpleFunctionExpression | PrimitiveInstanceValue,
626
+ applicationStore: ApplicationStore<
627
+ LegendApplicationConfig,
628
+ LegendApplicationPluginManager<LegendApplicationPlugin>
629
+ >,
615
630
  ): CustomDateOption => {
616
631
  if (
617
632
  valueSpecification instanceof SimpleFunctionExpression &&
@@ -620,29 +635,36 @@ const buildCustomDateOption = (
620
635
  QUERY_BUILDER_SUPPORTED_FUNCTIONS.ADJUST,
621
636
  )
622
637
  ) {
623
- const customDateOption = new CustomDateOption(
624
- '',
625
- CUSTOM_DATE_PICKER_OPTION.CUSTOM_DATE,
626
- buildCustomDateOptionDurationValue(valueSpecification),
627
- buildCustomDateOptionUnitValue(valueSpecification),
628
- buildCustomDateOptionDirectionValue(valueSpecification),
629
- buildCustomDateOptionReferenceMomentValue(valueSpecification),
630
- );
631
- const matchedPreservedCustomAdjustDates = reservedCustomDateOptions.filter(
632
- (t) =>
633
- t.generateDisplayLabel() === customDateOption.generateDisplayLabel(),
634
- );
635
- if (matchedPreservedCustomAdjustDates.length > 0) {
636
- customDateOption.label = guaranteeNonNullable(
637
- matchedPreservedCustomAdjustDates[0]?.label,
638
- );
639
- customDateOption.value = guaranteeNonNullable(
640
- matchedPreservedCustomAdjustDates[0]?.value,
638
+ try {
639
+ const customDateOption = new CustomDateOption(
640
+ '',
641
+ CUSTOM_DATE_PICKER_OPTION.CUSTOM_DATE,
642
+ buildCustomDateOptionDurationValue(valueSpecification),
643
+ buildCustomDateOptionUnitValue(valueSpecification),
644
+ buildCustomDateOptionDirectionValue(valueSpecification),
645
+ buildCustomDateOptionReferenceMomentValue(valueSpecification),
641
646
  );
647
+ const matchedPreservedCustomAdjustDates =
648
+ reservedCustomDateOptions.filter(
649
+ (t) =>
650
+ t.generateDisplayLabel() ===
651
+ customDateOption.generateDisplayLabel(),
652
+ );
653
+ if (matchedPreservedCustomAdjustDates.length > 0) {
654
+ customDateOption.label = guaranteeNonNullable(
655
+ matchedPreservedCustomAdjustDates[0]?.label,
656
+ );
657
+ customDateOption.value = guaranteeNonNullable(
658
+ matchedPreservedCustomAdjustDates[0]?.value,
659
+ );
660
+ return customDateOption;
661
+ }
662
+ customDateOption.updateLabel();
642
663
  return customDateOption;
664
+ } catch (error) {
665
+ assertErrorThrown(error);
666
+ applicationStore.notificationService.notifyError(error);
643
667
  }
644
- customDateOption.updateLabel();
645
- return customDateOption;
646
668
  }
647
669
  return new CustomDateOption('', '', 0, undefined, undefined, undefined);
648
670
  };
@@ -652,6 +674,10 @@ const buildCustomDateOption = (
652
674
  */
653
675
  export const buildDatePickerOption = (
654
676
  valueSpecification: SimpleFunctionExpression | PrimitiveInstanceValue,
677
+ applicationStore: ApplicationStore<
678
+ LegendApplicationConfig,
679
+ LegendApplicationPluginManager<LegendApplicationPlugin>
680
+ >,
655
681
  ): DatePickerOption => {
656
682
  if (valueSpecification instanceof SimpleFunctionExpression) {
657
683
  switch (getSupportedDateFunctionFullPath(valueSpecification.functionName)) {
@@ -694,7 +720,7 @@ export const buildDatePickerOption = (
694
720
  .values[0]?.value.name as CUSTOM_DATE_DAY_OF_WEEK,
695
721
  );
696
722
  case QUERY_BUILDER_SUPPORTED_FUNCTIONS.ADJUST:
697
- return buildCustomDateOption(valueSpecification);
723
+ return buildCustomDateOption(valueSpecification, applicationStore);
698
724
  default:
699
725
  return new DatePickerOption('', '');
700
726
  }
@@ -1210,6 +1236,7 @@ export const CustomDatePicker: React.FC<{
1210
1236
  observerContext,
1211
1237
  typeCheckOption,
1212
1238
  } = props;
1239
+ const applicationStore = useApplicationStore();
1213
1240
  // For some cases where types need to be matched strictly.
1214
1241
  // Some options need to be filtered out for DateTime.
1215
1242
  const targetDateOptionsEnum = typeCheckOption.match
@@ -1219,7 +1246,7 @@ export const CustomDatePicker: React.FC<{
1219
1246
  ])
1220
1247
  : Object.values(CUSTOM_DATE_PICKER_OPTION);
1221
1248
  const [datePickerOption, setDatePickerOption] = useState(
1222
- buildDatePickerOption(valueSpecification),
1249
+ buildDatePickerOption(valueSpecification, applicationStore),
1223
1250
  );
1224
1251
 
1225
1252
  const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
@@ -1229,10 +1256,14 @@ export const CustomDatePicker: React.FC<{
1229
1256
  setAnchorEl(event.currentTarget);
1230
1257
  };
1231
1258
  const handleEnter = (): void => {
1232
- setDatePickerOption(buildDatePickerOption(valueSpecification));
1259
+ setDatePickerOption(
1260
+ buildDatePickerOption(valueSpecification, applicationStore),
1261
+ );
1233
1262
  };
1234
1263
  const closeCustomDatePickerPopover = (): void => {
1235
- setDatePickerOption(buildDatePickerOption(valueSpecification));
1264
+ setDatePickerOption(
1265
+ buildDatePickerOption(valueSpecification, applicationStore),
1266
+ );
1236
1267
  setAnchorEl(null);
1237
1268
  };
1238
1269
  const handleDatePickerOptionChange = (
@@ -1311,7 +1342,10 @@ export const CustomDatePicker: React.FC<{
1311
1342
  <CustomDateInstanceValueEditor
1312
1343
  graph={graph}
1313
1344
  observerContext={observerContext}
1314
- customDateOptionValue={buildCustomDateOption(valueSpecification)}
1345
+ customDateOptionValue={buildCustomDateOption(
1346
+ valueSpecification,
1347
+ applicationStore,
1348
+ )}
1315
1349
  setValueSpecification={setValueSpecification}
1316
1350
  setDatePickerOption={setDatePickerOption}
1317
1351
  />
@@ -1323,6 +1357,7 @@ export const CustomDatePicker: React.FC<{
1323
1357
  observerContext={observerContext}
1324
1358
  customDateAdjustOptionValue={buildDatePickerOption(
1325
1359
  valueSpecification,
1360
+ applicationStore,
1326
1361
  )}
1327
1362
  setValueSpecification={setValueSpecification}
1328
1363
  setDatePickerOption={setDatePickerOption}
@@ -1335,6 +1370,7 @@ export const CustomDatePicker: React.FC<{
1335
1370
  observerContext={observerContext}
1336
1371
  customDateAdjustOptionValue={buildDatePickerOption(
1337
1372
  valueSpecification,
1373
+ applicationStore,
1338
1374
  )}
1339
1375
  setValueSpecification={setValueSpecification}
1340
1376
  setDatePickerOption={setDatePickerOption}
@@ -1347,8 +1383,10 @@ export const CustomDatePicker: React.FC<{
1347
1383
 
1348
1384
  // make sure the date picker label is updated when the value is reset or changed somehow
1349
1385
  useEffect(() => {
1350
- setDatePickerOption(buildDatePickerOption(valueSpecification));
1351
- }, [valueSpecification]);
1386
+ setDatePickerOption(
1387
+ buildDatePickerOption(valueSpecification, applicationStore),
1388
+ );
1389
+ }, [applicationStore, valueSpecification]);
1352
1390
 
1353
1391
  return (
1354
1392
  <>
@@ -55,7 +55,10 @@ export const VariableViewer = observer(
55
55
 
56
56
  const getNameOfValue = (value: ValueSpecification): string | undefined => {
57
57
  if (value instanceof SimpleFunctionExpression) {
58
- const possibleDateLabel = buildDatePickerOption(value).label;
58
+ const possibleDateLabel = buildDatePickerOption(
59
+ value,
60
+ queryBuilderState.applicationStore,
61
+ ).label;
59
62
  if (possibleDateLabel) {
60
63
  return possibleDateLabel;
61
64
  }
@@ -20,6 +20,8 @@ import {
20
20
  type GraphManagerState,
21
21
  ExecutionPlan,
22
22
  ExecutionNode,
23
+ StoreMappingGlobalGraphFetchExecutionNode,
24
+ RelationalGraphFetchExecutionNode,
23
25
  } from '@finos/legend-graph';
24
26
  import type { TreeNodeData, TreeData } from '@finos/legend-art';
25
27
  import type { GenericLegendApplicationStore } from '@finos/legend-application';
@@ -28,6 +30,7 @@ import {
28
30
  filterByType,
29
31
  guaranteeNonNullable,
30
32
  } from '@finos/legend-shared';
33
+ import { generateExecutionNodeLabel } from '../../components/execution-plan/ExecutionPlanViewer.js';
31
34
 
32
35
  export class ExecutionPlanViewTreeNodeData implements TreeNodeData {
33
36
  id: string;
@@ -63,8 +66,14 @@ export class ExecutionNodeTreeNodeData implements TreeNodeData {
63
66
  isOpen?: boolean;
64
67
  childrenIds?: string[];
65
68
  executionNode: ExecutionNode;
69
+ parentNodeId: string | undefined;
66
70
 
67
- constructor(id: string, label: string, executionNode: ExecutionNode) {
71
+ constructor(
72
+ id: string,
73
+ label: string,
74
+ executionNode: ExecutionNode,
75
+ parentNodeId: string | undefined,
76
+ ) {
68
77
  makeObservable(this, {
69
78
  isSelected: observable,
70
79
  isOpen: observable,
@@ -74,6 +83,7 @@ export class ExecutionNodeTreeNodeData implements TreeNodeData {
74
83
  this.id = id;
75
84
  this.label = label;
76
85
  this.executionNode = executionNode;
86
+ this.parentNodeId = parentNodeId;
77
87
  }
78
88
 
79
89
  setIsSelected(val: boolean): void {
@@ -96,6 +106,9 @@ export const generateExecutionNodeTreeNodeData = (
96
106
  executionNode._UUID,
97
107
  label,
98
108
  executionNode,
109
+ parentNode instanceof ExecutionNodeTreeNodeData
110
+ ? generateExecutionNodeLabel(parentNode.executionNode)
111
+ : undefined,
99
112
  );
100
113
 
101
114
  const childrenIds: string[] = [];
@@ -107,6 +120,27 @@ export const generateExecutionNodeTreeNodeData = (
107
120
  addUniqueEntry(childrenIds, childExecutionNode._UUID);
108
121
  });
109
122
 
123
+ if (executionNode instanceof StoreMappingGlobalGraphFetchExecutionNode) {
124
+ addUniqueEntry(
125
+ childrenIds,
126
+ executionNode.localGraphFetchExecutionNode._UUID,
127
+ );
128
+ executionNode.children
129
+ .slice()
130
+ .filter(filterByType(ExecutionNode))
131
+ .forEach((childExecutionNode) => {
132
+ addUniqueEntry(childrenIds, childExecutionNode._UUID);
133
+ });
134
+ }
135
+
136
+ if (executionNode instanceof RelationalGraphFetchExecutionNode) {
137
+ executionNode.children
138
+ .slice()
139
+ .filter(filterByType(ExecutionNode))
140
+ .forEach((childExecutionNode) => {
141
+ addUniqueEntry(childrenIds, childExecutionNode._UUID);
142
+ });
143
+ }
110
144
  executionNodeTreeNode.childrenIds = childrenIds;
111
145
 
112
146
  return executionNodeTreeNode;
@@ -149,6 +183,32 @@ export enum EXECUTION_PLAN_VIEW_MODE {
149
183
  JSON = 'JSON',
150
184
  }
151
185
 
186
+ export enum PLAN_TABS {
187
+ GENERAL = 'GENERAL',
188
+ GLOBAL_IMPLEMENTATION_SUPPORT = 'GLOBAL_IMPLEMENTATION_SUPPORT',
189
+ }
190
+
191
+ class GlobalImplementationSupportState {
192
+ selectedTab: PLAN_TABS = PLAN_TABS.GENERAL;
193
+ selectedJavaClass: string | undefined = undefined;
194
+ constructor() {
195
+ makeObservable(this, {
196
+ selectedTab: observable,
197
+ selectedJavaClass: observable,
198
+ setSelectedTab: action,
199
+ setSelectedJavaClass: action,
200
+ });
201
+ }
202
+
203
+ setSelectedTab(tab: PLAN_TABS): void {
204
+ this.selectedTab = tab;
205
+ }
206
+
207
+ setSelectedJavaClass(javaClass: string | undefined): void {
208
+ this.selectedJavaClass = javaClass;
209
+ }
210
+ }
211
+
152
212
  export class ExecutionPlanState {
153
213
  applicationStore: GenericLegendApplicationStore;
154
214
  graphManagerState: GraphManagerState;
@@ -165,6 +225,8 @@ export class ExecutionPlanState {
165
225
  rawPlan?: RawExecutionPlan | undefined;
166
226
  plan?: ExecutionPlan | undefined;
167
227
  debugText?: string | undefined;
228
+ globalImplementationSupportState: GlobalImplementationSupportState =
229
+ new GlobalImplementationSupportState();
168
230
 
169
231
  constructor(
170
232
  applicationStore: GenericLegendApplicationStore,
@@ -191,6 +253,7 @@ export class ExecutionPlanState {
191
253
  refreshTreeData: action,
192
254
  nonNullableTreeData: computed,
193
255
  initialize: action,
256
+ globalImplementationSupportState: observable,
194
257
  });
195
258
  this.applicationStore = applicationStore;
196
259
  this.graphManagerState = graphManagerState;
@@ -25,6 +25,7 @@ import {
25
25
  RootGraphFetchTree,
26
26
  getAllSuperclasses,
27
27
  type Binding,
28
+ PropertyGraphFetchTree,
28
29
  } from '@finos/legend-graph';
29
30
  import {
30
31
  type QueryBuilderGraphFetchTreeData,
@@ -323,12 +324,18 @@ export class QueryBuilderGraphFetchTreeState
323
324
  ? // since we traverse the nodes in order, parent node ID should already been computed
324
325
  guaranteeNonNullable(explorerTreeNodeIDIndex.get(node.parentId))
325
326
  : '';
327
+ let generateID = '';
328
+ if (node.tree instanceof RootGraphFetchTree) {
329
+ generateID = `root.${node.tree.class.valueForSerialization ?? ''}`;
330
+ } else if (node.tree instanceof PropertyGraphFetchTree) {
331
+ generateID = node.tree.property.value.name;
332
+ }
326
333
  const propertyNodeID = generateExplorerTreePropertyNodeID(
327
334
  parentNodeID,
328
- node.tree.property.value.name,
335
+ generateID,
329
336
  );
330
337
  ids.push(propertyNodeID);
331
- if (node.tree.subType) {
338
+ if (node.tree instanceof PropertyGraphFetchTree && node.tree.subType) {
332
339
  nodeID = generateExplorerTreeSubtypeNodeID(
333
340
  propertyNodeID,
334
341
  node.tree.subType.value.path,
@@ -502,11 +509,14 @@ export class QueryBuilderGraphFetchTreeState
502
509
 
503
510
  isVariableUsed(variable: VariableExpression): boolean {
504
511
  return Boolean(
505
- Array.from(this.treeData?.nodes.values() ?? []).find((node) =>
506
- node.tree.parameters.find((p) =>
507
- isValueExpressionReferencedInValue(variable, p),
508
- ),
509
- ),
512
+ Array.from(this.treeData?.nodes.values() ?? []).find((node) => {
513
+ if (node.tree instanceof PropertyGraphFetchTree) {
514
+ return node.tree.parameters.find((p) =>
515
+ isValueExpressionReferencedInValue(variable, p),
516
+ );
517
+ }
518
+ return undefined;
519
+ }),
510
520
  );
511
521
  }
512
522