@finos/legend-application 4.0.3 → 5.1.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 (145) hide show
  1. package/lib/application/LegendApplication.d.ts +9 -1
  2. package/lib/application/LegendApplication.d.ts.map +1 -1
  3. package/lib/application/LegendApplication.js +54 -1
  4. package/lib/application/LegendApplication.js.map +1 -1
  5. package/lib/components/VirtualAssistant.d.ts.map +1 -1
  6. package/lib/components/VirtualAssistant.js +91 -11
  7. package/lib/components/VirtualAssistant.js.map +1 -1
  8. package/lib/components/{BasicValueSpecificationEditor.d.ts → shared/BasicValueSpecificationEditor.d.ts} +2 -2
  9. package/lib/components/shared/BasicValueSpecificationEditor.d.ts.map +1 -0
  10. package/lib/components/{BasicValueSpecificationEditor.js → shared/BasicValueSpecificationEditor.js} +29 -20
  11. package/lib/components/shared/BasicValueSpecificationEditor.js.map +1 -0
  12. package/lib/components/{CustomDatePicker.d.ts → shared/CustomDatePicker.d.ts} +1 -1
  13. package/lib/components/shared/CustomDatePicker.d.ts.map +1 -0
  14. package/lib/components/{CustomDatePicker.js → shared/CustomDatePicker.js} +20 -20
  15. package/lib/components/shared/CustomDatePicker.js.map +1 -0
  16. package/lib/components/{DocumentationLink.d.ts → shared/DocumentationLink.d.ts} +0 -0
  17. package/lib/components/shared/DocumentationLink.d.ts.map +1 -0
  18. package/lib/components/{DocumentationLink.js → shared/DocumentationLink.js} +1 -1
  19. package/lib/components/shared/DocumentationLink.js.map +1 -0
  20. package/lib/components/{LambdaEditor.d.ts → shared/LambdaEditor.d.ts} +1 -1
  21. package/lib/components/shared/LambdaEditor.d.ts.map +1 -0
  22. package/lib/components/{LambdaEditor.js → shared/LambdaEditor.js} +3 -3
  23. package/lib/components/shared/LambdaEditor.js.map +1 -0
  24. package/lib/components/{LambdaParameterValuesEditor.d.ts → shared/LambdaParameterValuesEditor.d.ts} +1 -1
  25. package/lib/components/shared/LambdaParameterValuesEditor.d.ts.map +1 -0
  26. package/lib/components/{LambdaParameterValuesEditor.js → shared/LambdaParameterValuesEditor.js} +2 -2
  27. package/lib/components/shared/LambdaParameterValuesEditor.js.map +1 -0
  28. package/lib/components/shared/PackageableElementOptionRenderer.d.ts +21 -0
  29. package/lib/components/shared/PackageableElementOptionRenderer.d.ts.map +1 -0
  30. package/lib/components/shared/PackageableElementOptionRenderer.js +8 -0
  31. package/lib/components/shared/PackageableElementOptionRenderer.js.map +1 -0
  32. package/lib/components/{TextInputEditor.d.ts → shared/TextInputEditor.d.ts} +1 -1
  33. package/lib/components/shared/TextInputEditor.d.ts.map +1 -0
  34. package/lib/components/{TextInputEditor.js → shared/TextInputEditor.js} +2 -2
  35. package/lib/components/shared/TextInputEditor.js.map +1 -0
  36. package/lib/components/shared/execution-plan-viewer/ExecutionPlanViewer.d.ts +28 -0
  37. package/lib/components/shared/execution-plan-viewer/ExecutionPlanViewer.d.ts.map +1 -0
  38. package/lib/components/shared/execution-plan-viewer/ExecutionPlanViewer.js +182 -0
  39. package/lib/components/shared/execution-plan-viewer/ExecutionPlanViewer.js.map +1 -0
  40. package/lib/components/shared/execution-plan-viewer/SQLExecutionNodeViewer.d.ts +31 -0
  41. package/lib/components/shared/execution-plan-viewer/SQLExecutionNodeViewer.d.ts.map +1 -0
  42. package/lib/components/shared/execution-plan-viewer/SQLExecutionNodeViewer.js +32 -0
  43. package/lib/components/shared/execution-plan-viewer/SQLExecutionNodeViewer.js.map +1 -0
  44. package/lib/const.d.ts +0 -3
  45. package/lib/const.d.ts.map +1 -1
  46. package/lib/const.js +0 -3
  47. package/lib/const.js.map +1 -1
  48. package/lib/index.css +2 -2
  49. package/lib/index.css.map +1 -1
  50. package/lib/index.d.ts +12 -9
  51. package/lib/index.d.ts.map +1 -1
  52. package/lib/index.js +13 -9
  53. package/lib/index.js.map +1 -1
  54. package/lib/stores/ApplicationEvent.d.ts +4 -2
  55. package/lib/stores/ApplicationEvent.d.ts.map +1 -1
  56. package/lib/stores/ApplicationEvent.js +4 -2
  57. package/lib/stores/ApplicationEvent.js.map +1 -1
  58. package/lib/stores/ApplicationStore.d.ts.map +1 -1
  59. package/lib/stores/ApplicationStore.js +2 -1
  60. package/lib/stores/ApplicationStore.js.map +1 -1
  61. package/lib/stores/LegendApplicationAssistantService.d.ts +7 -2
  62. package/lib/stores/LegendApplicationAssistantService.d.ts.map +1 -1
  63. package/lib/stores/LegendApplicationAssistantService.js +22 -10
  64. package/lib/stores/LegendApplicationAssistantService.js.map +1 -1
  65. package/lib/stores/LegendApplicationConfig.d.ts +8 -5
  66. package/lib/stores/LegendApplicationConfig.d.ts.map +1 -1
  67. package/lib/stores/LegendApplicationConfig.js +15 -13
  68. package/lib/stores/LegendApplicationConfig.js.map +1 -1
  69. package/lib/stores/LegendApplicationDocumentationService.d.ts +34 -24
  70. package/lib/stores/LegendApplicationDocumentationService.d.ts.map +1 -1
  71. package/lib/stores/LegendApplicationDocumentationService.js +64 -60
  72. package/lib/stores/LegendApplicationDocumentationService.js.map +1 -1
  73. package/lib/stores/LegendApplicationPlugin.d.ts +14 -3
  74. package/lib/stores/LegendApplicationPlugin.d.ts.map +1 -1
  75. package/lib/stores/LegendApplicationPlugin.js.map +1 -1
  76. package/lib/stores/PureLanguageSupport.d.ts.map +1 -1
  77. package/lib/stores/PureLanguageSupport.js +8 -3
  78. package/lib/stores/PureLanguageSupport.js.map +1 -1
  79. package/lib/stores/shared/ExecutionPlanState.d.ts +62 -0
  80. package/lib/stores/shared/ExecutionPlanState.d.ts.map +1 -0
  81. package/lib/stores/shared/ExecutionPlanState.js +118 -0
  82. package/lib/stores/shared/ExecutionPlanState.js.map +1 -0
  83. package/lib/stores/{LambdaEditorState.d.ts → shared/LambdaEditorState.d.ts} +0 -0
  84. package/lib/stores/shared/LambdaEditorState.d.ts.map +1 -0
  85. package/lib/stores/{LambdaEditorState.js → shared/LambdaEditorState.js} +0 -0
  86. package/lib/stores/shared/LambdaEditorState.js.map +1 -0
  87. package/lib/stores/{LambdaParameterState.d.ts → shared/LambdaParameterState.d.ts} +1 -3
  88. package/lib/stores/shared/LambdaParameterState.d.ts.map +1 -0
  89. package/lib/stores/{LambdaParameterState.js → shared/LambdaParameterState.js} +3 -52
  90. package/lib/stores/shared/LambdaParameterState.js.map +1 -0
  91. package/lib/stores/{PackageableElementOption.d.ts → shared/PackageableElementOption.d.ts} +0 -0
  92. package/lib/stores/shared/PackageableElementOption.d.ts.map +1 -0
  93. package/lib/stores/{PackageableElementOption.js → shared/PackageableElementOption.js} +0 -0
  94. package/lib/stores/shared/PackageableElementOption.js.map +1 -0
  95. package/lib/stores/{ValueSpecificationModifierHelper.d.ts → shared/ValueSpecificationModifierHelper.d.ts} +0 -0
  96. package/lib/stores/shared/ValueSpecificationModifierHelper.d.ts.map +1 -0
  97. package/lib/stores/{ValueSpecificationModifierHelper.js → shared/ValueSpecificationModifierHelper.js} +0 -0
  98. package/lib/stores/shared/ValueSpecificationModifierHelper.js.map +1 -0
  99. package/package.json +13 -12
  100. package/src/application/LegendApplication.tsx +100 -4
  101. package/src/components/VirtualAssistant.tsx +106 -16
  102. package/src/components/{BasicValueSpecificationEditor.tsx → shared/BasicValueSpecificationEditor.tsx} +50 -19
  103. package/src/components/{CustomDatePicker.tsx → shared/CustomDatePicker.tsx} +44 -27
  104. package/src/components/{DocumentationLink.tsx → shared/DocumentationLink.tsx} +1 -1
  105. package/src/components/{LambdaEditor.tsx → shared/LambdaEditor.tsx} +4 -4
  106. package/src/components/{LambdaParameterValuesEditor.tsx → shared/LambdaParameterValuesEditor.tsx} +5 -3
  107. package/src/components/shared/PackageableElementOptionRenderer.tsx +40 -0
  108. package/src/components/{TextInputEditor.tsx → shared/TextInputEditor.tsx} +2 -2
  109. package/src/components/shared/execution-plan-viewer/ExecutionPlanViewer.tsx +550 -0
  110. package/src/components/shared/execution-plan-viewer/SQLExecutionNodeViewer.tsx +46 -0
  111. package/src/const.ts +0 -5
  112. package/src/index.ts +16 -13
  113. package/src/stores/ApplicationEvent.ts +4 -2
  114. package/src/stores/ApplicationStore.ts +3 -1
  115. package/src/stores/LegendApplicationAssistantService.ts +30 -16
  116. package/src/stores/LegendApplicationConfig.ts +28 -27
  117. package/src/stores/LegendApplicationDocumentationService.ts +128 -124
  118. package/src/stores/LegendApplicationPlugin.ts +17 -3
  119. package/src/stores/PureLanguageSupport.ts +8 -3
  120. package/src/stores/shared/ExecutionPlanState.ts +154 -0
  121. package/src/stores/{LambdaEditorState.ts → shared/LambdaEditorState.ts} +0 -0
  122. package/src/stores/{LambdaParameterState.ts → shared/LambdaParameterState.ts} +2 -100
  123. package/src/stores/{PackageableElementOption.ts → shared/PackageableElementOption.ts} +0 -0
  124. package/src/stores/{ValueSpecificationModifierHelper.ts → shared/ValueSpecificationModifierHelper.ts} +0 -0
  125. package/tsconfig.json +14 -10
  126. package/lib/components/BasicValueSpecificationEditor.d.ts.map +0 -1
  127. package/lib/components/BasicValueSpecificationEditor.js.map +0 -1
  128. package/lib/components/CustomDatePicker.d.ts.map +0 -1
  129. package/lib/components/CustomDatePicker.js.map +0 -1
  130. package/lib/components/DocumentationLink.d.ts.map +0 -1
  131. package/lib/components/DocumentationLink.js.map +0 -1
  132. package/lib/components/LambdaEditor.d.ts.map +0 -1
  133. package/lib/components/LambdaEditor.js.map +0 -1
  134. package/lib/components/LambdaParameterValuesEditor.d.ts.map +0 -1
  135. package/lib/components/LambdaParameterValuesEditor.js.map +0 -1
  136. package/lib/components/TextInputEditor.d.ts.map +0 -1
  137. package/lib/components/TextInputEditor.js.map +0 -1
  138. package/lib/stores/LambdaEditorState.d.ts.map +0 -1
  139. package/lib/stores/LambdaEditorState.js.map +0 -1
  140. package/lib/stores/LambdaParameterState.d.ts.map +0 -1
  141. package/lib/stores/LambdaParameterState.js.map +0 -1
  142. package/lib/stores/PackageableElementOption.d.ts.map +0 -1
  143. package/lib/stores/PackageableElementOption.js.map +0 -1
  144. package/lib/stores/ValueSpecificationModifierHelper.d.ts.map +0 -1
  145. package/lib/stores/ValueSpecificationModifierHelper.js.map +0 -1
