@finos/legend-query-builder 4.14.35 → 4.14.36

Sign up to get free protection for your applications and to get access to all the features.
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 =