@finos/legend-query-builder 4.14.35 → 4.14.36

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 (207) hide show
  1. package/lib/__lib__/QueryBuilderTesting.d.ts +1 -0
  2. package/lib/__lib__/QueryBuilderTesting.d.ts.map +1 -1
  3. package/lib/__lib__/QueryBuilderTesting.js +1 -0
  4. package/lib/__lib__/QueryBuilderTesting.js.map +1 -1
  5. package/lib/components/QueryBuilder.d.ts.map +1 -1
  6. package/lib/components/QueryBuilder.js +37 -17
  7. package/lib/components/QueryBuilder.js.map +1 -1
  8. package/lib/components/QueryBuilderConstantExpressionPanel.d.ts.map +1 -1
  9. package/lib/components/QueryBuilderConstantExpressionPanel.js +30 -13
  10. package/lib/components/QueryBuilderConstantExpressionPanel.js.map +1 -1
  11. package/lib/components/QueryBuilderPropertyExpressionEditor.d.ts.map +1 -1
  12. package/lib/components/QueryBuilderPropertyExpressionEditor.js +2 -1
  13. package/lib/components/QueryBuilderPropertyExpressionEditor.js.map +1 -1
  14. package/lib/components/QueryBuilderSideBar.d.ts +0 -16
  15. package/lib/components/QueryBuilderSideBar.d.ts.map +1 -1
  16. package/lib/components/QueryBuilderSideBar.js +32 -104
  17. package/lib/components/QueryBuilderSideBar.js.map +1 -1
  18. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  19. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +2 -1
  20. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  21. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.d.ts.map +1 -1
  22. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js +50 -5
  23. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js.map +1 -1
  24. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  25. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +2 -1
  26. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  27. package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
  28. package/lib/components/filter/QueryBuilderFilterPanel.js +2 -1
  29. package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
  30. package/lib/components/shared/BasicValueSpecificationEditor.d.ts.map +1 -1
  31. package/lib/components/shared/BasicValueSpecificationEditor.js +62 -28
  32. package/lib/components/shared/BasicValueSpecificationEditor.js.map +1 -1
  33. package/lib/components/shared/CustomDatePicker.d.ts +1 -0
  34. package/lib/components/shared/CustomDatePicker.d.ts.map +1 -1
  35. package/lib/components/shared/CustomDatePicker.js +13 -9
  36. package/lib/components/shared/CustomDatePicker.js.map +1 -1
  37. package/lib/components/shared/QueryBuilderVariableSelector.d.ts +1 -0
  38. package/lib/components/shared/QueryBuilderVariableSelector.d.ts.map +1 -1
  39. package/lib/components/shared/QueryBuilderVariableSelector.js +2 -2
  40. package/lib/components/shared/QueryBuilderVariableSelector.js.map +1 -1
  41. package/lib/components/workflows/ClassQueryBuilder.d.ts.map +1 -1
  42. package/lib/components/workflows/ClassQueryBuilder.js +19 -16
  43. package/lib/components/workflows/ClassQueryBuilder.js.map +1 -1
  44. package/lib/components/workflows/MappingQueryBuilder.d.ts.map +1 -1
  45. package/lib/components/workflows/MappingQueryBuilder.js +18 -15
  46. package/lib/components/workflows/MappingQueryBuilder.js.map +1 -1
  47. package/lib/components/workflows/ServiceQueryBuilder.d.ts.map +1 -1
  48. package/lib/components/workflows/ServiceQueryBuilder.js +13 -10
  49. package/lib/components/workflows/ServiceQueryBuilder.js.map +1 -1
  50. package/lib/index.css +2 -2
  51. package/lib/index.css.map +1 -1
  52. package/lib/index.d.ts +2 -1
  53. package/lib/index.d.ts.map +1 -1
  54. package/lib/index.js +1 -0
  55. package/lib/index.js.map +1 -1
  56. package/lib/package.json +1 -1
  57. package/lib/stores/QueryBuilderConstantsState.d.ts.map +1 -1
  58. package/lib/stores/QueryBuilderConstantsState.js +2 -1
  59. package/lib/stores/QueryBuilderConstantsState.js.map +1 -1
  60. package/lib/stores/QueryBuilderPropertyEditorState.d.ts +1 -1
  61. package/lib/stores/QueryBuilderPropertyEditorState.d.ts.map +1 -1
  62. package/lib/stores/QueryBuilderPropertyEditorState.js +12 -34
  63. package/lib/stores/QueryBuilderPropertyEditorState.js.map +1 -1
  64. package/lib/stores/QueryBuilderState.d.ts +3 -0
  65. package/lib/stores/QueryBuilderState.d.ts.map +1 -1
  66. package/lib/stores/QueryBuilderState.js +15 -1
  67. package/lib/stores/QueryBuilderState.js.map +1 -1
  68. package/lib/stores/QueryBuilderValueSpecificationHelper.d.ts +2 -1
  69. package/lib/stores/QueryBuilderValueSpecificationHelper.d.ts.map +1 -1
  70. package/lib/stores/QueryBuilderValueSpecificationHelper.js +23 -1
  71. package/lib/stores/QueryBuilderValueSpecificationHelper.js.map +1 -1
  72. package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts +13 -0
  73. package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts.map +1 -1
  74. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.d.ts +2 -0
  75. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.d.ts.map +1 -1
  76. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.js +2 -0
  77. package/lib/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.js.map +1 -1
  78. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts +2 -0
  79. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.d.ts.map +1 -1
  80. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js +6 -0
  81. package/lib/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.js.map +1 -1
  82. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts +2 -0
  83. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts.map +1 -1
  84. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js +15 -0
  85. package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js.map +1 -1
  86. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts +3 -0
  87. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts.map +1 -1
  88. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js +42 -3
  89. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
  90. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Contain.d.ts.map +1 -1
  91. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Contain.js +6 -5
  92. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Contain.js.map +1 -1
  93. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_EndWith.d.ts.map +1 -1
  94. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_EndWith.js +6 -5
  95. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_EndWith.js.map +1 -1
  96. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Equal.d.ts.map +1 -1
  97. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Equal.js +8 -37
  98. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Equal.js.map +1 -1
  99. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThan.d.ts.map +1 -1
  100. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThan.js +7 -10
  101. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThan.js.map +1 -1
  102. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_LessThan.d.ts.map +1 -1
  103. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_LessThan.js +7 -10
  104. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_LessThan.js.map +1 -1
  105. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_StartWith.d.ts.map +1 -1
  106. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_StartWith.js +6 -5
  107. package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_StartWith.js.map +1 -1
  108. package/lib/stores/filter/QueryBuilderFilterState.d.ts +3 -0
  109. package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
  110. package/lib/stores/filter/QueryBuilderFilterState.js +30 -2
  111. package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
  112. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.d.ts.map +1 -1
  113. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.js +5 -4
  114. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.js.map +1 -1
  115. package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.d.ts.map +1 -1
  116. package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.js +5 -4
  117. package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.js.map +1 -1
  118. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.d.ts.map +1 -1
  119. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.js +7 -35
  120. package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.js.map +1 -1
  121. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.d.ts.map +1 -1
  122. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.js +6 -8
  123. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.js.map +1 -1
  124. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.d.ts.map +1 -1
  125. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.js +6 -8
  126. package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.js.map +1 -1
  127. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.d.ts.map +1 -1
  128. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.js +6 -8
  129. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.js.map +1 -1
  130. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.d.ts.map +1 -1
  131. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.js +6 -8
  132. package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.js.map +1 -1
  133. package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.d.ts.map +1 -1
  134. package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.js +5 -4
  135. package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.js.map +1 -1
  136. package/lib/stores/query-workflow/QueryBuilderWorkFlowState.d.ts +5 -0
  137. package/lib/stores/query-workflow/QueryBuilderWorkFlowState.d.ts.map +1 -1
  138. package/lib/stores/query-workflow/QueryBuilderWorkFlowState.js +7 -0
  139. package/lib/stores/query-workflow/QueryBuilderWorkFlowState.js.map +1 -1
  140. package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts +1 -1
  141. package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts.map +1 -1
  142. package/lib/stores/shared/ValueSpecificationEditorHelper.js +20 -10
  143. package/lib/stores/shared/ValueSpecificationEditorHelper.js.map +1 -1
  144. package/lib/stores/watermark/QueryBuilderWatermarkState.d.ts +0 -2
  145. package/lib/stores/watermark/QueryBuilderWatermarkState.d.ts.map +1 -1
  146. package/lib/stores/watermark/QueryBuilderWatermarkState.js +0 -6
  147. package/lib/stores/watermark/QueryBuilderWatermarkState.js.map +1 -1
  148. package/lib/stores/workflows/MappingQueryBuilderState.d.ts +2 -2
  149. package/lib/stores/workflows/MappingQueryBuilderState.d.ts.map +1 -1
  150. package/lib/stores/workflows/MappingQueryBuilderState.js +2 -1
  151. package/lib/stores/workflows/MappingQueryBuilderState.js.map +1 -1
  152. package/lib/stores/workflows/ServiceQueryBuilderState.d.ts +2 -2
  153. package/lib/stores/workflows/ServiceQueryBuilderState.d.ts.map +1 -1
  154. package/lib/stores/workflows/ServiceQueryBuilderState.js +2 -1
  155. package/lib/stores/workflows/ServiceQueryBuilderState.js.map +1 -1
  156. package/package.json +4 -4
  157. package/src/__lib__/QueryBuilderTesting.ts +1 -0
  158. package/src/components/QueryBuilder.tsx +89 -46
  159. package/src/components/QueryBuilderConstantExpressionPanel.tsx +36 -14
  160. package/src/components/QueryBuilderPropertyExpressionEditor.tsx +2 -0
  161. package/src/components/QueryBuilderSideBar.tsx +138 -339
  162. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +6 -1
  163. package/src/components/fetch-structure/QueryBuilderResultModifierPanel.tsx +139 -1
  164. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +17 -0
  165. package/src/components/filter/QueryBuilderFilterPanel.tsx +6 -0
  166. package/src/components/shared/BasicValueSpecificationEditor.tsx +96 -34
  167. package/src/components/shared/CustomDatePicker.tsx +18 -11
  168. package/src/components/shared/QueryBuilderVariableSelector.tsx +2 -2
  169. package/src/components/workflows/ClassQueryBuilder.tsx +79 -77
  170. package/src/components/workflows/MappingQueryBuilder.tsx +75 -76
  171. package/src/components/workflows/ServiceQueryBuilder.tsx +71 -70
  172. package/src/index.ts +2 -1
  173. package/src/stores/QueryBuilderConstantsState.ts +2 -0
  174. package/src/stores/QueryBuilderPropertyEditorState.ts +15 -53
  175. package/src/stores/QueryBuilderState.ts +23 -1
  176. package/src/stores/QueryBuilderValueSpecificationHelper.ts +32 -0
  177. package/src/stores/QueryBuilder_LegendApplicationPlugin_Extension.ts +18 -0
  178. package/src/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.ts +4 -0
  179. package/src/stores/fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeState.ts +8 -0
  180. package/src/stores/fetch-structure/tds/QueryBuilderTDSState.ts +32 -0
  181. package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +59 -0
  182. package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Contain.ts +5 -5
  183. package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_EndWith.ts +5 -5
  184. package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_Equal.ts +10 -69
  185. package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_GreaterThan.ts +7 -18
  186. package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_LessThan.ts +7 -18
  187. package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_StartWith.ts +5 -5
  188. package/src/stores/filter/QueryBuilderFilterState.ts +48 -2
  189. package/src/stores/filter/operators/QueryBuilderFilterOperator_Contain.ts +5 -5
  190. package/src/stores/filter/operators/QueryBuilderFilterOperator_EndWith.ts +5 -5
  191. package/src/stores/filter/operators/QueryBuilderFilterOperator_Equal.ts +10 -71
  192. package/src/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.ts +6 -14
  193. package/src/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.ts +6 -14
  194. package/src/stores/filter/operators/QueryBuilderFilterOperator_LessThan.ts +6 -14
  195. package/src/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.ts +6 -14
  196. package/src/stores/filter/operators/QueryBuilderFilterOperator_StartWith.ts +5 -5
  197. package/src/stores/query-workflow/QueryBuilderWorkFlowState.ts +10 -0
  198. package/src/stores/shared/ValueSpecificationEditorHelper.ts +32 -16
  199. package/src/stores/watermark/QueryBuilderWatermarkState.ts +0 -7
  200. package/src/stores/workflows/MappingQueryBuilderState.ts +7 -1
  201. package/src/stores/workflows/ServiceQueryBuilderState.ts +6 -1
  202. package/tsconfig.json +0 -1
  203. package/lib/components/watermark/QueryBuilderWatermark.d.ts +0 -22
  204. package/lib/components/watermark/QueryBuilderWatermark.d.ts.map +0 -1
  205. package/lib/components/watermark/QueryBuilderWatermark.js +0 -83
  206. package/lib/components/watermark/QueryBuilderWatermark.js.map +0 -1
  207. 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">
