@finos/legend-query-builder 4.14.35 → 4.14.37

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 (216) hide show
  1. package/lib/__lib__/QueryBuilderDocumentation.d.ts +2 -1
  2. package/lib/__lib__/QueryBuilderDocumentation.d.ts.map +1 -1
  3. package/lib/__lib__/QueryBuilderDocumentation.js +1 -0
  4. package/lib/__lib__/QueryBuilderDocumentation.js.map +1 -1
  5. package/lib/__lib__/QueryBuilderTesting.d.ts +1 -0
  6. package/lib/__lib__/QueryBuilderTesting.d.ts.map +1 -1
  7. package/lib/__lib__/QueryBuilderTesting.js +1 -0
  8. package/lib/__lib__/QueryBuilderTesting.js.map +1 -1
  9. package/lib/components/QueryBuilder.d.ts.map +1 -1
  10. package/lib/components/QueryBuilder.js +55 -19
  11. package/lib/components/QueryBuilder.js.map +1 -1
  12. package/lib/components/QueryBuilderConstantExpressionPanel.d.ts.map +1 -1
  13. package/lib/components/QueryBuilderConstantExpressionPanel.js +30 -13
  14. package/lib/components/QueryBuilderConstantExpressionPanel.js.map +1 -1
  15. package/lib/components/QueryBuilderPropertyExpressionEditor.d.ts.map +1 -1
  16. package/lib/components/QueryBuilderPropertyExpressionEditor.js +2 -1
  17. package/lib/components/QueryBuilderPropertyExpressionEditor.js.map +1 -1
  18. package/lib/components/QueryBuilderSideBar.d.ts +0 -16
  19. package/lib/components/QueryBuilderSideBar.d.ts.map +1 -1
  20. package/lib/components/QueryBuilderSideBar.js +32 -104
  21. package/lib/components/QueryBuilderSideBar.js.map +1 -1
  22. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  23. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +2 -1
  24. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  25. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.d.ts.map +1 -1
  26. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js +50 -5
  27. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js.map +1 -1
  28. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  29. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +2 -1
  30. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  31. package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
  32. package/lib/components/filter/QueryBuilderFilterPanel.js +2 -1
  33. package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
  34. package/lib/components/result/QueryBuilderResultPanel.d.ts.map +1 -1
  35. package/lib/components/result/QueryBuilderResultPanel.js +18 -6
  36. package/lib/components/result/QueryBuilderResultPanel.js.map +1 -1
  37. package/lib/components/shared/BasicValueSpecificationEditor.d.ts.map +1 -1
  38. package/lib/components/shared/BasicValueSpecificationEditor.js +62 -28
  39. package/lib/components/shared/BasicValueSpecificationEditor.js.map +1 -1
  40. package/lib/components/shared/CustomDatePicker.d.ts +1 -0
  41. package/lib/components/shared/CustomDatePicker.d.ts.map +1 -1
  42. package/lib/components/shared/CustomDatePicker.js +13 -9
  43. package/lib/components/shared/CustomDatePicker.js.map +1 -1
  44. package/lib/components/shared/QueryBuilderVariableSelector.d.ts +1 -0
  45. package/lib/components/shared/QueryBuilderVariableSelector.d.ts.map +1 -1
  46. package/lib/components/shared/QueryBuilderVariableSelector.js +2 -2
  47. package/lib/components/shared/QueryBuilderVariableSelector.js.map +1 -1
  48. package/lib/components/workflows/ClassQueryBuilder.d.ts.map +1 -1
  49. package/lib/components/workflows/ClassQueryBuilder.js +19 -16
  50. package/lib/components/workflows/ClassQueryBuilder.js.map +1 -1
  51. package/lib/components/workflows/MappingQueryBuilder.d.ts.map +1 -1
  52. package/lib/components/workflows/MappingQueryBuilder.js +18 -15
  53. package/lib/components/workflows/MappingQueryBuilder.js.map +1 -1
  54. package/lib/components/workflows/ServiceQueryBuilder.d.ts.map +1 -1
  55. package/lib/components/workflows/ServiceQueryBuilder.js +13 -10
  56. package/lib/components/workflows/ServiceQueryBuilder.js.map +1 -1
  57. package/lib/index.css +2 -2
  58. package/lib/index.css.map +1 -1
  59. package/lib/index.d.ts +2 -1
  60. package/lib/index.d.ts.map +1 -1
  61. package/lib/index.js +1 -0
  62. package/lib/index.js.map +1 -1
  63. package/lib/package.json +1 -1
  64. package/lib/stores/QueryBuilderConstantsState.d.ts.map +1 -1
  65. package/lib/stores/QueryBuilderConstantsState.js +2 -1
  66. package/lib/stores/QueryBuilderConstantsState.js.map +1 -1
  67. package/lib/stores/QueryBuilderPropertyEditorState.d.ts +1 -1
  68. package/lib/stores/QueryBuilderPropertyEditorState.d.ts.map +1 -1
  69. package/lib/stores/QueryBuilderPropertyEditorState.js +12 -34
  70. package/lib/stores/QueryBuilderPropertyEditorState.js.map +1 -1
  71. package/lib/stores/QueryBuilderState.d.ts +3 -0
  72. package/lib/stores/QueryBuilderState.d.ts.map +1 -1
  73. package/lib/stores/QueryBuilderState.js +15 -1
  74. package/lib/stores/QueryBuilderState.js.map +1 -1
  75. package/lib/stores/QueryBuilderValueSpecificationHelper.d.ts +2 -1
  76. package/lib/stores/QueryBuilderValueSpecificationHelper.d.ts.map +1 -1
  77. package/lib/stores/QueryBuilderValueSpecificationHelper.js +23 -1
  78. package/lib/stores/QueryBuilderValueSpecificationHelper.js.map +1 -1
  79. package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts +29 -0
  80. package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts.map +1 -1
  81. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.d.ts +2 -0
  82. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.d.ts.map +1 -1
  83. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.js +2 -0
  84. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.js.map +1 -1
  85. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts +2 -0
  86. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts.map +1 -1
  87. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js +6 -0
  88. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js.map +1 -1
  89. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts +2 -0
  90. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts.map +1 -1
  91. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js +15 -0
  92. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js.map +1 -1
  93. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts +3 -0
  94. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts.map +1 -1
  95. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js +42 -3
  96. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
  97. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Contain.d.ts.map +1 -1
  98. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Contain.js +6 -5
  99. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Contain.js.map +1 -1
  100. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_EndWith.d.ts.map +1 -1
  101. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_EndWith.js +6 -5
  102. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_EndWith.js.map +1 -1
  103. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Equal.d.ts.map +1 -1
  104. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Equal.js +8 -37
  105. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Equal.js.map +1 -1
  106. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThan.d.ts.map +1 -1
  107. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThan.js +7 -10
  108. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThan.js.map +1 -1
  109. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_LessThan.d.ts.map +1 -1
  110. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_LessThan.js +7 -10
  111. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_LessThan.js.map +1 -1
  112. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_StartWith.d.ts.map +1 -1
  113. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_StartWith.js +6 -5
  114. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_StartWith.js.map +1 -1
  115. package/lib/stores/filter/QueryBuilderFilterState.d.ts +3 -0
  116. package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
  117. package/lib/stores/filter/QueryBuilderFilterState.js +30 -2
  118. package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
  119. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.d.ts.map +1 -1
  120. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.js +5 -4
  121. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.js.map +1 -1
  122. package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.d.ts.map +1 -1
  123. package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.js +5 -4
  124. package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.js.map +1 -1
  125. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.d.ts.map +1 -1
  126. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.js +7 -35
  127. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.js.map +1 -1
  128. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.d.ts.map +1 -1
  129. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.js +6 -8
  130. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.js.map +1 -1
  131. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.d.ts.map +1 -1
  132. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.js +6 -8
  133. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.js.map +1 -1
  134. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.d.ts.map +1 -1
  135. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.js +6 -8
  136. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.js.map +1 -1
  137. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.d.ts.map +1 -1
  138. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.js +6 -8
  139. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.js.map +1 -1
  140. package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.d.ts.map +1 -1
  141. package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.js +5 -4
  142. package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.js.map +1 -1
  143. package/lib/stores/query-workflow/QueryBuilderWorkFlowState.d.ts +5 -0
  144. package/lib/stores/query-workflow/QueryBuilderWorkFlowState.d.ts.map +1 -1
  145. package/lib/stores/query-workflow/QueryBuilderWorkFlowState.js +7 -0
  146. package/lib/stores/query-workflow/QueryBuilderWorkFlowState.js.map +1 -1
  147. package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts +1 -1
  148. package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts.map +1 -1
  149. package/lib/stores/shared/ValueSpecificationEditorHelper.js +20 -10
  150. package/lib/stores/shared/ValueSpecificationEditorHelper.js.map +1 -1
  151. package/lib/stores/watermark/QueryBuilderWatermarkState.d.ts +0 -2
  152. package/lib/stores/watermark/QueryBuilderWatermarkState.d.ts.map +1 -1
  153. package/lib/stores/watermark/QueryBuilderWatermarkState.js +0 -6
  154. package/lib/stores/watermark/QueryBuilderWatermarkState.js.map +1 -1
  155. package/lib/stores/workflows/MappingQueryBuilderState.d.ts +2 -2
  156. package/lib/stores/workflows/MappingQueryBuilderState.d.ts.map +1 -1
  157. package/lib/stores/workflows/MappingQueryBuilderState.js +2 -1
  158. package/lib/stores/workflows/MappingQueryBuilderState.js.map +1 -1
  159. package/lib/stores/workflows/ServiceQueryBuilderState.d.ts +2 -2
  160. package/lib/stores/workflows/ServiceQueryBuilderState.d.ts.map +1 -1
  161. package/lib/stores/workflows/ServiceQueryBuilderState.js +2 -1
  162. package/lib/stores/workflows/ServiceQueryBuilderState.js.map +1 -1
  163. package/package.json +4 -4
  164. package/src/__lib__/QueryBuilderDocumentation.ts +1 -0
  165. package/src/__lib__/QueryBuilderTesting.ts +1 -0
  166. package/src/components/QueryBuilder.tsx +179 -54
  167. package/src/components/QueryBuilderConstantExpressionPanel.tsx +36 -14
  168. package/src/components/QueryBuilderPropertyExpressionEditor.tsx +2 -0
  169. package/src/components/QueryBuilderSideBar.tsx +138 -339
  170. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +6 -1
  171. package/src/components/fetch-structure/QueryBuilderResultModifierPanel.tsx +139 -1
  172. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +17 -0
  173. package/src/components/filter/QueryBuilderFilterPanel.tsx +6 -0
  174. package/src/components/result/QueryBuilderResultPanel.tsx +63 -6
  175. package/src/components/shared/BasicValueSpecificationEditor.tsx +96 -34
  176. package/src/components/shared/CustomDatePicker.tsx +18 -11
  177. package/src/components/shared/QueryBuilderVariableSelector.tsx +2 -2
  178. package/src/components/workflows/ClassQueryBuilder.tsx +79 -77
  179. package/src/components/workflows/MappingQueryBuilder.tsx +75 -76
  180. package/src/components/workflows/ServiceQueryBuilder.tsx +71 -70
  181. package/src/index.ts +2 -1
  182. package/src/stores/QueryBuilderConstantsState.ts +2 -0
  183. package/src/stores/QueryBuilderPropertyEditorState.ts +15 -53
  184. package/src/stores/QueryBuilderState.ts +23 -1
  185. package/src/stores/QueryBuilderValueSpecificationHelper.ts +32 -0
  186. package/src/stores/QueryBuilder_LegendApplicationPlugin_Extension.ts +39 -0
  187. package/src/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.ts +4 -0
  188. package/src/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.ts +8 -0
  189. package/src/stores/fetch-structure/tds/QueryBuilderTDSState.ts +32 -0
  190. package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +59 -0
  191. package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Contain.ts +5 -5
  192. package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_EndWith.ts +5 -5
  193. package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Equal.ts +10 -69
  194. package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThan.ts +7 -18
  195. package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_LessThan.ts +7 -18
  196. package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_StartWith.ts +5 -5
  197. package/src/stores/filter/QueryBuilderFilterState.ts +48 -2
  198. package/src/stores/filter/operators/QueryBuilderFilterOperator_Contain.ts +5 -5
  199. package/src/stores/filter/operators/QueryBuilderFilterOperator_EndWith.ts +5 -5
  200. package/src/stores/filter/operators/QueryBuilderFilterOperator_Equal.ts +10 -71
  201. package/src/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.ts +6 -14
  202. package/src/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.ts +6 -14
  203. package/src/stores/filter/operators/QueryBuilderFilterOperator_LessThan.ts +6 -14
  204. package/src/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.ts +6 -14
  205. package/src/stores/filter/operators/QueryBuilderFilterOperator_StartWith.ts +5 -5
  206. package/src/stores/query-workflow/QueryBuilderWorkFlowState.ts +10 -0
  207. package/src/stores/shared/ValueSpecificationEditorHelper.ts +32 -16
  208. package/src/stores/watermark/QueryBuilderWatermarkState.ts +0 -7
  209. package/src/stores/workflows/MappingQueryBuilderState.ts +7 -1
  210. package/src/stores/workflows/ServiceQueryBuilderState.ts +6 -1
  211. package/tsconfig.json +0 -1
  212. package/lib/components/watermark/QueryBuilderWatermark.d.ts +0 -22
  213. package/lib/components/watermark/QueryBuilderWatermark.d.ts.map +0 -1
  214. package/lib/components/watermark/QueryBuilderWatermark.js +0 -83
  215. package/lib/components/watermark/QueryBuilderWatermark.js.map +0 -1
  216. package/src/components/watermark/QueryBuilderWatermark.tsx +0 -218