@@ -13,41 +13,15 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { CollectionInstanceValue, Enumeration, EnumValueExplicitReference, EnumValueInstanceValue, GenericType, GenericTypeExplicitReference, getEnumValue, observe_ValueSpecification, observe_VariableExpression, PrimitiveInstanceValue, PrimitiveType, PRIMITIVE_TYPE, VariableExpression, LambdaFunction, TYPICAL_MULTIPLICITY_TYPE, CORE_PURE_PATH, FunctionType, SimpleFunctionExpression, SUPPORTED_FUNCTIONS, extractElementNameFromPath, } from '@finos/legend-graph';
17
- import { addUniqueEntry, deleteEntry, IllegalStateError, isNonNullable, Randomizer, uuid, } from '@finos/legend-shared';
16
+ import { GenericType, GenericTypeExplicitReference, observe_ValueSpecification, observe_VariableExpression, PrimitiveInstanceValue, PRIMITIVE_TYPE, VariableExpression, LambdaFunction, TYPICAL_MULTIPLICITY_TYPE, CORE_PURE_PATH, FunctionType, SimpleFunctionExpression, SUPPORTED_FUNCTIONS, extractElementNameFromPath, generateVariableExpressionMockValue, } from '@finos/legend-graph';
17
+ import { addUniqueEntry, deleteEntry, IllegalStateError, isNonNullable, uuid, } from '@finos/legend-shared';
18
18
  import { makeObservable, observable, action } from 'mobx';
