@finos/legend-query-builder 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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 +10 -7
  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} +7 -6
  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 +7 -6
  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 +13 -13
  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 +9 -9
  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} +12 -5
  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 +7 -6
  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 +16 -19
  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
+ );