@@ -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"
@@ -19,6 +19,7 @@ import {
19
19
  BasePopover,
20
20
  BaseRadioGroup,
21
21
  CustomSelectorInput,
22
+ clsx,
22
23
  } from '@finos/legend-art';
23
24
  import {
24
25
  type PureModel,
@@ -733,11 +734,13 @@ export const buildDatePickerOption = (
733
734
  CUSTOM_DATE_PICKER_OPTION.LATEST_DATE,
734
735
  )
735
736
  : new DatePickerOption(
736
- valueSpecification.values[0] as string,
737
- valueSpecification.genericType.value.rawType.path ===
738
- PRIMITIVE_TYPE.DATETIME
739
- ? CUSTOM_DATE_PICKER_OPTION.ABSOLUTE_TIME
740
- : CUSTOM_DATE_PICKER_OPTION.ABSOLUTE_DATE,
737
+ (valueSpecification.values[0] ?? '') as string,
738
+ valueSpecification.values[0] === null
739
+ ? ''
740
+ : valueSpecification.genericType.value.rawType.path ===
741
+ PRIMITIVE_TYPE.DATETIME
742
+ ? CUSTOM_DATE_PICKER_OPTION.ABSOLUTE_TIME
743
+ : CUSTOM_DATE_PICKER_OPTION.ABSOLUTE_DATE,
741
744
  );
742
745
  }
