@finos/legend-query-builder 0.1.2 → 0.2.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 (329) hide show
  1. package/lib/components/QueryBuilder.d.ts.map +1 -1
  2. package/lib/components/QueryBuilder.js +1 -1
  3. package/lib/components/QueryBuilder.js.map +1 -1
  4. package/lib/components/QueryBuilderComponentTestUtils.d.ts.map +1 -1
  5. package/lib/components/QueryBuilderComponentTestUtils.js +1 -3
  6. package/lib/components/QueryBuilderComponentTestUtils.js.map +1 -1
  7. package/lib/components/QueryBuilderDiffPanel.js +1 -2
  8. package/lib/components/QueryBuilderDiffPanel.js.map +1 -1
  9. package/lib/components/QueryBuilderParametersPanel.d.ts +1 -1
  10. package/lib/components/QueryBuilderParametersPanel.d.ts.map +1 -1
  11. package/lib/components/QueryBuilderParametersPanel.js +8 -5
  12. package/lib/components/QueryBuilderParametersPanel.js.map +1 -1
  13. package/lib/components/QueryBuilderPropertyExpressionEditor.d.ts.map +1 -1
  14. package/lib/components/QueryBuilderPropertyExpressionEditor.js +11 -8
  15. package/lib/components/QueryBuilderPropertyExpressionEditor.js.map +1 -1
  16. package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
  17. package/lib/components/QueryBuilderResultPanel.js +6 -4
  18. package/lib/components/QueryBuilderResultPanel.js.map +1 -1
  19. package/lib/components/QueryBuilderTextEditor.js +2 -2
  20. package/lib/components/QueryBuilderTextEditor.js.map +1 -1
  21. package/lib/components/QueryBuilder_TestID.d.ts +1 -0
  22. package/lib/components/QueryBuilder_TestID.d.ts.map +1 -1
  23. package/lib/components/QueryBuilder_TestID.js +1 -0
  24. package/lib/components/QueryBuilder_TestID.js.map +1 -1
  25. package/lib/components/explorer/QueryBuilderExplorerPanel.js +2 -2
  26. package/lib/components/explorer/QueryBuilderExplorerPanel.js.map +1 -1
  27. package/lib/components/explorer/QueryBuilderMilestoningEditor.d.ts.map +1 -1
  28. package/lib/components/explorer/QueryBuilderMilestoningEditor.js +5 -4
  29. package/lib/components/explorer/QueryBuilderMilestoningEditor.js.map +1 -1
  30. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  31. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +4 -2
  32. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  33. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js +1 -1
  34. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js.map +1 -1
  35. package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
  36. package/lib/components/filter/QueryBuilderFilterPanel.js +7 -4
  37. package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
  38. package/lib/components/shared/BasicValueSpecificationEditor.d.ts +53 -0
  39. package/lib/components/shared/BasicValueSpecificationEditor.d.ts.map +1 -0
  40. package/lib/components/shared/BasicValueSpecificationEditor.js +323 -0
  41. package/lib/components/shared/BasicValueSpecificationEditor.js.map +1 -0
  42. package/lib/components/shared/CustomDatePicker.d.ts +39 -0
  43. package/lib/components/shared/CustomDatePicker.d.ts.map +1 -0
  44. package/lib/components/shared/CustomDatePicker.js +622 -0
  45. package/lib/components/shared/CustomDatePicker.js.map +1 -0
  46. package/lib/components/shared/LambdaEditor.d.ts +92 -0
  47. package/lib/components/shared/LambdaEditor.d.ts.map +1 -0
  48. package/lib/components/shared/LambdaEditor.js +432 -0
  49. package/lib/components/shared/LambdaEditor.js.map +1 -0
  50. package/lib/{graphManager/protocol/pure/v1/V1_QueryBuilder_PropertyExpressionTypeInferenceBuilder.d.ts → components/shared/LambdaParameterValuesEditor.d.ts} +11 -3
  51. package/lib/components/shared/LambdaParameterValuesEditor.d.ts.map +1 -0
  52. package/lib/components/shared/LambdaParameterValuesEditor.js +52 -0
  53. package/lib/components/shared/LambdaParameterValuesEditor.js.map +1 -0
  54. package/lib/components/shared/QueryBuilderLambdaEditor.d.ts +1 -1
  55. package/lib/components/shared/QueryBuilderLambdaEditor.d.ts.map +1 -1
  56. package/lib/components/shared/QueryBuilderLambdaEditor.js +3 -2
  57. package/lib/components/shared/QueryBuilderLambdaEditor.js.map +1 -1
  58. package/lib/graphManager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.d.ts.map +1 -1
  59. package/lib/graphManager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.js +1 -2
  60. package/lib/graphManager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.js.map +1 -1
  61. package/lib/graphManager/protocol/pure/v1/{V1_QueryBuilder_FunctionExpressionBuilder.d.ts → V1_QueryValueSpecificationBuilderHelper.d.ts} +3 -2
  62. package/lib/graphManager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.d.ts.map +1 -0
  63. package/lib/graphManager/protocol/pure/v1/{V1_QueryBuilder_FunctionExpressionBuilder.js → V1_QueryValueSpecificationBuilderHelper.js} +3 -2
  64. package/lib/graphManager/protocol/pure/v1/V1_QueryValueSpecificationBuilderHelper.js.map +1 -0
  65. package/lib/index.css +2 -2
  66. package/lib/index.css.map +1 -1
  67. package/lib/index.d.ts +7 -0
  68. package/lib/index.d.ts.map +1 -1
  69. package/lib/index.js +8 -0
  70. package/lib/index.js.map +1 -1
  71. package/lib/package.json +7 -10
  72. package/lib/stores/QueryBuilderMilestoningState.d.ts.map +1 -1
  73. package/lib/stores/QueryBuilderMilestoningState.js +6 -6
  74. package/lib/stores/QueryBuilderMilestoningState.js.map +1 -1
  75. package/lib/stores/QueryBuilderParametersState.d.ts +1 -1
  76. package/lib/stores/QueryBuilderParametersState.d.ts.map +1 -1
  77. package/lib/stores/QueryBuilderParametersState.js +1 -1
  78. package/lib/stores/QueryBuilderParametersState.js.map +1 -1
  79. package/lib/stores/QueryBuilderPropertyEditorState.d.ts.map +1 -1
  80. package/lib/stores/QueryBuilderPropertyEditorState.js +35 -38
  81. package/lib/stores/QueryBuilderPropertyEditorState.js.map +1 -1
  82. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  83. package/lib/stores/QueryBuilderResultState.js +2 -1
  84. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  85. package/lib/stores/QueryBuilderState.d.ts +2 -2
  86. package/lib/stores/QueryBuilderState.d.ts.map +1 -1
  87. package/lib/stores/QueryBuilderState.js +5 -5
  88. package/lib/stores/QueryBuilderState.js.map +1 -1
  89. package/lib/stores/QueryBuilderStateBuilder.js +1 -1
  90. package/lib/stores/QueryBuilderStateBuilder.js.map +1 -1
  91. package/lib/stores/QueryBuilderTextEditorState.d.ts +1 -1
  92. package/lib/stores/QueryBuilderTextEditorState.d.ts.map +1 -1
  93. package/lib/stores/QueryBuilderTextEditorState.js +2 -1
  94. package/lib/stores/QueryBuilderTextEditorState.js.map +1 -1
  95. package/lib/stores/QueryBuilderValueSpecificationBuilder.d.ts.map +1 -1
  96. package/lib/stores/QueryBuilderValueSpecificationBuilder.js +2 -2
  97. package/lib/stores/QueryBuilderValueSpecificationBuilder.js.map +1 -1
  98. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.d.ts.map +1 -1
  99. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.js +23 -20
  100. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.js.map +1 -1
  101. package/lib/stores/QueryBuilderValueSpecificationHelper.d.ts +1 -1
  102. package/lib/stores/QueryBuilderValueSpecificationHelper.d.ts.map +1 -1
  103. package/lib/stores/QueryBuilderValueSpecificationHelper.js +10 -9
  104. package/lib/stores/QueryBuilderValueSpecificationHelper.js.map +1 -1
  105. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts.map +1 -1
  106. package/lib/stores/explorer/QueryBuilderExplorerState.js +4 -3
  107. package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
  108. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js +1 -1
  109. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js.map +1 -1
  110. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeUtil.js +1 -1
  111. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeUtil.js.map +1 -1
  112. package/lib/stores/fetch-structure/graph-fetch/{QueryBuilderGraphFetchValueSpecificationBuilder.d.ts → QueryBuilderGraphFetchTreeValueSpecificationBuilder.d.ts} +1 -1
  113. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeValueSpecificationBuilder.d.ts.map +1 -0
  114. package/lib/stores/fetch-structure/graph-fetch/{QueryBuilderGraphFetchValueSpecificationBuilder.js → QueryBuilderGraphFetchTreeValueSpecificationBuilder.js} +1 -1
  115. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeValueSpecificationBuilder.js.map +1 -0
  116. package/lib/stores/fetch-structure/projection/QueryBuilderProjectionColumnState.d.ts +1 -1
  117. package/lib/stores/fetch-structure/projection/QueryBuilderProjectionColumnState.d.ts.map +1 -1
  118. package/lib/stores/fetch-structure/projection/QueryBuilderProjectionColumnState.js +3 -3
  119. package/lib/stores/fetch-structure/projection/QueryBuilderProjectionColumnState.js.map +1 -1
  120. package/lib/stores/fetch-structure/projection/QueryBuilderProjectionState.js +1 -1
  121. package/lib/stores/fetch-structure/projection/QueryBuilderProjectionState.js.map +1 -1
  122. package/lib/stores/fetch-structure/projection/QueryBuilderProjectionStateBuilder.js +4 -4
  123. package/lib/stores/fetch-structure/projection/QueryBuilderProjectionStateBuilder.js.map +1 -1
  124. package/lib/stores/fetch-structure/projection/QueryBuilderProjectionValueSpecificationBuilder.d.ts.map +1 -1
  125. package/lib/stores/fetch-structure/projection/QueryBuilderProjectionValueSpecificationBuilder.js +6 -6
  126. package/lib/stores/fetch-structure/projection/QueryBuilderProjectionValueSpecificationBuilder.js.map +1 -1
  127. package/lib/stores/fetch-structure/projection/aggregation/operators/{QueryBuilderAggregateOperatorHelper.d.ts → QueryBuilderAggregateOperatorValueSpecificationBuilder.d.ts} +2 -2
  128. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperatorValueSpecificationBuilder.d.ts.map +1 -0
  129. package/lib/stores/fetch-structure/projection/aggregation/operators/{QueryBuilderAggregateOperatorHelper.js → QueryBuilderAggregateOperatorValueSpecificationBuilder.js} +2 -2
  130. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperatorValueSpecificationBuilder.js.map +1 -0
  131. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Average.js +3 -3
  132. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Average.js.map +1 -1
  133. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Count.js +3 -3
  134. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Count.js.map +1 -1
  135. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Distinct.js +3 -3
  136. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Distinct.js.map +1 -1
  137. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_DistinctCount.js +1 -1
  138. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_DistinctCount.js.map +1 -1
  139. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_JoinString.js +1 -1
  140. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_JoinString.js.map +1 -1
  141. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Max.js +5 -5
  142. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Max.js.map +1 -1
  143. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Min.js +5 -5
  144. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Min.js.map +1 -1
  145. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_StdDev_Population.js +3 -3
  146. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_StdDev_Population.js.map +1 -1
  147. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_StdDev_Sample.js +3 -3
  148. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_StdDev_Sample.js.map +1 -1
  149. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Sum.js +3 -3
  150. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Sum.js.map +1 -1
  151. package/lib/stores/fetch-structure/projection/post-filter/QueryBuilderPostFilterStateBuilder.js +2 -2
  152. package/lib/stores/fetch-structure/projection/post-filter/QueryBuilderPostFilterStateBuilder.js.map +1 -1
  153. package/lib/stores/fetch-structure/projection/post-filter/QueryBuilderPostFilterValueSpecificationBuilder.d.ts +1 -1
  154. package/lib/stores/fetch-structure/projection/post-filter/QueryBuilderPostFilterValueSpecificationBuilder.d.ts.map +1 -1
  155. package/lib/stores/fetch-structure/projection/post-filter/QueryBuilderPostFilterValueSpecificationBuilder.js +10 -10
  156. package/lib/stores/fetch-structure/projection/post-filter/QueryBuilderPostFilterValueSpecificationBuilder.js.map +1 -1
  157. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperatorHelper.d.ts +1 -4
  158. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperatorHelper.d.ts.map +1 -1
  159. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperatorHelper.js +3 -46
  160. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperatorHelper.js.map +1 -1
  161. package/{src/graphManager/protocol/pure/v1/V1_QueryBuilder_PropertyExpressionTypeInferenceBuilder.ts → lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperatorValueSpecificationBuilder.d.ts} +5 -13
  162. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperatorValueSpecificationBuilder.d.ts.map +1 -0
  163. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperatorValueSpecificationBuilder.js +61 -0
  164. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperatorValueSpecificationBuilder.js.map +1 -0
  165. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_Contain.d.ts.map +1 -1
  166. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_Contain.js +5 -4
  167. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_Contain.js.map +1 -1
  168. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_EndWith.d.ts.map +1 -1
  169. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_EndWith.js +5 -4
  170. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_EndWith.js.map +1 -1
  171. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_Equal.d.ts.map +1 -1
  172. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_Equal.js +10 -8
  173. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_Equal.js.map +1 -1
  174. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThan.d.ts.map +1 -1
  175. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThan.js +5 -4
  176. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThan.js.map +1 -1
  177. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThanEqual.js +3 -3
  178. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThanEqual.js.map +1 -1
  179. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_In.js +3 -3
  180. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_In.js.map +1 -1
  181. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_IsEmpty.js +1 -1
  182. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_IsEmpty.js.map +1 -1
  183. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_LessThan.d.ts.map +1 -1
  184. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_LessThan.js +5 -4
  185. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_LessThan.js.map +1 -1
  186. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_LessThanEqual.js +3 -3
  187. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_LessThanEqual.js.map +1 -1
  188. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_StartWith.d.ts.map +1 -1
  189. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_StartWith.js +5 -4
  190. package/lib/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_StartWith.js.map +1 -1
  191. package/lib/stores/filter/operators/{QueryBuilderFilterOperatorHelper.d.ts → QueryBuilderFilterOperatorValueSpecificationBuilder.d.ts} +1 -1
  192. package/lib/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.d.ts.map +1 -0
  193. package/lib/stores/filter/operators/{QueryBuilderFilterOperatorHelper.js → QueryBuilderFilterOperatorValueSpecificationBuilder.js} +11 -13
  194. package/lib/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.js.map +1 -0
  195. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.d.ts.map +1 -1
  196. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.js +7 -6
  197. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.js.map +1 -1
  198. package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.d.ts.map +1 -1
  199. package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.js +7 -6
  200. package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.js.map +1 -1
  201. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.d.ts.map +1 -1
  202. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.js +13 -11
  203. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.js.map +1 -1
  204. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.d.ts.map +1 -1
  205. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.js +8 -7
  206. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.js.map +1 -1
  207. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.d.ts.map +1 -1
  208. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.js +8 -7
  209. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.js.map +1 -1
  210. package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.js +6 -6
  211. package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.js.map +1 -1
  212. package/lib/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.js +4 -4
  213. package/lib/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.js.map +1 -1
  214. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.d.ts.map +1 -1
  215. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.js +8 -7
  216. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.js.map +1 -1
  217. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.d.ts.map +1 -1
  218. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.js +8 -7
  219. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.js.map +1 -1
  220. package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.d.ts.map +1 -1
  221. package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.js +7 -6
  222. package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.js.map +1 -1
  223. package/lib/stores/shared/LambdaEditorState.d.ts +40 -0
  224. package/lib/stores/shared/LambdaEditorState.d.ts.map +1 -0
  225. package/lib/stores/shared/LambdaEditorState.js +81 -0
  226. package/lib/stores/shared/LambdaEditorState.js.map +1 -0
  227. package/lib/stores/shared/LambdaParameterState.d.ts +62 -0
  228. package/lib/stores/shared/LambdaParameterState.d.ts.map +1 -0
  229. package/lib/stores/shared/LambdaParameterState.js +157 -0
  230. package/lib/stores/shared/LambdaParameterState.js.map +1 -0
  231. package/lib/{graphManager/protocol/pure/v1/V1_QueryBuilder_PropertyExpressionTypeInferenceBuilder.js → stores/shared/ValueSpecificationEditorHelper.d.ts} +5 -3
  232. package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts.map +1 -0
  233. package/lib/stores/shared/ValueSpecificationEditorHelper.js +77 -0
  234. package/lib/stores/shared/ValueSpecificationEditorHelper.js.map +1 -0
  235. package/lib/stores/shared/ValueSpecificationModifierHelper.d.ts +33 -0
  236. package/lib/stores/shared/ValueSpecificationModifierHelper.d.ts.map +1 -0
  237. package/lib/stores/shared/ValueSpecificationModifierHelper.js +71 -0
  238. package/lib/stores/shared/ValueSpecificationModifierHelper.js.map +1 -0
  239. package/package.json +14 -17
  240. package/src/components/QueryBuilder.tsx +4 -1
  241. package/src/components/QueryBuilderComponentTestUtils.tsx +2 -2
  242. package/src/components/QueryBuilderDiffPanel.tsx +1 -1
  243. package/src/components/QueryBuilderParametersPanel.tsx +8 -7
  244. package/src/components/QueryBuilderPropertyExpressionEditor.tsx +15 -12
  245. package/src/components/QueryBuilderResultPanel.tsx +8 -6
  246. package/src/components/QueryBuilderTextEditor.tsx +2 -2
  247. package/src/components/QueryBuilder_TestID.ts +2 -0
  248. package/src/components/explorer/QueryBuilderExplorerPanel.tsx +2 -2
  249. package/src/components/explorer/QueryBuilderMilestoningEditor.tsx +5 -3
  250. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +6 -4
  251. package/src/components/fetch-structure/QueryBuilderResultModifierPanel.tsx +1 -1
  252. package/src/components/filter/QueryBuilderFilterPanel.tsx +9 -6
  253. package/src/components/shared/BasicValueSpecificationEditor.tsx +837 -0
  254. package/src/components/shared/CustomDatePicker.tsx +1363 -0
  255. package/src/components/shared/LambdaEditor.tsx +858 -0
  256. package/src/components/shared/LambdaParameterValuesEditor.tsx +121 -0
  257. package/src/components/shared/QueryBuilderLambdaEditor.tsx +5 -5
  258. package/src/graphManager/protocol/pure/QueryBuilder_PureProtocolProcessorPlugin.ts +2 -2
  259. package/src/graphManager/protocol/pure/v1/{V1_QueryBuilder_FunctionExpressionBuilder.ts → V1_QueryValueSpecificationBuilderHelper.ts} +9 -1
  260. package/src/index.ts +11 -0
  261. package/src/stores/QueryBuilderMilestoningState.ts +7 -7
  262. package/src/stores/QueryBuilderParametersState.ts +4 -4
  263. package/src/stores/QueryBuilderPropertyEditorState.ts +49 -56
  264. package/src/stores/QueryBuilderResultState.ts +2 -4
  265. package/src/stores/QueryBuilderState.ts +5 -5
  266. package/src/stores/QueryBuilderStateBuilder.ts +1 -1
  267. package/src/stores/QueryBuilderTextEditorState.ts +2 -1
  268. package/src/stores/QueryBuilderValueSpecificationBuilder.ts +5 -2
  269. package/src/stores/QueryBuilderValueSpecificationBuilderHelper.ts +30 -42
  270. package/src/stores/QueryBuilderValueSpecificationHelper.ts +13 -8
  271. package/src/stores/explorer/QueryBuilderExplorerState.ts +12 -2
  272. package/src/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.ts +1 -1
  273. package/src/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeUtil.ts +3 -3
  274. package/src/stores/fetch-structure/graph-fetch/{QueryBuilderGraphFetchValueSpecificationBuilder.ts → QueryBuilderGraphFetchTreeValueSpecificationBuilder.ts} +0 -1
  275. package/src/stores/fetch-structure/projection/QueryBuilderProjectionColumnState.ts +3 -3
  276. package/src/stores/fetch-structure/projection/QueryBuilderProjectionState.ts +1 -1
  277. package/src/stores/fetch-structure/projection/QueryBuilderProjectionStateBuilder.ts +4 -4
  278. package/src/stores/fetch-structure/projection/QueryBuilderProjectionValueSpecificationBuilder.ts +6 -9
  279. package/src/stores/fetch-structure/projection/aggregation/operators/{QueryBuilderAggregateOperatorHelper.ts → QueryBuilderAggregateOperatorValueSpecificationBuilder.ts} +1 -1
  280. package/src/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Average.ts +3 -3
  281. package/src/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Count.ts +3 -3
  282. package/src/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Distinct.ts +3 -3
  283. package/src/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_DistinctCount.ts +1 -1
  284. package/src/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_JoinString.ts +1 -1
  285. package/src/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Max.ts +5 -5
  286. package/src/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Min.ts +5 -5
  287. package/src/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_StdDev_Population.ts +3 -3
  288. package/src/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_StdDev_Sample.ts +3 -3
  289. package/src/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperator_Sum.ts +3 -3
  290. package/src/stores/fetch-structure/projection/post-filter/QueryBuilderPostFilterStateBuilder.ts +2 -2
  291. package/src/stores/fetch-structure/projection/post-filter/QueryBuilderPostFilterValueSpecificationBuilder.ts +12 -10
  292. package/src/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperatorHelper.ts +2 -86
  293. package/src/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperatorValueSpecificationBuilder.ts +104 -0
  294. package/src/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_Contain.ts +3 -3
  295. package/src/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_EndWith.ts +3 -3
  296. package/src/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_Equal.ts +8 -7
  297. package/src/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThan.ts +4 -4
  298. package/src/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThanEqual.ts +3 -3
  299. package/src/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_In.ts +2 -2
  300. package/src/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_IsEmpty.ts +1 -1
  301. package/src/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_LessThan.ts +4 -4
  302. package/src/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_LessThanEqual.ts +3 -3
  303. package/src/stores/fetch-structure/projection/post-filter/operators/QueryBuilderPostFilterOperator_StartWith.ts +3 -3
  304. package/src/stores/filter/operators/{QueryBuilderFilterOperatorHelper.ts → QueryBuilderFilterOperatorValueSpecificationBuilder.ts} +10 -11
  305. package/src/stores/filter/operators/QueryBuilderFilterOperator_Contain.ts +5 -5
  306. package/src/stores/filter/operators/QueryBuilderFilterOperator_EndWith.ts +5 -5
  307. package/src/stores/filter/operators/QueryBuilderFilterOperator_Equal.ts +11 -10
  308. package/src/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.ts +7 -7
  309. package/src/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.ts +7 -7
  310. package/src/stores/filter/operators/QueryBuilderFilterOperator_In.ts +5 -5
  311. package/src/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.ts +3 -3
  312. package/src/stores/filter/operators/QueryBuilderFilterOperator_LessThan.ts +7 -7
  313. package/src/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.ts +7 -7
  314. package/src/stores/filter/operators/QueryBuilderFilterOperator_StartWith.ts +5 -5
  315. package/src/stores/shared/LambdaEditorState.ts +118 -0
  316. package/src/stores/shared/LambdaParameterState.ts +259 -0
  317. package/src/stores/shared/ValueSpecificationEditorHelper.ts +143 -0
  318. package/src/stores/shared/ValueSpecificationModifierHelper.ts +177 -0
  319. package/tsconfig.json +14 -7
  320. package/lib/graphManager/protocol/pure/v1/V1_QueryBuilder_FunctionExpressionBuilder.d.ts.map +0 -1
  321. package/lib/graphManager/protocol/pure/v1/V1_QueryBuilder_FunctionExpressionBuilder.js.map +0 -1
  322. package/lib/graphManager/protocol/pure/v1/V1_QueryBuilder_PropertyExpressionTypeInferenceBuilder.d.ts.map +0 -1
  323. package/lib/graphManager/protocol/pure/v1/V1_QueryBuilder_PropertyExpressionTypeInferenceBuilder.js.map +0 -1
  324. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchValueSpecificationBuilder.d.ts.map +0 -1
  325. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchValueSpecificationBuilder.js.map +0 -1
  326. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperatorHelper.d.ts.map +0 -1
  327. package/lib/stores/fetch-structure/projection/aggregation/operators/QueryBuilderAggregateOperatorHelper.js.map +0 -1
  328. package/lib/stores/filter/operators/QueryBuilderFilterOperatorHelper.d.ts.map +0 -1
  329. package/lib/stores/filter/operators/QueryBuilderFilterOperatorHelper.js.map +0 -1