@@ -32,10 +32,15 @@ import {
32
32
  MenuContentItem,
33
33
  ModalFooterButton,
34
34
  InputWithInlineValidation,
35
+ PanelDivider,
36
+ PanelDropZone,
37
+ PanelFormSection,
35
38
  } from '@finos/legend-art';
36
39
  import { SortColumnState } from '../../stores/fetch-structure/tds/QueryResultSetModifierState.js';
37
40
  import {
38
41
  addUniqueEntry,
42
+ clone,
43
+ deepClone,
39
44
  deleteEntry,
40
45
  guaranteeNonNullable,
41
46
  } from '@finos/legend-shared';
@@ -43,9 +48,23 @@ import { useApplicationStore } from '@finos/legend-application';
43
48
  import type { QueryBuilderTDSState } from '../../stores/fetch-structure/tds/QueryBuilderTDSState.js';
44
49
  import type { QueryBuilderTDSColumnState } from '../../stores/fetch-structure/tds/QueryBuilderTDSColumnState.js';
45
50
  import { COLUMN_SORT_TYPE } from '../../graph/QueryBuilderMetaModelConst.js';
46
- import { useEffect, useState } from 'react';
51
+ import { useCallback, useEffect, useState } from 'react';
47
52
  import type { QueryBuilderProjectionColumnState } from '../../stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.js';