19
19
  import { genericType_setRawType, multiplicity_setLowerBound, multiplicity_setUpperBound, } from './ValueSpecificationModifierHelper.js';
20
- import { format, addDays } from 'date-fns';
21
- import { DATE_FORMAT, DATE_TIME_FORMAT } from '../const.js';
22
20
  export var PARAMETER_SUBMIT_ACTION;
23
21
  (function (PARAMETER_SUBMIT_ACTION) {
24
22
  PARAMETER_SUBMIT_ACTION["EXECUTE"] = "EXECUTE";
25
23
  PARAMETER_SUBMIT_ACTION["EXPORT"] = "EXPORT";
26
24
  })(PARAMETER_SUBMIT_ACTION = PARAMETER_SUBMIT_ACTION || (PARAMETER_SUBMIT_ACTION = {}));
27
- export const createMockEnumerationProperty = (enumeration) => new Randomizer().getRandomItemInCollection(enumeration.values)?.name ?? '';
28
- const createMockPrimitiveProperty = (primitiveType, propertyName) => {
29
- const randomizer = new Randomizer();
30
- switch (primitiveType.name) {
31
- case PRIMITIVE_TYPE.BOOLEAN:
32
- return randomizer.getRandomItemInCollection([true, false]) ?? true;
33
- case PRIMITIVE_TYPE.FLOAT:
34
- return randomizer.getRandomFloat();
35
- case PRIMITIVE_TYPE.DECIMAL:
36
- return randomizer.getRandomDouble();
37
- case PRIMITIVE_TYPE.NUMBER:
38
- case PRIMITIVE_TYPE.INTEGER:
39
- return randomizer.getRandomWholeNumber(100);
40
- // NOTE that `Date` is the umbrella type that comprises `StrictDate` and `DateTime`, but for simplicity, we will generate `Date` as `StrictDate`
41
- case PRIMITIVE_TYPE.DATE:
42
- case PRIMITIVE_TYPE.STRICTDATE:
43
- return format(randomizer.getRandomDate(new Date(Date.now()), addDays(Date.now(), 100)), DATE_FORMAT);
44
- case PRIMITIVE_TYPE.DATETIME:
45
- return format(randomizer.getRandomDate(new Date(Date.now()), addDays(Date.now(), 100)), DATE_TIME_FORMAT);
46
- case PRIMITIVE_TYPE.STRING:
47
- default:
48
- return `${propertyName} ${randomizer.getRandomWholeNumber(100)}`;
49
- }
50
- };
51
25
  export const buildParametersLetLambdaFunc = (graph, lambdaParametersStates) => {
52
26
  const multiplicityOne = graph.getTypicalMultiplicity(TYPICAL_MULTIPLICITY_TYPE.ONE);
53
27
  const typeString = graph.getPrimitiveType(PRIMITIVE_TYPE.STRING);
@@ -83,30 +57,7 @@ export class LambdaParameterState {
83
57
  this.parameter = observe_VariableExpression(variableExpression);
84
58
  }
85
59
  mockParameterValue() {
86
- this.setValue(this.generateMockValues(this.parameter.genericType?.value.rawType, this.parameter.multiplicity));
87
- }
88
- generateMockValues(varType, multiplicity) {
89
- if ((!multiplicity.upperBound || multiplicity.upperBound > 1) && varType) {
90
- return new CollectionInstanceValue(multiplicity, GenericTypeExplicitReference.create(new GenericType(varType)));
91
- }
92
- if (varType instanceof PrimitiveType) {
93
- const primitiveInst = new PrimitiveInstanceValue(GenericTypeExplicitReference.create(new GenericType(varType)), multiplicity);
94
- primitiveInst.values = [
95
- createMockPrimitiveProperty(varType, this.parameter.name === '' ? 'myVar' : this.parameter.name),
96
- ];
97
- return primitiveInst;
98
- }
99
- else if (varType instanceof Enumeration) {
100
- const enumValueInstance = new EnumValueInstanceValue(GenericTypeExplicitReference.create(new GenericType(varType)), multiplicity);
101
- const mock = createMockEnumerationProperty(varType);
102
- if (mock !== '') {
103
- enumValueInstance.values = [
104
- EnumValueExplicitReference.create(getEnumValue(varType, mock)),
105
- ];
106
- }
107
- return enumValueInstance;
108
- }
109
- return undefined;
60
+ this.setValue(generateVariableExpressionMockValue(this.parameter));
110
61
  }
111
62
  setValue(value) {
112
63
  if (value instanceof VariableExpression) {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LambdaParameterState.js","sourceRoot":"","sources":["../../../src/stores/shared/LambdaParameterState.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PackageableElementOption.d.ts","sourceRoot":"","sources":["../../../src/stores/shared/PackageableElementOption.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,MAAM,WAAW,wBAAwB,CAAC,CAAC,SAAS,kBAAkB;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;CACV;AAED,eAAO,MAAM,kBAAkB,YACpB,kBAAkB,KAC1B,yBAAyB,kBAAkB,CAG5C,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PackageableElementOption.js","sourceRoot":"","sources":["../../../src/stores/shared/PackageableElementOption.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AASH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,OAA2B,EACmB,EAAE,CAAC,CAAC;IAClD,KAAK,EAAE,OAAO,CAAC,IAAI;IACnB,KAAK,EAAE,OAAO;CACf,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ValueSpecificationModifierHelper.d.ts","sourceRoot":"","sources":["../../../src/stores/shared/ValueSpecificationModifierHelper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,IAAI,EACT,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,0BAA0B,EAEhC,MAAM,qBAAqB,CAAC;AAI7B,eAAO,MAAM,sBAAsB,gBACnB,WAAW,QAAQ,IAAI,KAAG,IAGzC,CAAC;AAEF,eAAO,MAAM,0BAA0B,OAChC,YAAY,OAAO,MAAM,KAAG,IAGlC,CAAC;AACF,eAAO,MAAM,0BAA0B,OAChC,YAAY,OAAO,MAAM,GAAG,SAAS,KAAG,IAG9C,CAAC;AAEF,eAAO,MAAM,sCAAsC,uBAE3B,kBAAkB,OACjC,kBAAkB,EAAE,WAChB,eAAe,KACvB,IAKJ,CAAC;AAEF,eAAO,MAAM,0BAA0B,MACjC,kBAAkB,OAAO,MAAM,KAAG,IAGvC,CAAC;AAEF,eAAO,MAAM,yBAAyB,kBACpB,aAAa,OAAO,OAAO,OAAO,MAAM,SAGzD,CAAC;AAEF,eAAO,MAAM,0BAA0B,kBACrB,aAAa,OAAO,OAAO,EAAE,SAG9C,CAAC;AAEF,eAAO,MAAM,yBAAyB,SAC7B,cAAc,OAAO,cAAc,KAAG,IAG9C,CAAC;AAEF,eAAO,MAAM,4BAA4B,SAChC,cAAc,OAAO,cAAc,KAAG,IAG9C,CAAC;AAEF,eAAO,MAAM,qCAAqC,uBAE1B,0BAA0B,OACzC,MAAM,OACN,kBAAkB,WACd,eAAe,KACvB,IAMJ,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ValueSpecificationModifierHelper.js","sourceRoot":"","sources":["../../../src/stores/shared/ValueSpecificationModifierHelper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAWL,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAE9B,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAC1C,CAAC,WAAwB,EAAE,IAAU,EAAQ,EAAE;IAC7C,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;AAC7B,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAC9C,CAAC,EAAgB,EAAE,GAAW,EAAQ,EAAE;IACtC,EAAE,CAAC,UAAU,GAAG,GAAG,CAAC;AACtB,CAAC,CACF,CAAC;AACF,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAC9C,CAAC,EAAgB,EAAE,GAAuB,EAAQ,EAAE;IAClD,EAAE,CAAC,UAAU,GAAG,GAAG,CAAC;AACtB,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,sCAAsC,GAAG,MAAM,CAC1D,CACE,kBAAsC,EACtC,GAAyB,EACzB,OAAwB,EAClB,EAAE;IACR,kBAAkB,CAAC,gBAAgB,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAClD,0BAA0B,CAAC,CAAC,EAAE,OAAO,CAAC,CACvC,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAC9C,CAAC,CAAqB,EAAE,GAAW,EAAQ,EAAE;IAC3C,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC;AACf,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAC7C,CAAC,aAA4B,EAAE,GAAY,EAAE,GAAW,EAAE,EAAE;IAC1D,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AAClC,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAC9C,CAAC,aAA4B,EAAE,GAAc,EAAE,EAAE;IAC/C,aAAa,CAAC,MAAM,GAAG,GAAG,CAAC;AAC7B,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAC7C,CAAC,IAAoB,EAAE,GAAmB,EAAQ,EAAE;IAClD,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AACrC,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,4BAA4B,GAAG,MAAM,CAChD,CAAC,IAAoB,EAAE,GAAmB,EAAQ,EAAE;IAClD,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,qCAAqC,GAAG,MAAM,CACzD,CACE,kBAA8C,EAC9C,GAAW,EACX,GAAuB,EACvB,OAAwB,EAClB,EAAE;IACR,kBAAkB,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,0BAA0B,CACnE,GAAG,EACH,OAAO,CACR,CAAC;AACJ,CAAC,CACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finos/legend-application",
3
- "version": "4.0.3",
3
+ "version": "5.1.0",
4
4
  "description": "Legend application core",
5
5
  "keywords": [
6
6
  "legend",
@@ -43,18 +43,18 @@
43
43
  "test:watch": "jest --watch"
44
44
  },
45
45
  "dependencies": {
46
- "@finos/legend-art": "2.0.2",
47
- "@finos/legend-graph": "8.0.3",
48
- "@finos/legend-shared": "3.0.2",
46
+ "@finos/legend-art": "2.0.5",
47
+ "@finos/legend-graph": "10.0.0",
48
+ "@finos/legend-shared": "4.0.2",
49
49
  "@types/css-font-loading-module": "0.0.7",
50
50
  "@types/papaparse": "5.3.2",
51
51
  "@types/react": "18.0.14",
52
- "@types/react-dom": "18.0.5",
52
+ "@types/react-dom": "18.0.6",
53
53
  "@types/react-router-dom": "5.3.3",
54
54
  "date-fns": "2.28.0",
55
55
  "fuse.js": "6.6.2",
56
56
  "history": "5.3.0",
57
- "mobx": "6.6.0",
57
+ "mobx": "6.6.1",
58
58
  "mobx-react-lite": "3.4.0",
59
59
  "monaco-editor": "0.33.0",
60
60
  "papaparse": "5.3.2",
@@ -64,17 +64,18 @@
64
64
  "react-resize-detector": "7.1.2",
65
65
  "react-router": "5.3.3",
66
66
  "react-router-dom": "5.3.3",
67
- "serializr": "2.0.5"
67
+ "serializr": "2.0.5",
68
+ "sql-formatter": "8.0.2"
68
69
  },
69
70
  "devDependencies": {
70
- "@finos/legend-dev-utils": "2.0.1",
71
- "@jest/globals": "28.1.1",
71
+ "@finos/legend-dev-utils": "2.0.4",
72
+ "@jest/globals": "28.1.2",
72
73
  "cross-env": "7.0.3",
73
- "eslint": "8.18.0",
74
- "jest": "28.1.1",
74
+ "eslint": "8.19.0",
75
+ "jest": "28.1.2",
75
76
  "npm-run-all": "4.1.5",
76
77
  "rimraf": "3.0.2",
77
- "sass": "1.52.3",
78
+ "sass": "1.53.0",
78
79
  "typescript": "4.7.4"
79
80
  },
80
81
  "peerDependencies": {
@@ -30,12 +30,19 @@ import {
30
30
  guaranteeNonEmptyString,
31
31
  assertNonNullable,
32
32
  NetworkClient,
33
+ type Writable,
33
34
  } from '@finos/legend-shared';
34
35
  import { APPLICATION_EVENT } from '../stores/ApplicationEvent.js';
35
36
  import { configureComponents } from '@finos/legend-art';
36
37
  import type { GraphPluginManager } from '@finos/legend-graph';
37
38
  import type { LegendApplicationPluginManager } from './LegendApplicationPluginManager.js';
38
39
  import { setupPureLanguageService } from '../stores/PureLanguageSupport.js';
40
+ import {
41
+ collectKeyedDocumnetationEntriesFromConfig,
42
+ type LegendApplicationDocumentationConfigEntry,
43
+ type LegendApplicationDocumentationRegistryData,
44
+ type LegendApplicationDocumentationRegistryEntry,
45
+ } from '../stores/LegendApplicationDocumentationService.js';
39
46
 
40
47
  export abstract class LegendApplicationLogger {
41
48
  abstract debug(event: LogEvent, ...data: unknown[]): void;
@@ -126,6 +133,15 @@ export const setupLegendApplicationUILibrary = async (
126
133
  configureComponents();
127
134
  };
128
135
 
136
+ export interface LegendApplicationConfigurationInput<
137
+ T extends LegendApplicationConfigurationData,
138
+ > {
139
+ baseUrl: string;
140
+ configData: T;
141
+ versionData: LegendApplicationVersionData;
142
+ docEntries?: Record<string, LegendApplicationDocumentationConfigEntry>;
143
+ }
144
+
129
145
  export abstract class LegendApplication {
130
146
  protected config!: LegendApplicationConfig;
131
147
  protected logger!: LegendApplicationLogger;
@@ -193,6 +209,8 @@ export abstract class LegendApplication {
193
209
  baseUrl: string,
194
210
  ): Promise<[LegendApplicationConfig, Record<PropertyKey, object>]> {
195
211
  const client = new NetworkClient();
212
+
213
+ // app config
196
214
  let configData: LegendApplicationConfigurationData | undefined;
197
215
  try {
198
216
  configData = await client.get<LegendApplicationConfigurationData>(
@@ -209,6 +227,8 @@ export abstract class LegendApplication {
209
227
  configData,
210
228
  `Can't fetch Legend application configuration`,
211
229
  );
230
+
231
+ // app version
212
232
  let versionData;
213
233
  try {
214
234
  versionData = await client.get<LegendApplicationVersionData>(
@@ -222,16 +242,86 @@ export abstract class LegendApplication {
222
242
  );
223
243
  }
224
244
  assertNonNullable(versionData, `Can't fetch Legend application version`);
245
+
225
246
  return [
226
- await this.configureApplication(configData, versionData, baseUrl),
247
+ await this.configureApplication({
248
+ configData,
249
+ versionData,
250
+ baseUrl,
251
+ }),
227
252
  (configData.extensions ?? {}) as Record<PropertyKey, object>,
228
253
  ];
229
254
  }
230
255
 
256
+ async loadDocumentationRegistryData(
257
+ config: LegendApplicationConfig,
258
+ ): Promise<void> {
259
+ const entries: Record<string, LegendApplicationDocumentationConfigEntry> =
260
+ {};
261
+
262
+ await Promise.all(
263
+ [
264
+ ...config.documentationRegistryEntries,
265
+ ...this.pluginManager
266
+ .getApplicationPlugins()
267
+ .flatMap(
268
+ (plugin) => plugin.getExtraDocumentationRegistryEntries?.() ?? [],
269
+ ),
270
+ ].map(async (entry: LegendApplicationDocumentationRegistryEntry) => {
271
+ try {
272
+ const client = new NetworkClient(
273
+ entry.simple
274
+ ? {
275
+ /**
276
+ * NOTE: see the documentation for `simple` flag {@link LegendApplicationDocumentationRegistryEntry}
277
+ * here, basically, we expect to fetch just the JSON from an endpoint where `Access-Control-Allow-Origin", "*"` is set
278
+ * as such, we must not include the credential in our request
279
+ * See https://stackoverflow.com/questions/19743396/cors-cannot-use-wildcard-in-access-control-allow-origin-when-credentials-flag-i
280
+ */
281
+ options: {
282
+ credentials: 'omit',
283
+ },
284
+ }
285
+ : {},
286
+ );
287
+ const docData =
288
+ await client.get<LegendApplicationDocumentationRegistryData>(
289
+ guaranteeNonEmptyString(
290
+ entry.url,
291
+ `Can't load documentation registry: 'url' field is missing or empty`,
292
+ ),
293
+ );
294
+ assertNonNullable(
295
+ docData.entries,
296
+ `Can't load documentation registry data: 'entries' field is missing`,
297
+ );
298
+ Object.entries(docData.entries).forEach(([key, docEntry]) => {
299
+ // NOTE: entries will NOT override
300
+ if (!entries[key]) {
301
+ entries[key] = docEntry;
302
+ }
303
+ });
304
+ } catch (error) {
305
+ assertErrorThrown(error);
306
+ this.logger.warn(
307
+ LogEvent.create(
308
+ APPLICATION_EVENT.APPLICATION_DOCUMENTATION_FETCH_FAILURE,
309
+ ),
310
+ error,
311
+ );
312
+ }
313
+ }),
314
+ );
315
+
316
+ // NOTE: config entries will override
317
+ (config as Writable<LegendApplicationConfig>).keyedDocumentationEntries = [
318
+ ...collectKeyedDocumnetationEntriesFromConfig(entries),
319
+ ...config.keyedDocumentationEntries,
320
+ ];
321
+ }
322
+
231
323
  protected abstract configureApplication(
232
- configData: LegendApplicationConfigurationData,
233
- versionData: LegendApplicationVersionData,
234
- baseUrl: string,
324
+ input: LegendApplicationConfigurationInput<LegendApplicationConfigurationData>,
235
325
  ): Promise<LegendApplicationConfig>;
236
326
 
237
327
  protected abstract loadApplication(): Promise<void>;
@@ -252,6 +342,12 @@ export abstract class LegendApplication {
252
342
  this.pluginManager.configure(extensionConfigData);
253
343
  this.pluginManager.install();
254
344
 
345
+ // Other setups
346
+ await Promise.all(
347
+ // NOTE: to be done in parallel to save time
348
+ [this.loadDocumentationRegistryData(config)],
349
+ );
350
+
255
351
  await this.loadApplication();
256
352
 
257
353
  this.logger.info(
@@ -16,7 +16,6 @@
16
16
 
17
17
  import {
18
18
  clsx,
19
- BasePopper,
20
19
  TimesIcon,
21
20
  SearchIcon,
22
21
  MapMarkerIcon,
@@ -35,6 +34,8 @@ import {
35
34
  VerticalDragHandleThinIcon,
36
35
  CircleIcon,
37
36
  PanelLoadingIndicator,
37
+ BasePopover,
38
+ FaceSadTearIcon,
38
39
  } from '@finos/legend-art';
39
40
  import {
40
41
  ContentType,
@@ -46,13 +47,14 @@ import {
46
47
  import { format } from 'date-fns';
47
48
  import { observer } from 'mobx-react-lite';
48
49
  import { useEffect, useMemo, useRef, useState } from 'react';
49
- import { DATE_TIME_FORMAT, TAB_SIZE } from '../const.js';
50
+ import { TAB_SIZE } from '../const.js';
50
51
  import {
51
52
  type VirtualAssistantDocumentationEntry,
52
53
  VIRTUAL_ASSISTANT_TAB,
53
54
  } from '../stores/LegendApplicationAssistantService.js';
54
55
  import { useApplicationStore } from './ApplicationStoreProvider.js';
55
56
  import Draggable from 'react-draggable';
57
+ import { DATE_TIME_FORMAT } from '@finos/legend-graph';
56
58
 
57
59
  const WIZARD_GREETING = `Bonjour, It's Pierre!`;
58
60
 
@@ -217,12 +219,12 @@ const VirtualAssistantContextualSupportPanel = observer(() => {
217
219
  )}
218
220
  {!contextualEntry && (
219
221
  <BlankPanelContent>
220
- <div className="virtual-assistant__contextual-support__placeholder">
221
- <FaceLaughWinkIcon className="virtual-assistant__contextual-support__placeholder__icon" />
222
- <div className="virtual-assistant__contextual-support__placeholder__message">
222
+ <div className="virtual-assistant__panel__placeholder">
223
+ <FaceLaughWinkIcon className="virtual-assistant__panel__placeholder__icon" />
224
+ <div className="virtual-assistant__panel__placeholder__message">
223
225
  No contextual documentation found!
224
226
  </div>
225
- <div className="virtual-assistant__contextual-support__placeholder__instruction">
227
+ <div className="virtual-assistant__panel__placeholder__instruction">
226
228
  Keep using the app, when contextual doc available, we will let you
227
229
  know!
228
230
  </div>
@@ -271,14 +273,14 @@ const VirtualAssistantSearchPanel = observer(() => {
271
273
  ContentType.APPLICATION_JSON,
272
274
  );
273
275
  };
274
- const downloadContextualDocRegistry = (): void => {
276
+ const downloadContextualDocMap = (): void => {
275
277
  downloadFileUsingDataURI(
276
278
  `documentation-registry_${format(
277
279
  new Date(Date.now()),
278
280
  DATE_TIME_FORMAT,
279
281
  )}.json`,
280
282
  JSON.stringify(
281
- applicationStore.documentationService.publishContextualDocRegistry(),
283
+ applicationStore.documentationService.publishContextualDocMap(),
282
284
  undefined,
283
285
  TAB_SIZE,
284
286
  ),
@@ -295,6 +297,37 @@ const VirtualAssistantSearchPanel = observer(() => {
295
297
  <div className="virtual-assistant__search__header">
296
298
  <input
297
299
  ref={searchInputRef}
300
+ /**
301
+ * NOTE: In the scenario where another modal is opened at the same time the assistant panel
302
+ * is open, the focus will be stolen by the newly opened modal. In that case, we need
303
+ * to take back the focus. The trick here is to remount the whole panel (modal/popover)
304
+ * by refreshing the `key` prop of the panel. This will cause `mui` to recompute the
305
+ * focus-trap and allow the input field to be selectable again. Basically, we are stealing
306
+ * back the focus for the assistant.
307
+ *
308
+ * However, the caveat is that this will cause the component states, such as scroll positions,
309
+ * to be reset as such, we need to do this really sparingly. In fact, the only
310
+ * scenario where we need to do this is when a new modal is opened when the assistant panel
311
+ * is already opened. Basically, Other scenarios, such as when the assistant is opened after the modal
312
+ * is opened seem to pose no issue.
313
+ */
314
+ onClick={(): void => {
315
+ if (
316
+ // only when there are dialogs being opened
317
+ // NOTE: this seems rather hacky, but querying by role is the least
318
+ // vendor-dependent approach we can think of at the moment
319
+ document.querySelectorAll('[role="dialog"]').length &&
320
+ // only when the focus is not already with the input field
321
+ // this means the focus is being stolen from the assistant because
322
+ // the newly opened modal is opened more recently than the assistant
323
+ //
324
+ // once the focus has been gained by the assistant
325
+ // we will not need to do this anymore
326
+ searchInputRef.current !== document.activeElement
327
+ ) {
328
+ assistantService.refreshPanelRendering();
329
+ }
330
+ }}
298
331
  className={clsx('virtual-assistant__search__input input--dark', {
299
332
  'virtual-assistant__search__input--searching': searchText,
300
333
  })}
@@ -338,8 +371,11 @@ const VirtualAssistantSearchPanel = observer(() => {
338
371
  )}
339
372
  {searchText && !results.length && (
340
373
  <BlankPanelContent>
341
- <div className="virtual-assistant__search__results__placeholder">
342
- no result
374
+ <div className="virtual-assistant__panel__placeholder">
375
+ <FaceSadTearIcon className="virtual-assistant__panel__placeholder__icon" />
376
+ <div className="virtual-assistant__panel__placeholder__message">
377
+ No result...
378
+ </div>
343
379
  </div>
344
380
  </BlankPanelContent>
345
381
  )}
@@ -363,8 +399,8 @@ const VirtualAssistantSearchPanel = observer(() => {
363
399
  <MenuContentItem onClick={downloadDocRegistry}>
364
400
  Download documentation registry
365
401
  </MenuContentItem>
366
- <MenuContentItem onClick={downloadContextualDocRegistry}>
367
- Download contextual documentation registry
402
+ <MenuContentItem onClick={downloadContextualDocMap}>
403
+ Download contextual documentation mapping
368
404
  </MenuContentItem>
369
405
  </MenuContent>
370
406
  }
@@ -405,14 +441,68 @@ const VirtualAssistantPanel = observer(
405
441
  const closeAssistantPanel = (): void => assistantService.setIsOpen(false);
406
442
 
407
443
  return (
408
- <BasePopper
444
+ /**
445
+ * The most appropriate component to use is `Popper`
446
+ * as it does not block click-away
447
+ * See https://mui.com/material-ui/react-popper/
448
+ *
449
+ * However, the caveat is that in the implementation of mui Popper
450
+ * focus trap is not supported. As such, we could end up in a situation
451
+ * where the assistant input fields will not be focusable
452
+ * when another modal is being opened, as that newly opened modal will
453
+ * **steal** the focus
454
+ *
455
+ * See https://github.com/finos/legend-studio/issues/1255
456
+ * See https://mui.com/material-ui/react-modal/#focus-trap
457
+ * See https://github.com/mui/material-ui/issues/17497
458
+ */
459
+ <BasePopover
409
460
  open={assistantService.isOpen}
410
461
  className="virtual-assistant__panel__container"
411
462
  anchorEl={triggerElement}
463
+ // we need to get rid of the backdrop and the click-away trap
464
+ // to make popover behave like a popper
465
+ hideBackdrop={true}
466
+ PaperProps={{
467
+ // we will cancel the effect of click-away trap using CSS
468
+ classes: { root: 'virtual-assistant__panel__container__root' },
469
+ }}
470
+ // allow other modals to take the focus from the virtual assistant
471
+ disableEnforceFocus={true}
412
472
  // NOTE: make sure the assistant is always fully displayed (not cropped)
413
- placement="auto-start"
473
+ anchorOrigin={{
474
+ vertical: 'bottom',
475
+ horizontal: 'left',
476
+ }}
477
+ transformOrigin={{
478
+ vertical: 'bottom',
479
+ horizontal: 'right',
480
+ }}
481
+ key={assistantService.panelRenderingKey}
414
482
  >
415
- <div className="virtual-assistant__panel">
483
+ <div
484
+ className="virtual-assistant__panel"
485
+ // NOTE: here we block `tabbing` (to move focus). This is to counter the effect of
486
+ // `disableEnforceFocus={true}` set in the assistant panel popover
487
+ // this is the poor-man focus trap for the assistant to ensure
488
+ // that we don't leak focus tab down to other parts of the app
489
+ //
490
+ // Especially, due to the hack we do to compete for focus when another modal
491
+ // is opened, we need to do this to avoid leaking of focus to components
492
+ // beneath the modal via assistant
493
+ //
494
+ // setting `tabIndex={0}` is a hack to make this DOM node focusable
495
+ // and hence, we could trap the focus here using `onKeyDown`
496
+ // See https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
497
+ tabIndex={0}
498
+ onKeyDown={(event): void => {
499
+ if (event.key === 'Tab') {
500
+ event.preventDefault();
501
+ event.stopPropagation();
502
+ return;
503
+ }
504
+ }}
505
+ >
416
506
  <div className="virtual-assistant__panel__header">
417
507
  <div className="virtual-assistant__panel__header__tabs">
418
508
  <div
@@ -466,7 +556,7 @@ const VirtualAssistantPanel = observer(
466
556
  )}
467
557
  </div>
468
558
  </div>
469
- </BasePopper>
559
+ </BasePopover>
470
560
  );
471
561
  },
472
562
  );