@@ -0,0 +1,858 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { useRef, useEffect, useState, useMemo } from 'react';
18
+ import {
19
+ editor as monacoEditorAPI,
20
+ type IDisposable,
21
+ type IKeyboardEvent,
22
+ } from 'monaco-editor';
23
+ import { observer } from 'mobx-react-lite';
24
+ import {
25
+ clsx,
26
+ setErrorMarkers,
27
+ disposeEditor,
28
+ disableEditorHotKeys,
29
+ baseTextEditorSettings,
30
+ getEditorValue,
31
+ normalizeLineEnding,
32
+ FilledWindowMaximizeIcon,
33
+ LongArrowAltDownIcon,
34
+ LongArrowAltUpIcon,
35
+ Dialog,
36
+ useResizeDetector,
37
+ } from '@finos/legend-art';
38
+ import type { LambdaEditorState } from '../../stores/shared/LambdaEditorState.js';
39
+ import {
40
+ debounce,
41
+ noop,
42
+ type DebouncedFunc,
43
+ type GeneratorFn,
44
+ } from '@finos/legend-shared';
45
+ import { flowResult } from 'mobx';
46
+ import { ParserError, type EngineError, type Type } from '@finos/legend-graph';
47
+ import {
48
+ EDITOR_LANGUAGE,
49
+ EDITOR_THEME,
50
+ TAB_SIZE,
51
+ useApplicationStore,
52
+ } from '@finos/legend-application';
53
+ import { QUERY_BUILDER_TEST_ID } from '../QueryBuilder_TestID.js';
54
+
55
+ export type LambdaEditorOnKeyDownEventHandler = {
56
+ matcher: (event: IKeyboardEvent) => boolean;
57
+ action: (event: IKeyboardEvent) => void;
58
+ };
59
+
60
+ const LambdaErrorFeedback: React.FC<{
61
+ error?: EngineError | undefined;
62
+ discardChanges: () => void;
63
+ }> = (props) => {
64
+ const { error, discardChanges } = props;
65
+
66
+ if (!error) {
67
+ return null;
68
+ }
69
+ return (
70
+ <div className="lambda-editor__error-feedback">
71
+ <div className="lambda-editor__error-feedback__error__message">
72
+ {error.message}
73
+ </div>
74
+ {error instanceof ParserError && (
75
+ <div className="lambda-editor__error-feedback__parsing-error__content">
76
+ <button
77
+ className="lambda-editor__error-feedback__parsing-error__discard-changes-btn"
78
+ onClick={discardChanges}
79
+ tabIndex={-1}
80
+ >
81
+ Discard Changes
82
+ </button>
83
+ </div>
84
+ )}
85
+ </div>
86
+ );
87
+ };
88
+
89
+ const LambdaEditorInline = observer(
90
+ (props: {
91
+ className?: string | undefined;
92
+ disabled: boolean;
93
+ lambdaEditorState: LambdaEditorState;
94
+ transformStringToLambda: DebouncedFunc<() => GeneratorFn<void>> | undefined;
95
+ expectedType?: Type | undefined;
96
+ matchedExpectedType?: (() => boolean) | undefined;
97
+ onExpectedTypeLabelSelect?: (() => void) | undefined;
98
+ useBaseTextEditorSettings?: boolean | undefined;
99
+ hideErrorBar?: boolean | undefined;
100
+ forceBackdrop: boolean;
101
+ disableExpansion?: boolean | undefined;
102
+ forceExpansion?: boolean | undefined;
103
+ disablePopUp?: boolean | undefined;
104
+ backdropSetter?: ((val: boolean) => void) | undefined;
105
+ onKeyDownEventHandlers: LambdaEditorOnKeyDownEventHandler[];
106
+ openInPopUp: () => void;
107
+ onEditorFocusEventHandler?: (() => void) | undefined;
108
+ }) => {
109
+ const {
110
+ className,
111
+ disabled,
112
+ lambdaEditorState,
113
+ transformStringToLambda,
114
+ expectedType,
115
+ onExpectedTypeLabelSelect,
116
+ matchedExpectedType,
117
+ forceBackdrop,
118
+ backdropSetter,
119
+ disableExpansion,
120
+ forceExpansion,
121
+ disablePopUp,
122
+ useBaseTextEditorSettings,
123
+ hideErrorBar,
124
+ onKeyDownEventHandlers,
125
+ openInPopUp,
126
+ onEditorFocusEventHandler,
127
+ } = props;
128
+ const applicationStore = useApplicationStore();
129
+ const onDidChangeModelContentEventDisposer = useRef<
130
+ IDisposable | undefined
131
+ >(undefined);
132
+ const onKeyDownEventDisposer = useRef<IDisposable | undefined>(undefined);
133
+ const onDidFocusEditorWidgetDisposer = useRef<IDisposable | undefined>(
134
+ undefined,
135
+ );
136
+ const value = normalizeLineEnding(lambdaEditorState.lambdaString);
137
+ const parserError = lambdaEditorState.parserError;
138
+ const compilationError = lambdaEditorState.compilationError;
139
+ const selectTypeLabel = (): void => onExpectedTypeLabelSelect?.();
140
+ const [isExpanded, setExpanded] = useState(Boolean(forceExpansion));
141
+ const [editor, setEditor] = useState<
142
+ monacoEditorAPI.IStandaloneCodeEditor | undefined
143
+ >();
144
+ const textInputRef = useRef<HTMLDivElement>(null);
145
+
146
+ const transformLambdaToString = async (pretty: boolean): Promise<void> => {
147
+ transformStringToLambda?.cancel();
148
+ return flowResult(
149
+ lambdaEditorState.convertLambdaObjectToGrammarString(pretty),
150
+ ).catch(applicationStore.alertUnhandledError);
151
+ };
152
+ const discardChanges = applicationStore.guardUnhandledError(() =>
153
+ transformLambdaToString(isExpanded),
154
+ );
155
+ const toggleExpandedMode = (): void => {
156
+ if (!forceExpansion && !parserError) {
157
+ transformLambdaToString(!isExpanded).catch(
158
+ applicationStore.alertUnhandledError,
159
+ );
160
+ setExpanded(!isExpanded);
161
+ }
162
+ };
163
+
164
+ const { ref, width, height } = useResizeDetector<HTMLDivElement>();
165
+ useEffect(() => {
166
+ if (width !== undefined && height !== undefined) {
167
+ editor?.layout({ width, height });
168
+ }
169
+ }, [editor, width, height]);
170
+
171
+ useEffect(() => {
172
+ if (!editor && textInputRef.current) {
173
+ const element = textInputRef.current;
174
+ const lambdaEditorOptions: monacoEditorAPI.IStandaloneEditorConstructionOptions =
175
+ useBaseTextEditorSettings
176
+ ? {}
177
+ : {
178
+ renderLineHighlight: 'none',
179
+ lineHeight: 24,
180
+ overviewRulerBorder: false, // hide overview ruler (no current way to hide this completely yet)
181
+ overviewRulerLanes: 0,
182
+ hideCursorInOverviewRuler: false,
183
+ glyphMargin: false,
184
+ folding: false,
185
+ minimap: { enabled: false },
186
+ lineNumbers: 'off',
187
+ lineNumbersMinChars: 0,
188
+ lineDecorationsWidth: 5,
189
+ snippetSuggestions: 'none',
190
+ scrollbar: { vertical: 'hidden' },
191
+ };
192
+ const _editor = monacoEditorAPI.create(element, {
193
+ ...baseTextEditorSettings,
194
+ language: EDITOR_LANGUAGE.PURE,
195
+ theme: applicationStore.TEMPORARY__isLightThemeEnabled
196
+ ? EDITOR_THEME.TEMPORARY__VSCODE_LIGHT
197
+ : EDITOR_THEME.LEGEND,
198
+ ...lambdaEditorOptions,
199
+ });
200
+ disableEditorHotKeys(_editor);
201
+ setEditor(_editor);
202
+ }
203
+ }, [editor, applicationStore, useBaseTextEditorSettings]);
204
+
205
+ // set styling for expanded mode
206
+ useEffect(() => {
207
+ if (editor) {
208
+ const currentClassName = editor.getRawOptions().extraEditorClassName;
209
+ const isInExpanded = currentClassName === 'lambda-editor__expanded';
210
+ if (isInExpanded !== isExpanded) {
211
+ editor.updateOptions(
212
+ isExpanded
213
+ ? {
214
+ extraEditorClassName:
215
+ 'lambda-editor__editor__input__expanded',
216
+ }
217
+ : {
218
+ extraEditorClassName:
219
+ 'lambda-editor__editor__input__compressed',
220
+ },
221
+ );
222
+ // set the value here so we don't lose the error when toggling between expand/collape modes
223
+ const currentValue = getEditorValue(editor);
224
+ editor.setValue(currentValue);
225
+ }
226
+ }
227
+ }, [editor, isExpanded]);
228
+
229
+ // set backdrop to force user to fix parser error when it happens
230
+ useEffect(() => {
231
+ if (backdropSetter) {
232
+ if (parserError) {
233
+ backdropSetter(true);
234
+ } else if (!forceBackdrop) {
235
+ // make sure the backdrop is no longer `needed` for blocking by another parser error before hiding it
236
+ // NOTE: this has a serious drawback, see the documentation for `forceBackdrop` prop of `LambdaEditor`
237
+ // for better context
238
+ backdropSetter(false);
239
+ }
240
+ }
241
+ }, [parserError, forceBackdrop, backdropSetter]);
242
+
243
+ if (editor) {
244
+ /**
245
+ * See the extensive note about this instantiation in `LambdaEditor`. The fact that `transformStringToLambda` can change
246
+ * since it does not solely depends on `LambdaEditorState` but also the `disabled` flag means that the update function
247
+ * can go stale, so we cannot place this `onDidChangeModelContent` in a one-time called instantiation of the editor
248
+ * (i.e. the first `useEffect` where we create the editor). As such, we have to use refs and disposer to update this every time
249
+ * the lambda editor is re-rendered.
250
+ *
251
+ * A potential bug that could come up if we place this logic in the `useEffect` for instantiating the editor is:
252
+ * 1. Initially set the `disabled` to true, then switch it back to `false` (using a timer or something)
253
+ * 2. Type something in the lambda editor, the transform function is `undefined` and does not update the underlying lambda
254
+ */
255
+ onDidChangeModelContentEventDisposer.current?.dispose();
256
+ onDidChangeModelContentEventDisposer.current =
257
+ editor.onDidChangeModelContent(() => {
258
+ const currentVal = getEditorValue(editor);
259
+ /**
260
+ * Avoid unecessary setting of lambda string. Also, this prevents clearing the non-parser error on first render.
261
+ * Since this method is guaranteed to be called one time during the first rendering when we first set the
262
+ * value for the lambda editor, we do not want to clear any existing non-parser error in case it is set by methods
263
+ * like reveal error in each editor
264
+ */
265
+ if (currentVal !== value) {
266
+ lambdaEditorState.setLambdaString(currentVal);
267
+ /**
268
+ * Here we clear the error as user changes the input
269
+ * NOTE: we don't reset the parser error here, we could, but with that, we have to assume that the parsing check is
270
+ * pretty quick--almost near real time, but if after typing new character, we clear the parsing error and the user
271
+ * still make mistake, then the warning message will appear to flash, which is bad UX, so for now, we leave it be
272
+ */
273
+ lambdaEditorState.setCompilationError(undefined);
274
+ }
275
+ /**
276
+ * This method MUST run on the first rendering of the lambda editor, as it will update the lambda object. This is
277
+ * needed for new lambda where a lot of time is just a stub lambda. Without having this method called on the first
278
+ * rendering, that stub lambda will remain stub lambda until user starts typing something in the lambda editor.
279
+ * This stub lambda sometimes does not even get registered in change detection and causing the user to lose data
280
+ * Although, technically a stub lambda is useless, so this is not too serious, but it may come across as buggy
281
+ */
282
+ transformStringToLambda?.cancel();
283
+ if (transformStringToLambda) {
284
+ const stringToLambdaTransformation = transformStringToLambda();
285
+ if (stringToLambdaTransformation) {
286
+ flowResult(stringToLambdaTransformation).catch(
287
+ applicationStore.alertUnhandledError,
288
+ );
289
+ }
290
+ }
291
+ });
292
+
293
+ // set hotkeys (before calling the action, finish parsing the current text value)
294
+ onKeyDownEventDisposer.current?.dispose(); // dispose to avoid trigger hotkeys multiple times
295
+ /**
296
+ * NOTE: We can use `setCommand` here but that does not expose the event so we cannot `stopPropagation`, and we need to
297
+ * use `stopPropagation` to prevent the event top bubble up to global hotkeys listener.
298
+ * If we really want to use `setCommand` the other approach is to set <HotKeys/> around this lambda editor to override F9
299
+ * perhaps that's the cleaner approach because we use `react-hotkeys` to handle it's business, but there is an on-going
300
+ * issue with <HotKeys/> keybindings are lost when component rerenders and this happen as users type because we call `setValue`
301
+ * See https://github.com/greena13/react-hotkeys/issues/209
302
+ *
303
+ * The main role of this section is to disable `monaco-editor` command and override with global actions, such as generate, compile,
304
+ * toggle text mode, etc. The important thing is before we do so, we would like to finish the parsing of the current string, otherwise,
305
+ * those operations can end up flushing the current state and trashing the user input, which is bad, as such, we make sure the
306
+ * parsing passes before actually calling those global operations.
307
+ */
308
+ onKeyDownEventDisposer.current = editor.onKeyDown((event) => {
309
+ onKeyDownEventHandlers.forEach((handler) => {
310
+ if (handler.matcher(event)) {
311
+ event.preventDefault();
312
+ event.stopPropagation();
313
+ transformStringToLambda?.cancel();
314
+ handler.action(event);
315
+ }
316
+ });
317
+ });
318
+
319
+ onDidFocusEditorWidgetDisposer.current?.dispose();
320
+ onDidFocusEditorWidgetDisposer.current = editor.onDidFocusEditorWidget(
321
+ () => {
322
+ onEditorFocusEventHandler?.();
323
+ },
324
+ );
325
+
326
+ // Set the text value
327
+ const currentValue = getEditorValue(editor);
328
+ const editorModel = editor.getModel();
329
+ const currentConfig = editor.getRawOptions();
330
+ if (currentValue !== value) {
331
+ editor.setValue(value);
332
+ }
333
+ if (currentConfig.readOnly !== disabled) {
334
+ editor.updateOptions({
335
+ readOnly: disabled,
336
+ });
337
+ }
338
+
339
+ // Set the errors
340
+ if (editorModel) {
341
+ editorModel.updateOptions({ tabSize: TAB_SIZE });
342
+ const error = parserError ?? compilationError;
343
+ if (error?.sourceInformation) {
344
+ setErrorMarkers(
345
+ editorModel,
346
+ error.message,
347
+ error.sourceInformation.startLine,
348
+ error.sourceInformation.startColumn,
349
+ error.sourceInformation.endLine,
350
+ error.sourceInformation.endColumn,
351
+ );
352
+ } else {
353
+ monacoEditorAPI.setModelMarkers(editorModel, 'Error', []);
354
+ }
355
+ }
356
+ }
357
+
358
+ useEffect(
359
+ () => (): void => {
360
+ if (editor) {
361
+ disposeEditor(editor);
362
+ }
363
+ },
364
+ [editor],
365
+ ); // dispose editor
366
+
367
+ return (
368
+ <>
369
+ <div
370
+ className={clsx('lambda-editor', className, {
371
+ 'lambda-editor__expanded': isExpanded,
372
+ })}
373
+ >
374
+ <div
375
+ ref={ref}
376
+ data-testid={QUERY_BUILDER_TEST_ID.LAMBDA_EDITOR__EDITOR_INPUT}
377
+ className="lambda-editor__editor__input"
378
+ >
379
+ <div className="text-editor__body" ref={textInputRef} />
380
+ </div>
381
+ {Boolean(expectedType) && (
382
+ <div className="lambda-editor__editor__info">
383
+ {onExpectedTypeLabelSelect && (
384
+ <button
385
+ className={clsx(
386
+ 'lambda-editor__editor__expected-return-type lambda-editor__editor__expected-return-type--clickable',
387
+ {
388
+ 'lambda-editor__editor__expected-return-type--highlighted':
389
+ matchedExpectedType?.(),
390
+ },
391
+ )}
392
+ onClick={selectTypeLabel}
393
+ tabIndex={-1}
394
+ title="Toggle highlight expected type"
395
+ >
396
+ {expectedType?.name ?? 'unknown'}
397
+ </button>
398
+ )}
399
+ {!onExpectedTypeLabelSelect && (
400
+ <div
401
+ className={clsx(
402
+ 'lambda-editor__editor__expected-return-type',
403
+ {
404
+ 'lambda-editor__editor__expected-return-type--highlighted':
405
+ matchedExpectedType?.(),
406
+ },
407
+ )}
408
+ >
409
+ {expectedType?.name ?? 'unknown'}
410
+ </div>
411
+ )}
412
+ </div>
413
+ )}
414
+ {!disableExpansion && !forceExpansion && (
415
+ <button
416
+ className="lambda-editor__editor__expand-btn"
417
+ onClick={toggleExpandedMode}
418
+ disabled={Boolean(parserError)}
419
+ tabIndex={-1}
420
+ title="Toggle Expand"
421
+ >
422
+ {isExpanded ? <LongArrowAltUpIcon /> : <LongArrowAltDownIcon />}
423
+ </button>
424
+ )}
425
+ {!disablePopUp && (
426
+ <button
427
+ className="lambda-editor__action"
428
+ onClick={openInPopUp}
429
+ disabled={Boolean(parserError)}
430
+ tabIndex={-1}
431
+ title="Open..."
432
+ >
433
+ <FilledWindowMaximizeIcon />
434
+ </button>
435
+ )}
436
+ </div>
437
+ {!hideErrorBar && (
438
+ <LambdaErrorFeedback
439
+ error={parserError ?? compilationError}
440
+ discardChanges={discardChanges}
441
+ />
442
+ )}
443
+ </>
444
+ );
445
+ },
446
+ );
447
+
448
+ const LambdaEditorPopUp = observer(
449
+ (props: {
450
+ className?: string | undefined;
451
+ disabled: boolean;
452
+ lambdaEditorState: LambdaEditorState;
453
+ transformStringToLambda: DebouncedFunc<() => GeneratorFn<void>> | undefined;
454
+ onKeyDownEventHandlers: LambdaEditorOnKeyDownEventHandler[];
455
+ onClose: () => void;
456
+ }) => {
457
+ const {
458
+ className,
459
+ disabled,
460
+ lambdaEditorState,
461
+ transformStringToLambda,
462
+ onKeyDownEventHandlers,
463
+ onClose,
464
+ } = props;
465
+ const applicationStore = useApplicationStore();
466
+ const onKeyDownEventDisposer = useRef<IDisposable | undefined>(undefined);
467
+ const onDidChangeModelContentEventDisposer = useRef<
468
+ IDisposable | undefined
469
+ >(undefined);
470
+ const value = normalizeLineEnding(lambdaEditorState.lambdaString);
471
+ const parserError = lambdaEditorState.parserError;
472
+ const compilationError = lambdaEditorState.compilationError;
473
+ const [editor, setEditor] = useState<
474
+ monacoEditorAPI.IStandaloneCodeEditor | undefined
475
+ >();
476
+ const textInputRef = useRef<HTMLDivElement>(null);
477
+
478
+ const transformLambdaToString = async (pretty: boolean): Promise<void> => {
479
+ transformStringToLambda?.cancel();
480
+ return flowResult(
481
+ lambdaEditorState.convertLambdaObjectToGrammarString(pretty),
482
+ ).catch(applicationStore.alertUnhandledError);
483
+ };
484
+ const discardChanges = applicationStore.guardUnhandledError(() =>
485
+ transformLambdaToString(true),
486
+ );
487
+
488
+ const { ref, width, height } = useResizeDetector<HTMLDivElement>();
489
+ useEffect(() => {
490
+ if (width !== undefined && height !== undefined) {
491
+ editor?.layout({ width, height });
492
+ }
493
+ }, [editor, width, height]);
494
+
495
+ const onEnter = (): void => {
496
+ if (!editor && textInputRef.current) {
497
+ const element = textInputRef.current;
498
+ const _editor = monacoEditorAPI.create(element, {
499
+ ...baseTextEditorSettings,
500
+ language: EDITOR_LANGUAGE.PURE,
501
+ theme: EDITOR_THEME.LEGEND,
502
+ });
503
+ disableEditorHotKeys(_editor);
504
+ setEditor(_editor);
505
+ }
506
+ };
507
+
508
+ if (editor) {
509
+ /**
510
+ * See the extensive note about this instantiation in `LambdaEditor`. The fact that `transformStringToLambda` can change
511
+ * since it does not solely depends on `LambdaEditorState` but also the `disabled` flag means that the update function
512
+ * can go stale, so we cannot place this `onDidChangeModelContent` in a one-time called instantiation of the editor
513
+ * (i.e. the first `useEffect` where we create the editor). As such, we have to use refs and disposer to update this every time
514
+ * the lambda editor is re-rendered.
515
+ *
516
+ * A potential bug that could come up if we place this logic in the `useEffect` for instantiating the editor is:
517
+ * 1. Initially set the `disabled` to true, then switch it back to `false` (using a timer or something)
518
+ * 2. Type something in the lambda editor, the transform function is `undefined` and does not update the underlying lambda
519
+ */
520
+ onDidChangeModelContentEventDisposer.current?.dispose();
521
+ onDidChangeModelContentEventDisposer.current =
522
+ editor.onDidChangeModelContent(() => {
523
+ const currentVal = getEditorValue(editor);
524
+ /**
525
+ * Avoid unecessary setting of lambda string. Also, this prevents clearing the non-parser error on first render.
526
+ * Since this method is guaranteed to be called one time during the first rendering when we first set the
527
+ * value for the lambda editor, we do not want to clear any existing non-parser error in case it is set by methods
528
+ * like reveal error in each editor
529
+ */
530
+ if (currentVal !== value) {
531
+ lambdaEditorState.setLambdaString(currentVal);
532
+ /**
533
+ * Here we clear the error as user changes the input
534
+ * NOTE: we don't reset the parser error here, we could, but with that, we have to assume that the parsing check is
535
+ * pretty quick--almost near real time, but if after typing new character, we clear the parsing error and the user
536
+ * still make mistake, then the warning message will appear to flash, which is bad UX, so for now, we leave it be
537
+ */
538
+ lambdaEditorState.setCompilationError(undefined);
539
+ }
540
+ /**
541
+ * This method MUST run on the first rendering of the lambda editor, as it will update the lambda object. This is
542
+ * needed for new lambda where a lot of time is just a stub lambda. Without having this method called on the first
543
+ * rendering, that stub lambda will remain stub lambda until user starts typing something in the lambda editor.
544
+ * This stub lambda sometimes does not even get registered in change detection and causing the user to lose data
545
+ * Although, technically a stub lambda is useless, so this is not too serious, but it may come across as buggy
546
+ */
547
+ transformStringToLambda?.cancel();
548
+ if (transformStringToLambda) {
549
+ const stringToLambdaTransformation = transformStringToLambda();
550
+ if (stringToLambdaTransformation) {
551
+ flowResult(stringToLambdaTransformation).catch(
552
+ applicationStore.alertUnhandledError,
553
+ );
554
+ }
555
+ }
556
+ });
557
+
558
+ // set hotkeys (before calling the action, finish parsing the current text value)
559
+ onKeyDownEventDisposer.current?.dispose(); // dispose to avoid trigger hotkeys multiple times
560
+ /**
561
+ * NOTE: We can use `setCommand` here but that does not expose the event so we cannot `stopPropagation`, and we need to
562
+ * use `stopPropagation` to prevent the event top bubble up to global hotkeys listener.
563
+ * If we really want to use `setCommand` the other approach is to set <HotKeys/> around this lambda editor to override F9
564
+ * perhaps that's the cleaner approach because we use `react-hotkeys` to handle it's business, but there is an on-going
565
+ * issue with <HotKeys/> keybindings are lost when component rerenders and this happen as users type because we call `setValue`
566
+ * See https://github.com/greena13/react-hotkeys/issues/209
567
+ *
568
+ * The main role of this section is to disable `monaco-editor` command and override with global actions, such as generate, compile,
569
+ * toggle text mode, etc. The important thing is before we do so, we would like to finish the parsing of the current string, otherwise,
570
+ * those operations can end up flushing the current state and trashing the user input, which is bad, as such, we make sure the
571
+ * parsing passes before actually calling those global operations.
572
+ */
573
+ onKeyDownEventDisposer.current = editor.onKeyDown((event) => {
574
+ onKeyDownEventHandlers.forEach((handler) => {
575
+ if (handler.matcher(event)) {
576
+ event.preventDefault();
577
+ event.stopPropagation();
578
+ transformStringToLambda?.cancel();
579
+ handler.action(event);
580
+ }
581
+ });
582
+ });
583
+
584
+ // Set the text value
585
+ const currentValue = getEditorValue(editor);
586
+ const editorModel = editor.getModel();
587
+ const currentConfig = editor.getRawOptions();
588
+ if (currentValue !== value) {
589
+ editor.setValue(value);
590
+ }
591
+ if (currentConfig.readOnly !== disabled) {
592
+ editor.updateOptions({
593
+ readOnly: disabled,
594
+ });
595
+ }
596
+
597
+ // Set the errors
598
+ if (editorModel) {
599
+ editorModel.updateOptions({ tabSize: TAB_SIZE });
600
+ const error = parserError ?? compilationError;
601
+ if (error?.sourceInformation) {
602
+ setErrorMarkers(
603
+ editorModel,
604
+ error.message,
605
+ error.sourceInformation.startLine,
606
+ error.sourceInformation.startColumn,
607
+ error.sourceInformation.endLine,
608
+ error.sourceInformation.endColumn,
609
+ );
610
+ } else {
611
+ monacoEditorAPI.setModelMarkers(editorModel, 'Error', []);
612
+ }
613
+ }
614
+ }
615
+
616
+ useEffect(() => {
617
+ flowResult(
618
+ lambdaEditorState.convertLambdaObjectToGrammarString(true),
619
+ ).catch(applicationStore.alertUnhandledError);
620
+ }, [applicationStore, lambdaEditorState]);
621
+
622
+ useEffect(
623
+ () => (): void => {
624
+ if (editor) {
625
+ disposeEditor(editor);
626
+ }
627
+ },
628
+ [editor],
629
+ ); // dispose editor
630
+
631
+ return (
632
+ <Dialog
633
+ open={true}
634
+ TransitionProps={{
635
+ onEnter,
636
+ }}
637
+ onClose={noop} // disallow closing dialog by using Esc key or clicking on the backdrop
638
+ classes={{
639
+ root: 'editor-modal__root-container',
640
+ container: 'editor-modal__container',
641
+ paper: 'editor-modal__content',
642
+ }}
643
+ >
644
+ <div
645
+ className={clsx(
646
+ 'modal modal--dark editor-modal lambda-editor__popup__modal',
647
+ {
648
+ 'lambda-editor__popup__modal--has-error': Boolean(
649
+ lambdaEditorState.parserError,
650
+ ),
651
+ },
652
+ )}
653
+ >
654
+ <div className="modal__header">
655
+ <div className="modal__title">Edit Lambda</div>
656
+ {lambdaEditorState.parserError && (
657
+ <div className="modal__title__error-badge">
658
+ Failed to parse lambda
659
+ </div>
660
+ )}
661
+ </div>
662
+ <div className="modal__body">
663
+ <div className={clsx('lambda-editor__popup__content', className)}>
664
+ <div
665
+ ref={ref}
666
+ data-testid={QUERY_BUILDER_TEST_ID.LAMBDA_EDITOR__EDITOR_INPUT}
667
+ className="lambda-editor__editor__input"
668
+ >
669
+ <div className="text-editor__body" ref={textInputRef} />
670
+ </div>
671
+ </div>
672
+ </div>
673
+ <div className="modal__footer">
674
+ <button
675
+ className="btn btn--dark btn--caution"
676
+ onClick={discardChanges}
677
+ >
678
+ Discard changes
679
+ </button>
680
+ <button
681
+ className="btn btn--dark"
682
+ onClick={onClose}
683
+ disabled={Boolean(lambdaEditorState.parserError)}
684
+ >
685
+ Close
686
+ </button>
687
+ </div>
688
+ </div>
689
+ </Dialog>
690
+ );
691
+ },
692
+ );
693
+
694
+ /**
695
+ * This is not strictly meant for lambda. The idea is to create an editor that allows
696
+ * editing _something_ but allows user to edit via text.
697
+ */
698
+ export const LambdaEditor = observer(
699
+ (props: {
700
+ className?: string | undefined;
701
+ disabled: boolean;
702
+ lambdaEditorState: LambdaEditorState;
703
+ /**
704
+ * TODO: when we pass in these expected type we should match a type as expected type if it's covariance, i.e. it is a subtype of
705
+ * the expected type. Note that we also have to handle that relationship for Primitive type
706
+ * See https://dzone.com/articles/covariance-and-contravariance
707
+ */
708
+ expectedType?: Type | undefined;
709
+ matchedExpectedType?: (() => boolean) | undefined;
710
+ onExpectedTypeLabelSelect?: (() => void) | undefined;
711
+ /**
712
+ * As backdrop element is often shared in the application, and there could be multiple
713
+ * editor using that backdrop, we could end up in situation where some such editors
714
+ * have parser errors and some don't (this can happen when user make edits very quickly 2 lambda
715
+ * editor and causes parsers error simultaneously). In this case, we want to make sure when
716
+ * parser error is fixed in one editor, the backdrop is not dismissed immediately.
717
+ *
718
+ * NOTE: the current approach has a critical flaw, where on the same screen, there could be multiple
719
+ * sets of lambda editors with different values for `forceBackdrop`. So really, the only way to
720
+ * accomondate for this is to have `forceBackdrop` as a global value. Or we should get rid of this
721
+ * backdrop mechanism altogether as it's not really a good UX pattern. i.e. quick evaluation makes
722
+ * us believe that this is a good option, user will lose what they type, but the most recent parsable
723
+ * input will still be captured.
724
+ */
725
+ forceBackdrop: boolean;
726
+ /**
727
+ * (de)activator for backdrop that is usually used to block any background interactions
728
+ * while there is a parser error in the editor
729
+ */
730
+ backdropSetter?: ((val: boolean) => void) | undefined;
731
+ /**
732
+ * To whether or not disable expasipn toggler
733
+ */
734
+ disableExpansion?: boolean | undefined;
735
+ /**
736
+ * To whether show the inline editor in expanded mode initially and
737
+ * disable expansion toggler
738
+ *
739
+ * This flag will override the effect of `forceExpansion`
740
+ */
741
+ forceExpansion?: boolean | undefined;
742
+ /**
743
+ * To whether or not disable popup mode
744
+ */
745
+ disablePopUp?: boolean | undefined;
746
+ /**
747
+ * To whether or not style inline editor
748
+ */
749
+ useBaseTextEditorSettings?: boolean | undefined;
750
+ /**
751
+ * To whether or not hide parser error bar in inline mode
752
+ */
753
+ hideErrorBar?: boolean | undefined;
754
+ /**
755
+ * Allow adding hotkeys handler to the editor, this is usually used
756
+ * to allow activating global hotkeys while typing in the editor
757
+ */
758
+ onKeyDownEventHandlers?: LambdaEditorOnKeyDownEventHandler[];
759
+ onEditorFocusEventHandler?: (() => void) | undefined;
760
+ }) => {
761
+ const {
762
+ className,
763
+ lambdaEditorState,
764
+ disabled,
765
+ forceBackdrop,
766
+ backdropSetter,
767
+ expectedType,
768
+ onExpectedTypeLabelSelect,
769
+ matchedExpectedType,
770
+ disableExpansion,
771
+ forceExpansion,
772
+ disablePopUp,
773
+ useBaseTextEditorSettings,
774
+ hideErrorBar,
775
+ onKeyDownEventHandlers,
776
+ onEditorFocusEventHandler,
777
+ } = props;
778
+ const [showPopUp, setShowPopUp] = useState(false);
779
+ const openInPopUp = (): void => setShowPopUp(true);
780
+ const closePopUp = (): void => setShowPopUp(false);
781
+ const debouncedTransformStringToLambda = useMemo(
782
+ () =>
783
+ disabled
784
+ ? undefined
785
+ : debounce(
786
+ () => lambdaEditorState.convertLambdaGrammarStringToObject(),
787
+ 1000,
788
+ ),
789
+ [lambdaEditorState, disabled],
790
+ );
791
+
792
+ if (!disablePopUp && showPopUp) {
793
+ return (
794
+ <>
795
+ <div className="lambda-editor" />
796
+ <LambdaEditorPopUp
797
+ className={className}
798
+ disabled={disabled}
799
+ lambdaEditorState={lambdaEditorState}
800
+ transformStringToLambda={debouncedTransformStringToLambda}
801
+ onKeyDownEventHandlers={onKeyDownEventHandlers ?? []}
802
+ onClose={closePopUp}
803
+ />
804
+ </>
805
+ );
806
+ }
807
+ return (
808
+ <LambdaEditorInline
809
+ /**
810
+ * See the usage of `transformStringToLambda` as well as the instatiation of the editor in `LambdaEditorInner`.
811
+ * One of the big problem is that the editor uses lambda editor state (there are some non-trivial logic there, that
812
+ * handles string <-> lambda object conversion), but there are certain operations in this app that can potentially
813
+ * remove and recreate the lambda editor state, such as global generate or global compile, for such case, `LambdaEditorInner`
814
+ * receives a new lambda editor state, but since React is smart about redrawing the DOM, it will not recreate the instance
815
+ * of `monaco-editor` (see the useEffect() block), as such, the editor is using a stale state. That is definitely a bug;
816
+ * and to demonstrate, we can try the following sequence of actions:
817
+ *
818
+ * 1. Type something that parses in the lambda editor
819
+ * 2. Wait till the parse call finishes, hit F10 (trigger state update)
820
+ * 3. Type something to cause parser error
821
+ * 4. We will see that nothing happens. If we inspect network call, we will see a call returns with parsing error, but
822
+ * the editor is refering to the old state, hence no reporting
823
+ *
824
+ * As such, the most appropriate resolution is to intentionally force remount of lambda editor when user perform a state
825
+ * refresh operations. To do this, we use React `key` field with UUID bound to the state, as the state is recreated, the UUID
826
+ * changes and the editor is recreated. However, this alone is not enough because we use `useMemo` for the debounced
827
+ * transform function, which relies on another value other than the state (i.e. `disabled` flag), the same problem happens
828
+ * as the function goes stale if `disabled` flag changes value. For that, see the implementation trick below (involving refs and disposer)
829
+ *
830
+ * So technically, we don't need to do the force-remount using `key`, but to be cleaner, we prevent other poential bugs, we do it anyway
831
+ * to reset everything.
832
+ */
833
+ key={lambdaEditorState.uuid}
834
+ className={className}
835
+ disabled={disabled}
836
+ lambdaEditorState={lambdaEditorState}
837
+ transformStringToLambda={debouncedTransformStringToLambda}
838
+ expectedType={expectedType}
839
+ matchedExpectedType={matchedExpectedType}
840
+ onExpectedTypeLabelSelect={onExpectedTypeLabelSelect}
841
+ forceBackdrop={forceBackdrop}
842
+ backdropSetter={backdropSetter}
843
+ disableExpansion={disableExpansion}
844
+ forceExpansion={
845
+ disableExpansion !== undefined
846
+ ? !disableExpansion && forceExpansion
847
+ : forceExpansion
848
+ }
849
+ disablePopUp={disablePopUp}
850
+ useBaseTextEditorSettings={useBaseTextEditorSettings}
851
+ hideErrorBar={hideErrorBar}
852
+ onKeyDownEventHandlers={onKeyDownEventHandlers ?? []}
853
+ openInPopUp={openInPopUp}
854
+ onEditorFocusEventHandler={onEditorFocusEventHandler}
855
+ />
856
+ );
857
+ },
858
+ );