48
53
  import { QUERY_BUILDER_TEST_ID } from '../../__lib__/QueryBuilderTesting.js';
54
+ import { VariableSelector } from '../shared/QueryBuilderVariableSelector.js';
55
+ import {
56
+ type ValueSpecification,
57
+ type VariableExpression,
58
+ PrimitiveType,
59
+ Multiplicity,
60
+ areMultiplicitiesEqual,
61
+ } from '@finos/legend-graph';
62
+ import {
63
+ BasicValueSpecificationEditor,
64
+ QUERY_BUILDER_VARIABLE_DND_TYPE,
65
+ type QueryBuilderVariableDragSource,
66
+ } from '../shared/BasicValueSpecificationEditor.js';
67
+ import { useDrop } from 'react-dnd';
49
68
 
50
69
  const ColumnSortEditor = observer(
51
70
  (props: {
@@ -246,6 +265,10 @@ export const QueryResultModifierModal = observer(
246
265
  const [slice, setSlice] = useState<
247
266
  [number | undefined, number | undefined]
248
267
  >(stateSlice ?? [undefined, undefined]);
268
+ const watermarkState = tdsState.queryBuilderState.watermarkState;
269
+ const [watermarkValue, setWatermarkValue] = useState(
270
+ deepClone(watermarkState.value),
271
+ );
249
272
 
250
273
  // Sync temp state with tdsState when modal is opened/closed
251
274
  useEffect(() => {
@@ -253,8 +276,10 @@ export const QueryResultModifierModal = observer(
253
276
  setDistinct(stateDistinct);
254
277
  setLimitResults(stateLimitResults);
255
278
  setSlice(stateSlice ?? [undefined, undefined]);
279
+ setWatermarkValue(deepClone(watermarkState.value));
256
280
  }, [
257
281
  resultSetModifierState.showModal,
282
+ watermarkState.value,
258
283
  stateSortColumns,
259
284
  stateDistinct,
260
285
  stateLimitResults,
@@ -273,6 +298,7 @@ export const QueryResultModifierModal = observer(
273
298
  resultSetModifierState.setSlice(undefined);
274
299
  }
275
300
  resultSetModifierState.setShowModal(false);
301
+ watermarkState.setValue(watermarkValue);
276
302
  };
277
303
 
278
304
  const handleLimitResultsChange: React.ChangeEventHandler<
@@ -321,6 +347,50 @@ export const QueryResultModifierModal = observer(
321
347
  slice[1] !== undefined &&
322
348
  slice[0] >= slice[1]);
323
349
 
350
+ // watermark
351
+ const isParamaterCompatibleWithWaterMark = (
352
+ parameter: VariableExpression,
353
+ ): boolean =>
354
+ PrimitiveType.STRING === parameter.genericType?.value.rawType &&
355
+ areMultiplicitiesEqual(parameter.multiplicity, Multiplicity.ONE);
356
+ const handleDrop = useCallback(
357
+ (item: QueryBuilderVariableDragSource): void => {
358
+ setWatermarkValue(item.variable);
359
+ },
360
+ [setWatermarkValue],
361
+ );
362
+ const toggleWatermark = (): void => {
363
+ if (watermarkValue) {
364
+ setWatermarkValue(undefined);
365
+ } else {
366
+ setWatermarkValue(watermarkState.getDefaultValue());
367
+ }
368
+ };
369
+ const [{ isParameterValueDragOver }, dropTargetConnector] = useDrop<
370
+ QueryBuilderVariableDragSource,
371
+ void,
372
+ { isParameterValueDragOver: boolean }
373
+ >(
374
+ () => ({
375
+ accept: [QUERY_BUILDER_VARIABLE_DND_TYPE],
376
+ drop: (item, monitor): void => {
377
+ if (
378
+ !monitor.didDrop() &&
379
+ // Only allows parameters with muliplicity 1 and type string
380
+ isParamaterCompatibleWithWaterMark(item.variable)
381
+ ) {
382
+ handleDrop(item);
383
+ } // prevent drop event propagation to accomondate for nested DnD
384
+ },
385
+ collect: (monitor) => ({
386
+ isParameterValueDragOver: monitor.isOver({
387
+ shallow: true,
388
+ }),
389
+ }),
390
+ }),
391
+ [handleDrop],
392
+ );
393
+
324
394
  return (
325
395
  <Dialog
326
396
  open={Boolean(resultSetModifierState.showModal)}
@@ -428,6 +498,74 @@ export const QueryResultModifierModal = observer(
428
498
  </div>
429
499
  </div>
430
500
  </div>
501
+ <>
502
+ <PanelFormSection>
503
+ <label className="panel__content__form__section__header__label">
504
+ Watermark
505
+ </label>
506
+ <button
507
+ className={clsx(
508
+ 'panel__content__form__section__toggler',
509
+ 'panel__content__form__section__toggler__btn',
510
+ {
511
+ 'panel__content__form__section__toggler__btn--toggled':
512
+ watermarkValue,
513
+ },
514
+ )}
515
+ onClick={toggleWatermark}
516
+ tabIndex={-1}
517
+ >
518
+ {watermarkValue ? <CheckSquareIcon /> : <SquareIcon />}
519
+ <div className="panel__content__form__section__toggler__prompt">
520
+ Enable Watermark
521
+ </div>
522
+ </button>
523
+ </PanelFormSection>
524
+ {watermarkValue && (
525
+ <>
526
+ <PanelFormSection>
527
+ <div className="query-builder__variable-editor">
528
+ <PanelDropZone
529
+ isDragOver={isParameterValueDragOver}
530
+ dropTargetConnector={dropTargetConnector}
531
+ >
532
+ <BasicValueSpecificationEditor
533
+ valueSpecification={watermarkValue}
534
+ setValueSpecification={(
535
+ val: ValueSpecification,
536
+ ): void => {
537
+ setWatermarkValue(clone(val));
538
+ }}
539
+ graph={
540
+ watermarkState.queryBuilderState.graphManagerState
541
+ .graph
542
+ }
543
+ obseverContext={
544
+ watermarkState.queryBuilderState.observerContext
545
+ }
546
+ typeCheckOption={{
547
+ expectedType: PrimitiveType.STRING,
548
+ }}
549
+ resetValue={() =>
550
+ setWatermarkValue(
551
+ watermarkState.getDefaultValue(),
552
+ )
553
+ }
554
+ isConstant={watermarkState.queryBuilderState.constantState.isValueSpecConstant(
555
+ watermarkValue,
556
+ )}
557
+ />
558
+ </PanelDropZone>
559
+ </div>
560
+ </PanelFormSection>
561
+ <PanelDivider />
562
+ <VariableSelector
563
+ filterBy={isParamaterCompatibleWithWaterMark}
564
+ queryBuilderState={tdsState.queryBuilderState}
565
+ />
566
+ </>
567
+ )}
568
+ </>
431
569
  </div>
432
570
  </ModalBody>
433
571
  <ModalFooter>
@@ -116,6 +116,7 @@ import {
116
116
  QueryBuilderDerivationInfoTooltip,
117
117
  QueryBuilderPropertyInfoTooltip,
118
118
  } from '../shared/QueryBuilderPropertyInfoTooltip.js';
119
+ import { getNameOfValueSpecification } from '../shared/QueryBuilderVariableSelector.js';
119
120
 
120
121
  const QueryBuilderProjectionColumnContextMenu = observer(
121
122
  forwardRef<
@@ -1214,6 +1215,22 @@ export const QueryBuilderTDSPanel = observer(
1214
1215
  </div>
1215
1216
  </div>
1216
1217
  )}
1218
+ {tdsState.queryBuilderState.watermarkState.value && (
1219
+ <div className="query-builder__projection__result-modifier-prompt__group">
1220
+ <div className="query-builder__projection__result-modifier-prompt__group__label">
1221
+ Watermark
1222
+ </div>
1223
+ <div
1224
+ className="query-builder__projection__result-modifier-prompt__group__content"
1225
+ onClick={openResultSetModifierEditor}
1226
+ >
1227
+ {getNameOfValueSpecification(
1228
+ tdsState.queryBuilderState.watermarkState.value,
1229
+ tdsState.queryBuilderState,
1230
+ )}
1231
+ </div>
1232
+ </div>
1233
+ )}
1217
1234
  </div>
1218
1235
  <div className="query-builder__projection__toolbar__actions">
1219
1236
  <button
@@ -111,6 +111,7 @@ import { QueryBuilderTelemetryHelper } from '../../__lib__/QueryBuilderTelemetry
111
111
  import { getPropertyChainName } from '../../stores/QueryBuilderPropertyEditorState.js';
112
112
  import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '../../graph/QueryBuilderMetaModelConst.js';
113
113
  import { buildPropertyExpressionChain } from '../../stores/QueryBuilderValueSpecificationBuilderHelper.js';
114
+ import { QueryBuilderPanelIssueCountBadge } from '../shared/QueryBuilderPanelIssueCountBadge.js';
114
115
 
115
116
  const isCollectionProperty = (
116
117
  propertyExpression: AbstractPropertyExpression,
@@ -1479,6 +1480,11 @@ export const QueryBuilderFilterPanel = observer(
1479
1480
  <div className="panel__header">
1480
1481
  <div className="panel__header__title">
1481
1482
  <div className="panel__header__title__label">filter</div>
1483
+ {filterState.allValidationIssues.length !== 0 && (
1484
+ <QueryBuilderPanelIssueCountBadge
1485
+ issues={filterState.allValidationIssues}
1486
+ />
1487
+ )}
1482
1488
  </div>
1483
1489
 
1484
1490
  <div className="panel__header__actions">
@@ -37,6 +37,12 @@ import {
37
37
  PanelDivider,
38
38
  SquareIcon,
39
39
  CheckSquareIcon,
40
+ MenuContentItemIcon,
41
+ MenuContentItemLabel,
42
+ ChartIcon,
43
+ CsvIcon,
44
+ DebugIcon,
45
+ ReportIcon,
40
46
  } from '@finos/legend-art';
41
47
  import { observer } from 'mobx-react-lite';
42
48
  import { flowResult } from 'mobx';
@@ -306,6 +312,28 @@ export const QueryBuilderResultPanel = observer(
306
312
  !queryBuilderState.isLocalModeEnabled,
307
313
  );
308
314
  };
315
+
316
+ const extraExportMenuContentItems = applicationStore.pluginManager
317
+ .getApplicationPlugins()
318
+ .flatMap(
319
+ (plugin) =>
320
+ (
321
+ plugin as QueryBuilder_LegendApplicationPlugin_Extension
322
+ ).getExtraQueryBuilderExportMenuActionConfigurations?.() ?? [],
323
+ )
324
+ .map((item) => (
325
+ <MenuContentItem
326
+ key={item.key}
327
+ title={item.title ?? ''}
328
+ onClick={() => {
329
+ item.onClick(queryBuilderState);
330
+ }}
331
+ >
332
+ {item.icon && <MenuContentItemIcon>{item.icon}</MenuContentItemIcon>}
333
+ <MenuContentItemLabel>{item.label}</MenuContentItemLabel>
334
+ </MenuContentItem>
335
+ ));
336
+
309
337
  return (
310
338
  <div
311
339
  data-testid={QUERY_BUILDER_TEST_ID.QUERY_BUILDER_RESULT_PANEL}
@@ -490,14 +518,22 @@ export const QueryBuilderResultPanel = observer(
490
518
  onClick={generatePlan}
491
519
  disabled={isRunQueryDisabled}
492
520
  >
493
- Generate Plan
521
+ <MenuContentItemIcon>
522
+ <ReportIcon />
523
+ </MenuContentItemIcon>
524
+ <MenuContentItemLabel>
525
+ Generate Plan
526
+ </MenuContentItemLabel>
494
527
  </MenuContentItem>
495
528
  <MenuContentItem
496
529
  className="btn__dropdown-combo__option"
497
530
  onClick={debugPlanGeneration}
498
531
  disabled={isRunQueryDisabled}
499
532
  >
500
- Debug
533
+ <MenuContentItemIcon>
534
+ <DebugIcon />
535
+ </MenuContentItemIcon>
536
+ <MenuContentItemLabel>Debug</MenuContentItemLabel>
501
537
  </MenuContentItem>
502
538
  </MenuContent>
503
539
  }
@@ -522,14 +558,15 @@ export const QueryBuilderResultPanel = observer(
522
558
  ).map((format) => (
523
559
  <MenuContentItem
524
560
  key={format}
525
- className="query-builder__result__export__dropdown__menu__item"
526
561
  onClick={(): void => confirmExport(format)}
527
562
  >
528
- {format}
563
+ <MenuContentItemIcon>
564
+ <CsvIcon />
565
+ </MenuContentItemIcon>
566
+ <MenuContentItemLabel>{format}</MenuContentItemLabel>
529
567
  </MenuContentItem>
530
568
  ))}
531
569
  <MenuContentItem
532
- className="query-builder__result__export__dropdown__menu__item"
533
570
  onClick={(): void =>
534
571
  resultState.setIsQueryUsageViewerOpened(true)
535
572
  }
@@ -538,8 +575,12 @@ export const QueryBuilderResultPanel = observer(
538
575
  !isExtraQueryUsageOptionsConfigured
539
576
  }
540
577
  >
541
- Query Code Snippets...
578
+ <MenuContentItemIcon>
579
+ <ChartIcon />
580
+ </MenuContentItemIcon>
581
+ <MenuContentItemLabel>Others...</MenuContentItemLabel>
542
582
  </MenuContentItem>
583
+ {extraExportMenuContentItems}
543
584
  </MenuContent>
544
585
  }
545
586
  menuProps={{
@@ -558,6 +599,22 @@ export const QueryBuilderResultPanel = observer(
558
599
  {resultState.isQueryUsageViewerOpened && (
559
600
  <QueryUsageViewer resultState={resultState} />
560
601
  )}
602
+ {applicationStore.pluginManager
603
+ .getApplicationPlugins()
604
+ .flatMap(
605
+ (plugin) =>
606
+ (
607
+ plugin as QueryBuilder_LegendApplicationPlugin_Extension
608
+ ).getExtraQueryBuilderExportMenuActionConfigurations?.() ??
609
+ [],
610
+ )
611
+ .map((item) => (
612
+ <div key={item.key}>
613
+ {item.renderExtraComponent
614
+ ? item.renderExtraComponent(queryBuilderState)
615
+ : undefined}
616
+ </div>
617
+ ))}
561
618
  </div>
562
619
  </div>
563
620
  <PanelContent>
@@ -33,6 +33,7 @@ import {
33
33
  BasePopover,
34
34
  PanelFormSection,
35
35
  CalculateIcon,
36
+ InputWithInlineValidation,
36
37
  } from '@finos/legend-art';
37
38
  import {
38
39
  type Enum,
@@ -67,6 +68,7 @@ import {
67
68
  parseCSVString,
68
69
  guaranteeIsNumber,
69
70
  csvStringify,
71
+ guaranteeType,
70
72
  } from '@finos/legend-shared';
71
73
  import { flowResult } from 'mobx';
72
74
  import { observer } from 'mobx-react-lite';
@@ -83,7 +85,10 @@ import {
83
85
  } from '../../stores/shared/ValueSpecificationModifierHelper.js';
84
86
  import { CustomDatePicker } from './CustomDatePicker.js';
85
87
  import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '../../graph/QueryBuilderMetaModelConst.js';
86
- import { simplifyValueExpression } from '../../stores/QueryBuilderValueSpecificationHelper.js';
88
+ import {
89
+ isValidInstanceValue,
90
+ simplifyValueExpression,
91
+ } from '../../stores/QueryBuilderValueSpecificationHelper.js';
87
92
  import { evaluate } from 'mathjs';
88
93
  import { isUsedDateFunctionSupportedInFormMode } from '../../stores/QueryBuilderStateBuilder.js';
89
94
 
@@ -240,7 +245,7 @@ const StringPrimitiveInstanceValueEditor = observer(
240
245
  } = props;
241
246
  const useSelector = Boolean(selectorConfig);
242
247
  const applicationStore = useApplicationStore();
243
- const value = valueSpecification.values[0] as string;
248
+ const value = valueSpecification.values[0] as string | null;
244
249
  const updateValueSpec = (val: string): void => {
245
250
  instanceValue_setValue(valueSpecification, val, 0, obseverContext);
246
251
  setValueSpecification(valueSpecification);
@@ -295,8 +300,8 @@ const StringPrimitiveInstanceValueEditor = observer(
295
300
  className="value-spec-editor__enum-selector"
296
301
  options={queryOptions}
297
302
  onChange={changeValue}
298
- value={selectedValue}
299
- inputValue={value}
303
+ value={selectedValue.label === '' ? '' : selectedValue}
304
+ inputValue={value ?? ''}
300
305
  onInputChange={handleInputChange}
301
306
  darkMode={
302
307
  !applicationStore.layoutService
@@ -308,15 +313,22 @@ const StringPrimitiveInstanceValueEditor = observer(
308
313
  components={{
309
314
  DropdownIndicator: null,
310
315
  }}
316
+ hasError={!isValidInstanceValue(valueSpecification)}
317
+ placeholder={value === '' ? '(empty)' : undefined}
311
318
  />
312
319
  ) : (
313
- <input
320
+ <InputWithInlineValidation
314
321
  className="panel__content__form__section__input value-spec-editor__input"
315
322
  spellCheck={false}
316
- value={value}
323
+ value={value ?? ''}
317
324
  placeholder={value === '' ? '(empty)' : undefined}
318
325
  onChange={changeInputValue}
319
326
  ref={ref}
327
+ error={
328
+ !isValidInstanceValue(valueSpecification)
329
+ ? 'Invalid String value'
330
+ : undefined
331
+ }
320
332
  />
321
333
  )}
322
334
  <button
@@ -397,26 +409,37 @@ const NumberPrimitiveInstanceValueEditor = observer(
397
409
  obseverContext,
398
410
  } = props;
399
411
  const [value, setValue] = useState(
400
- (valueSpecification.values[0] as number).toString(),
412
+ valueSpecification.values[0] === null
413
+ ? ''
414
+ : (valueSpecification.values[0] as number).toString(),
401
415
  );
402
416
  const inputRef = useRef<HTMLInputElement>(null);
403
417
  useImperativeHandle(ref, () => inputRef.current as HTMLInputElement, []);
404
- const numericValue = isInteger
405
- ? Number.parseInt(Number(value).toString(), 10)
406
- : Number(value);
418
+ const numericValue = value
419
+ ? isInteger
420
+ ? Number.parseInt(Number(value).toString(), 10)
421
+ : Number(value)
422
+ : null;
407
423
 
408
424
  const updateValueSpecIfValid = (val: string): void => {
409
- const parsedValue = isInteger
410
- ? Number.parseInt(Number(val).toString(), 10)
411
- : Number(val);
412
- if (!isNaN(parsedValue) && parsedValue !== valueSpecification.values[0]) {
413
- instanceValue_setValue(
414
- valueSpecification,
415
- parsedValue,
416
- 0,
417
- obseverContext,
418
- );
419
- setValueSpecification(valueSpecification);
425
+ if (val) {
426
+ const parsedValue = isInteger
427
+ ? Number.parseInt(Number(val).toString(), 10)
428
+ : Number(val);
429
+ if (
430
+ !isNaN(parsedValue) &&
431
+ parsedValue !== valueSpecification.values[0]
432
+ ) {
433
+ instanceValue_setValue(
434
+ valueSpecification,
435
+ parsedValue,
436
+ 0,
437
+ obseverContext,
438
+ );
439
+ setValueSpecification(valueSpecification);
440
+ }
441
+ } else {
442
+ resetValue();
420
443
  }
421
444
  };
422
445
 
@@ -429,20 +452,29 @@ const NumberPrimitiveInstanceValueEditor = observer(
429
452
 
430
453
  // Support expression evaluation
431
454
  const calculateExpression = (): void => {
432
- if (isNaN(numericValue)) {
455
+ if (numericValue !== null && isNaN(numericValue)) {
456
+ // If the value is not a number, try to evaluate it as an expression
433
457
  try {
434
458
  const calculatedValue = guaranteeIsNumber(evaluate(value));
435
459
  updateValueSpecIfValid(calculatedValue.toString());
436
460
  setValue(calculatedValue.toString());
437
461
  } catch {
438
- updateValueSpecIfValid(
439
- (valueSpecification.values[0] as number).toString(),
440
- );
441
- setValue((valueSpecification.values[0] as number).toString());
462
+ // If we fail to evaluate the expression, we just keep the previous value
463
+ const prevValue =
464
+ valueSpecification.values[0] !== null &&
465
+ valueSpecification.values[0] !== undefined
466
+ ? valueSpecification.values[0].toString()
467
+ : '';
468
+ updateValueSpecIfValid(prevValue);
469
+ setValue(prevValue);
442
470
  }
443
- } else {
471
+ } else if (numericValue !== null) {
472
+ // If numericValue is a number, update the value spec
444
473
  updateValueSpecIfValid(numericValue.toString());
445
474
  setValue(numericValue.toString());
475
+ } else {
476
+ // If numericValue is null, reset the value spec
477
+ resetValue();
446
478
  }
447
479
  };
448
480
 
@@ -457,10 +489,15 @@ const NumberPrimitiveInstanceValueEditor = observer(
457
489
 
458
490
  useEffect(() => {
459
491
  if (
492
+ numericValue !== null &&
460
493
  !isNaN(numericValue) &&
461
494
  numericValue !== valueSpecification.values[0]
462
495
  ) {
463
- setValue((valueSpecification.values[0] as number).toString());
496
+ const valueFromValueSpec =
497
+ valueSpecification.values[0] !== null
498
+ ? (valueSpecification.values[0] as number).toString()
499
+ : '';
500
+ setValue(valueFromValueSpec);
464
501
  }
465
502
  }, [numericValue, valueSpecification]);
466
503
 
@@ -469,7 +506,15 @@ const NumberPrimitiveInstanceValueEditor = observer(
469
506
  <div className="value-spec-editor__number__input-container">
470
507
  <input
471
508
  ref={inputRef}
472
- className="panel__content__form__section__input value-spec-editor__input value-spec-editor__number__input"
509
+ className={clsx(
510
+ 'panel__content__form__section__input',
511
+ 'value-spec-editor__input',
512
+ 'value-spec-editor__number__input',
513
+ {
514
+ 'value-spec-editor__number__input--error':
515
+ !isValidInstanceValue(valueSpecification),
516
+ },
517
+ )}
473
518
  spellCheck={false}
474
519
  type="text" // NOTE: we leave this as text so that we can support expression evaluation
475
520
  inputMode="numeric"
@@ -517,9 +562,15 @@ const EnumValueInstanceValueEditor = observer(
517
562
  obseverContext,
518
563
  } = props;
519
564
  const applicationStore = useApplicationStore();
520
- const enumValueRef = guaranteeNonNullable(valueSpecification.values[0]);
521
- const enumValue = enumValueRef.value;
522
- const options = enumValue._OWNER.values.map((value) => ({
565
+ const enumType = guaranteeType(
566
+ valueSpecification.genericType?.value.rawType,
567
+ Enumeration,
568
+ );
569
+ const enumValue =
570
+ valueSpecification.values[0] === undefined
571
+ ? null
572
+ : valueSpecification.values[0].value;
573
+ const options = enumType.values.map((value) => ({
523
574
  label: value.name,
524
575
  value: value,
525
576
  }));
@@ -539,10 +590,12 @@ const EnumValueInstanceValueEditor = observer(
539
590
  className="value-spec-editor__enum-selector"
540
591
  options={options}
541
592
  onChange={changeValue}
542
- value={{ value: enumValue, label: enumValue.name }}
593
+ value={enumValue ? { value: enumValue, label: enumValue.name } : null}
543
594
  darkMode={
544
595
  !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled
545
596
  }
597
+ hasError={!isValidInstanceValue(valueSpecification)}
598
+ placeholder="Select value"
546
599
  />
547
600
  <button
548
601
  className="value-spec-editor__reset-btn"
@@ -899,7 +952,12 @@ const CollectionValueInstanceValueEditor = observer(
899
952
  onClick={enableEdit}
900
953
  title="Click to edit"
901
954
  >
902
- <div className="value-spec-editor__list-editor__preview">
955
+ <div
956
+ className={clsx('value-spec-editor__list-editor__preview', {
957
+ 'value-spec-editor__list-editor__preview--error':
958
+ !isValidInstanceValue(valueSpecification),
959
+ })}
960
+ >
903
961
  {previewText}
904
962
  </div>
905
963
  <button className="value-spec-editor__list-editor__edit-icon">
@@ -941,6 +999,10 @@ const DateInstanceValueEditor = observer(
941
999
  observerContext={obseverContext}
942
1000
  typeCheckOption={typeCheckOption}
943
1001
  setValueSpecification={setValueSpecification}
1002
+ hasError={
1003
+ valueSpecification instanceof PrimitiveInstanceValue &&
1004
+ !isValidInstanceValue(valueSpecification)
1005
+ }
944
1006
  />
945
1007
  <button
946
1008
  className="value-spec-editor__reset-btn"