743
746
  };
@@ -760,7 +763,7 @@ const AbsoluteDateValueSpecificationEditor: React.FC<{
760
763
  const absoluteDateValue =
761
764
  valueSpecification instanceof SimpleFunctionExpression
762
765
  ? ''
763
- : (valueSpecification.values[0] as string);
766
+ : (valueSpecification.values[0] as string | null);
764
767
  const updateAbsoluteDateValue: React.ChangeEventHandler<HTMLInputElement> = (
765
768
  event,
766
769
  ) => {
@@ -812,7 +815,7 @@ const AbsoluteDateValueSpecificationEditor: React.FC<{
812
815
  className="panel__content__form__section__input value-spec-editor__date-picker__absolute-date__input input--dark"
813
816
  type="date"
814
817
  spellCheck={false}
815
- value={absoluteDateValue}
818
+ value={absoluteDateValue ?? ''}
816
819
  onChange={updateAbsoluteDateValue}
817
820
  />
818
821
  </div>
@@ -837,7 +840,7 @@ const AbsoluteTimeValueSpecificationEditor: React.FC<{
837
840
  const absoluteTimeValue =
838
841
  valueSpecification instanceof SimpleFunctionExpression
839
842
  ? ''
840
- : (valueSpecification.values[0] as string);
843
+ : (valueSpecification.values[0] as string | null);
841
844
  const updateAbsoluteTimeValue: React.ChangeEventHandler<HTMLInputElement> = (
842
845
  event,
843
846
  ) => {
@@ -893,7 +896,7 @@ const AbsoluteTimeValueSpecificationEditor: React.FC<{
893
896
  // See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local#step
894
897
  step="1"
895
898
  spellCheck={false}
896
- value={absoluteTimeValue}
899
+ value={absoluteTimeValue ?? ''}
897
900
  onChange={updateAbsoluteTimeValue}
898
901
  />
899
902
  </div>
@@ -1225,6 +1228,7 @@ export const CustomDatePicker: React.FC<{
1225
1228
  valueSpecification: PrimitiveInstanceValue | SimpleFunctionExpression;
1226
1229
  graph: PureModel;
1227
1230
  observerContext: ObserverContext;
1231
+ hasError?: boolean;
1228
1232
  typeCheckOption: {
1229
1233
  expectedType: Type;
1230
1234
  /**
@@ -1247,6 +1251,7 @@ export const CustomDatePicker: React.FC<{
1247
1251
  setValueSpecification,
1248
1252
  graph,
1249
1253
  observerContext,
1254
+ hasError,
1250
1255
  typeCheckOption,
1251
1256
  } = props;
1252
1257
  const applicationStore = useApplicationStore();
@@ -1404,11 +1409,13 @@ export const CustomDatePicker: React.FC<{
1404
1409
  return (
1405
1410
  <>
1406
1411
  <button
1407
- className="value-spec-editor__date-picker__trigger"
1412
+ className={clsx('value-spec-editor__date-picker__trigger', {
1413
+ 'value-spec-editor__date-picker__trigger--error': hasError,
1414
+ })}
1408
1415
  title="Click to edit and pick from more date options"
1409
1416
  onClick={openCustomDatePickerPopover}
1410
1417
  >
1411
- {datePickerOption.label}
1418
+ {datePickerOption.label || 'Select value'}
1412
1419
  </button>
1413
1420
  <BasePopover
1414
1421
  open={Boolean(anchorEl)}
@@ -48,7 +48,7 @@ import { forwardRef, useState } from 'react';
48
48
 
49
49
  const CALCULATED = '(calculated)';
50
50
 
51
- const getNameOfValue = (
51
+ export const getNameOfValueSpecification = (
52
52
  value: ValueSpecification,
53
53
  queryBuilderState: QueryBuilderState,
54
54
  ): string | undefined => {
@@ -143,7 +143,7 @@ export const VariableViewer = observer(
143
143
  const onContextMenuClose = (): void => setIsSelectedFromContextMenu(false);
144
144
  const isConstant = Boolean(value);
145
145
  const constantValueString = value?.val
146
- ? getNameOfValue(value.val, queryBuilderState)
146
+ ? getNameOfValueSpecification(value.val, queryBuilderState)
147
147
  : undefined;
148
148
  const name = variable.name;
149
149
  const variableTypeName =