@finos/legend-application-query 5.0.1 → 5.2.1

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 (210) hide show
  1. package/lib/application/LegendQueryApplicationConfig.d.ts +17 -1
  2. package/lib/application/LegendQueryApplicationConfig.d.ts.map +1 -1
  3. package/lib/application/LegendQueryApplicationConfig.js +23 -1
  4. package/lib/application/LegendQueryApplicationConfig.js.map +1 -1
  5. package/lib/components/QueryBuilder.d.ts.map +1 -1
  6. package/lib/components/QueryBuilder.js +3 -1
  7. package/lib/components/QueryBuilder.js.map +1 -1
  8. package/lib/components/QueryBuilderExplorerPanel.d.ts.map +1 -1
  9. package/lib/components/QueryBuilderExplorerPanel.js +10 -35
  10. package/lib/components/QueryBuilderExplorerPanel.js.map +1 -1
  11. package/lib/components/QueryBuilderFetchStructurePanel.d.ts.map +1 -1
  12. package/lib/components/QueryBuilderFetchStructurePanel.js +78 -35
  13. package/lib/components/QueryBuilderFetchStructurePanel.js.map +1 -1
  14. package/lib/components/QueryBuilderFilterPanel.d.ts.map +1 -1
  15. package/lib/components/QueryBuilderFilterPanel.js +80 -66
  16. package/lib/components/QueryBuilderFilterPanel.js.map +1 -1
  17. package/lib/components/QueryBuilderFunctionsExplorerPanel.d.ts.map +1 -1
  18. package/lib/components/QueryBuilderFunctionsExplorerPanel.js +9 -39
  19. package/lib/components/QueryBuilderFunctionsExplorerPanel.js.map +1 -1
  20. package/lib/components/QueryBuilderGraphFetchTreePanel.d.ts.map +1 -1
  21. package/lib/components/QueryBuilderGraphFetchTreePanel.js +5 -5
  22. package/lib/components/QueryBuilderGraphFetchTreePanel.js.map +1 -1
  23. package/lib/components/QueryBuilderLambdaEditor.d.ts +1 -0
  24. package/lib/components/QueryBuilderLambdaEditor.d.ts.map +1 -1
  25. package/lib/components/QueryBuilderLambdaEditor.js +2 -2
  26. package/lib/components/QueryBuilderLambdaEditor.js.map +1 -1
  27. package/lib/components/QueryBuilderMilestoneEditor.js +5 -5
  28. package/lib/components/QueryBuilderMilestoneEditor.js.map +1 -1
  29. package/lib/components/QueryBuilderPanelIssueCountBadge.d.ts +20 -0
  30. package/lib/components/QueryBuilderPanelIssueCountBadge.d.ts.map +1 -0
  31. package/lib/components/QueryBuilderPanelIssueCountBadge.js +28 -0
  32. package/lib/components/QueryBuilderPanelIssueCountBadge.js.map +1 -0
  33. package/lib/components/QueryBuilderParameterPanel.d.ts.map +1 -1
  34. package/lib/components/QueryBuilderParameterPanel.js +13 -33
  35. package/lib/components/QueryBuilderParameterPanel.js.map +1 -1
  36. package/lib/components/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  37. package/lib/components/QueryBuilderPostFilterPanel.js +59 -62
  38. package/lib/components/QueryBuilderPostFilterPanel.js.map +1 -1
  39. package/lib/components/QueryBuilderProjectionPanel.d.ts.map +1 -1
  40. package/lib/components/QueryBuilderProjectionPanel.js +47 -63
  41. package/lib/components/QueryBuilderProjectionPanel.js.map +1 -1
  42. package/lib/components/QueryBuilderPropertyExpressionEditor.d.ts.map +1 -1
  43. package/lib/components/QueryBuilderPropertyExpressionEditor.js +11 -11
  44. package/lib/components/QueryBuilderPropertyExpressionEditor.js.map +1 -1
  45. package/lib/components/QueryBuilderPropertySearchPanel.js +5 -7
  46. package/lib/components/QueryBuilderPropertySearchPanel.js.map +1 -1
  47. package/lib/components/QueryBuilderResultModifierPanel.d.ts.map +1 -1
  48. package/lib/components/QueryBuilderResultModifierPanel.js +3 -1
  49. package/lib/components/QueryBuilderResultModifierPanel.js.map +1 -1
  50. package/lib/components/QueryBuilderResultPanel.d.ts.map +1 -1
  51. package/lib/components/QueryBuilderResultPanel.js +37 -23
  52. package/lib/components/QueryBuilderResultPanel.js.map +1 -1
  53. package/lib/components/QueryBuilderSetupPanel.d.ts.map +1 -1
  54. package/lib/components/QueryBuilderSetupPanel.js +10 -9
  55. package/lib/components/QueryBuilderSetupPanel.js.map +1 -1
  56. package/lib/components/QueryBuilderUnsupportedQueryEditor.d.ts.map +1 -1
  57. package/lib/components/QueryBuilderUnsupportedQueryEditor.js +4 -2
  58. package/lib/components/QueryBuilderUnsupportedQueryEditor.js.map +1 -1
  59. package/lib/components/QueryEditor.d.ts.map +1 -1
  60. package/lib/components/QueryEditor.js +16 -4
  61. package/lib/components/QueryEditor.js.map +1 -1
  62. package/lib/index.css +2 -2
  63. package/lib/index.css.map +1 -1
  64. package/lib/package.json +10 -9
  65. package/lib/stores/QueryBuilderExplorerState.d.ts +1 -1
  66. package/lib/stores/QueryBuilderExplorerState.d.ts.map +1 -1
  67. package/lib/stores/QueryBuilderExplorerState.js +18 -3
  68. package/lib/stores/QueryBuilderExplorerState.js.map +1 -1
  69. package/lib/stores/QueryBuilderFetchStructureState.d.ts +8 -1
  70. package/lib/stores/QueryBuilderFetchStructureState.d.ts.map +1 -1
  71. package/lib/stores/QueryBuilderFetchStructureState.js +10 -2
  72. package/lib/stores/QueryBuilderFetchStructureState.js.map +1 -1
  73. package/lib/stores/QueryBuilderFilterState.d.ts +10 -5
  74. package/lib/stores/QueryBuilderFilterState.d.ts.map +1 -1
  75. package/lib/stores/QueryBuilderFilterState.js +34 -8
  76. package/lib/stores/QueryBuilderFilterState.js.map +1 -1
  77. package/lib/stores/QueryBuilderGraphFetchTreeState.d.ts.map +1 -1
  78. package/lib/stores/QueryBuilderGraphFetchTreeState.js +6 -3
  79. package/lib/stores/QueryBuilderGraphFetchTreeState.js.map +1 -1
  80. package/lib/stores/QueryBuilderLambdaProcessor.d.ts.map +1 -1
  81. package/lib/stores/QueryBuilderLambdaProcessor.js +2 -0
  82. package/lib/stores/QueryBuilderLambdaProcessor.js.map +1 -1
  83. package/lib/stores/QueryBuilderOperatorLoader.d.ts +47 -0
  84. package/lib/stores/QueryBuilderOperatorLoader.d.ts.map +1 -0
  85. package/lib/stores/QueryBuilderOperatorLoader.js +94 -0
  86. package/lib/stores/QueryBuilderOperatorLoader.js.map +1 -0
  87. package/lib/stores/QueryBuilderOperatorsHelper.d.ts +1 -0
  88. package/lib/stores/QueryBuilderOperatorsHelper.d.ts.map +1 -1
  89. package/lib/stores/QueryBuilderOperatorsHelper.js +28 -1
  90. package/lib/stores/QueryBuilderOperatorsHelper.js.map +1 -1
  91. package/lib/stores/QueryBuilderPostFilterState.d.ts +9 -6
  92. package/lib/stores/QueryBuilderPostFilterState.d.ts.map +1 -1
  93. package/lib/stores/QueryBuilderPostFilterState.js +31 -7
  94. package/lib/stores/QueryBuilderPostFilterState.js.map +1 -1
  95. package/lib/stores/QueryBuilderPreviewDataHelper.d.ts +4 -3
  96. package/lib/stores/QueryBuilderPreviewDataHelper.d.ts.map +1 -1
  97. package/lib/stores/QueryBuilderPreviewDataHelper.js +77 -97
  98. package/lib/stores/QueryBuilderPreviewDataHelper.js.map +1 -1
  99. package/lib/stores/QueryBuilderProjectionState.d.ts +4 -7
  100. package/lib/stores/QueryBuilderProjectionState.d.ts.map +1 -1
  101. package/lib/stores/QueryBuilderProjectionState.js +23 -39
  102. package/lib/stores/QueryBuilderProjectionState.js.map +1 -1
  103. package/lib/stores/QueryBuilderPropertySearchPanelState.js +1 -1
  104. package/lib/stores/QueryBuilderPropertySearchPanelState.js.map +1 -1
  105. package/lib/stores/QueryBuilderResultState.d.ts +5 -2
  106. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  107. package/lib/stores/QueryBuilderResultState.js +19 -7
  108. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  109. package/lib/stores/QueryBuilderSetupState.js +1 -1
  110. package/lib/stores/QueryBuilderSetupState.js.map +1 -1
  111. package/lib/stores/QueryBuilderState.d.ts +7 -0
  112. package/lib/stores/QueryBuilderState.d.ts.map +1 -1
  113. package/lib/stores/QueryBuilderState.js +18 -58
  114. package/lib/stores/QueryBuilderState.js.map +1 -1
  115. package/lib/stores/QueryBuilderTestUtils.d.ts +24 -0
  116. package/lib/stores/QueryBuilderTestUtils.d.ts.map +1 -0
  117. package/lib/stores/QueryBuilderTestUtils.js +49 -0
  118. package/lib/stores/QueryBuilderTestUtils.js.map +1 -0
  119. package/lib/stores/QueryBuilderTypeaheadHelper.d.ts +24 -0
  120. package/lib/stores/QueryBuilderTypeaheadHelper.d.ts.map +1 -0
  121. package/lib/stores/QueryBuilderTypeaheadHelper.js +89 -0
  122. package/lib/stores/QueryBuilderTypeaheadHelper.js.map +1 -0
  123. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.d.ts.map +1 -1
  124. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.js +7 -7
  125. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.js.map +1 -1
  126. package/lib/stores/QueryEditorStore.d.ts.map +1 -1
  127. package/lib/stores/QueryEditorStore.js +14 -3
  128. package/lib/stores/QueryEditorStore.js.map +1 -1
  129. package/lib/stores/QueryFunctionsExplorerState.d.ts +2 -6
  130. package/lib/stores/QueryFunctionsExplorerState.d.ts.map +1 -1
  131. package/lib/stores/QueryFunctionsExplorerState.js +2 -11
  132. package/lib/stores/QueryFunctionsExplorerState.js.map +1 -1
  133. package/lib/stores/QueryParametersState.d.ts +1 -3
  134. package/lib/stores/QueryParametersState.d.ts.map +1 -1
  135. package/lib/stores/QueryParametersState.js +1 -4
  136. package/lib/stores/QueryParametersState.js.map +1 -1
  137. package/lib/stores/filterOperators/QueryBuilderFilterOperator_Equal.d.ts.map +1 -1
  138. package/lib/stores/filterOperators/QueryBuilderFilterOperator_Equal.js +9 -32
  139. package/lib/stores/filterOperators/QueryBuilderFilterOperator_Equal.js.map +1 -1
  140. package/lib/stores/filterOperators/QueryBuilderFilterOperator_GreaterThan.d.ts.map +1 -1
  141. package/lib/stores/filterOperators/QueryBuilderFilterOperator_GreaterThan.js +9 -32
  142. package/lib/stores/filterOperators/QueryBuilderFilterOperator_GreaterThan.js.map +1 -1
  143. package/lib/stores/filterOperators/QueryBuilderFilterOperator_GreaterThanEqual.d.ts.map +1 -1
  144. package/lib/stores/filterOperators/QueryBuilderFilterOperator_GreaterThanEqual.js +9 -32
  145. package/lib/stores/filterOperators/QueryBuilderFilterOperator_GreaterThanEqual.js.map +1 -1
  146. package/lib/stores/filterOperators/QueryBuilderFilterOperator_LessThan.d.ts.map +1 -1
  147. package/lib/stores/filterOperators/QueryBuilderFilterOperator_LessThan.js +9 -33
  148. package/lib/stores/filterOperators/QueryBuilderFilterOperator_LessThan.js.map +1 -1
  149. package/lib/stores/filterOperators/QueryBuilderFilterOperator_LessThanEqual.d.ts.map +1 -1
  150. package/lib/stores/filterOperators/QueryBuilderFilterOperator_LessThanEqual.js +9 -32
  151. package/lib/stores/filterOperators/QueryBuilderFilterOperator_LessThanEqual.js.map +1 -1
  152. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_Equal.d.ts.map +1 -1
  153. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_Equal.js +7 -30
  154. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_Equal.js.map +1 -1
  155. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_GreaterThan.d.ts.map +1 -1
  156. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_GreaterThan.js +8 -31
  157. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_GreaterThan.js.map +1 -1
  158. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_LessThan.d.ts.map +1 -1
  159. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_LessThan.js +8 -31
  160. package/lib/stores/postFilterOperators/QueryBuilderPostFilterOperator_LessThan.js.map +1 -1
  161. package/package.json +17 -16
  162. package/src/application/LegendQueryApplicationConfig.ts +35 -1
  163. package/src/components/QueryBuilder.tsx +13 -2
  164. package/src/components/QueryBuilderExplorerPanel.tsx +20 -57
  165. package/src/components/QueryBuilderFetchStructurePanel.tsx +94 -41
  166. package/src/components/QueryBuilderFilterPanel.tsx +271 -232
  167. package/src/components/QueryBuilderFunctionsExplorerPanel.tsx +24 -68
  168. package/src/components/QueryBuilderGraphFetchTreePanel.tsx +34 -25
  169. package/src/components/QueryBuilderLambdaEditor.tsx +3 -0
  170. package/src/components/QueryBuilderMilestoneEditor.tsx +34 -34
  171. package/src/components/QueryBuilderPanelIssueCountBadge.tsx +38 -0
  172. package/src/components/QueryBuilderParameterPanel.tsx +23 -55
  173. package/src/components/QueryBuilderPostFilterPanel.tsx +245 -233
  174. package/src/components/QueryBuilderProjectionPanel.tsx +127 -154
  175. package/src/components/QueryBuilderPropertyExpressionEditor.tsx +61 -57
  176. package/src/components/QueryBuilderPropertySearchPanel.tsx +9 -9
  177. package/src/components/QueryBuilderResultModifierPanel.tsx +4 -2
  178. package/src/components/QueryBuilderResultPanel.tsx +139 -91
  179. package/src/components/QueryBuilderSetupPanel.tsx +13 -12
  180. package/src/components/QueryBuilderUnsupportedQueryEditor.tsx +4 -2
  181. package/src/components/QueryEditor.tsx +39 -1
  182. package/src/stores/QueryBuilderExplorerState.ts +22 -3
  183. package/src/stores/QueryBuilderFetchStructureState.ts +18 -2
  184. package/src/stores/QueryBuilderFilterState.ts +52 -7
  185. package/src/stores/QueryBuilderGraphFetchTreeState.ts +14 -8
  186. package/src/stores/QueryBuilderLambdaProcessor.ts +8 -0
  187. package/src/stores/QueryBuilderOperatorLoader.ts +133 -0
  188. package/src/stores/QueryBuilderOperatorsHelper.ts +35 -0
  189. package/src/stores/QueryBuilderPostFilterState.ts +47 -8
  190. package/src/stores/QueryBuilderPreviewDataHelper.ts +122 -217
  191. package/src/stores/QueryBuilderProjectionState.ts +40 -53
  192. package/src/stores/QueryBuilderPropertySearchPanelState.ts +1 -1
  193. package/src/stores/QueryBuilderResultState.ts +27 -9
  194. package/src/stores/QueryBuilderSetupState.ts +1 -1
  195. package/src/stores/QueryBuilderState.ts +35 -94
  196. package/src/stores/QueryBuilderTestUtils.ts +93 -0
  197. package/src/stores/QueryBuilderTypeaheadHelper.ts +149 -0
  198. package/src/stores/QueryBuilderValueSpecificationBuilderHelper.ts +9 -7
  199. package/src/stores/QueryEditorStore.ts +19 -3
  200. package/src/stores/QueryFunctionsExplorerState.ts +1 -11
  201. package/src/stores/QueryParametersState.ts +1 -3
  202. package/src/stores/filterOperators/QueryBuilderFilterOperator_Equal.ts +14 -36
  203. package/src/stores/filterOperators/QueryBuilderFilterOperator_GreaterThan.ts +17 -36
  204. package/src/stores/filterOperators/QueryBuilderFilterOperator_GreaterThanEqual.ts +17 -36
  205. package/src/stores/filterOperators/QueryBuilderFilterOperator_LessThan.ts +17 -37
  206. package/src/stores/filterOperators/QueryBuilderFilterOperator_LessThanEqual.ts +17 -36
  207. package/src/stores/postFilterOperators/QueryBuilderPostFilterOperator_Equal.ts +14 -34
  208. package/src/stores/postFilterOperators/QueryBuilderPostFilterOperator_GreaterThan.ts +19 -37
  209. package/src/stores/postFilterOperators/QueryBuilderPostFilterOperator_LessThan.ts +19 -37
  210. package/tsconfig.json +4 -0
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { useEffect, useRef, useState, useCallback, forwardRef } from 'react';
17
+ import { useRef, useState, useCallback, forwardRef, useMemo } from 'react';
18
18
  import { observer } from 'mobx-react-lite';
19
19
  import {
20
20
  type TreeNodeContainerProps,
@@ -38,6 +38,10 @@ import {
38
38
  ChevronRightIcon,
39
39
  PlusCircleIcon,
40
40
  TimesIcon,
41
+ PanelDropZone,
42
+ DragPreviewLayer,
43
+ PanelEntryDropZonePlaceholder,
44
+ useDragPreviewLayer,
41
45
  } from '@finos/legend-art';
42
46
  import {
43
47
  type QueryBuilderFilterConditionDragSource,
@@ -50,13 +54,7 @@ import {
50
54
  QueryBuilderFilterTreeBlankConditionNodeData,
51
55
  QueryBuilderFilterTreeGroupNodeData,
52
56
  } from '../stores/QueryBuilderFilterState.js';
53
- import {
54
- type DropTargetMonitor,
55
- useDragLayer,
56
- useDrag,
57
- useDrop,
58
- } from 'react-dnd';
59
- import { getEmptyImage } from 'react-dnd-html5-backend';
57
+ import { useDrag, useDrop } from 'react-dnd';
60
58
  import {
61
59
  type QueryBuilderExplorerTreeDragSource,
62
60
  type QueryBuilderExplorerTreePropertyNodeData,
@@ -65,7 +63,11 @@ import {
65
63
  } from '../stores/QueryBuilderExplorerState.js';
66
64
  import { QueryBuilderPropertyExpressionBadge } from './QueryBuilderPropertyExpressionEditor.js';
67
65
  import type { QueryBuilderState } from '../stores/QueryBuilderState.js';
68
- import { assertErrorThrown } from '@finos/legend-shared';
66
+ import {
67
+ assertErrorThrown,
68
+ debounce,
69
+ UnsupportedOperationError,
70
+ } from '@finos/legend-shared';
69
71
  import { QUERY_BUILDER_TEST_ID } from './QueryBuilder_TestID.js';
70
72
  import {
71
73
  useApplicationStore,
@@ -73,56 +75,25 @@ import {
73
75
  } from '@finos/legend-application';
74
76
  import {
75
77
  type QueryBuilderParameterDragSource,
76
- QUERY_BUILDER_PARAMETER_TREE_DND_TYPE,
78
+ QUERY_BUILDER_PARAMETER_DND_TYPE,
77
79
  } from '../stores/QueryParametersState.js';
78
- import { QUERY_BUILDER_GROUP_OPERATION } from '../stores/QueryBuilderOperatorsHelper.js';
80
+ import {
81
+ isTypeCompatibleWithConditionValueType,
82
+ QUERY_BUILDER_GROUP_OPERATION,
83
+ } from '../stores/QueryBuilderOperatorsHelper.js';
79
84
  import type { ValueSpecification } from '@finos/legend-graph';
80
-
81
- const FilterConditionDragLayer: React.FC = () => {
82
- const { itemType, item, isDragging, currentPosition } = useDragLayer(
83
- (monitor) => ({
84
- itemType: monitor.getItemType() as QUERY_BUILDER_FILTER_DND_TYPE,
85
- item: monitor.getItem<QueryBuilderFilterConditionDragSource | null>(),
86
- isDragging: monitor.isDragging(),
87
- initialOffset: monitor.getInitialSourceClientOffset(),
88
- currentPosition: monitor.getClientOffset(),
89
- }),
90
- );
91
-
92
- if (
93
- !isDragging ||
94
- !item ||
95
- !Object.values(QUERY_BUILDER_FILTER_DND_TYPE).includes(itemType)
96
- ) {
97
- return null;
98
- }
99
- return (
100
- <div className="query-builder-filter-tree__drag-preview-layer">
101
- <div
102
- className="query-builder-filter-tree__drag-preview"
103
- // added some offset so the mouse doesn't overlap the label too much
104
- style={
105
- !currentPosition
106
- ? { display: 'none' }
107
- : {
108
- transform: `translate(${currentPosition.x + 20}px, ${
109
- currentPosition.y + 10
110
- }px)`,
111
- }
112
- }
113
- >
114
- {item.node.dragLayerLabel}
115
- </div>
116
- </div>
117
- );
118
- };
85
+ import {
86
+ type QueryBuilderProjectionColumnDragSource,
87
+ QueryBuilderSimpleProjectionColumnState,
88
+ QUERY_BUILDER_PROJECTION_COLUMN_DND_TYPE,
89
+ } from '../stores/QueryBuilderProjectionState.js';
119
90
 
120
91
  const QueryBuilderFilterGroupConditionEditor = observer(
121
92
  (props: {
122
93
  node: QueryBuilderFilterTreeGroupNodeData;
123
- isPropertyDragOver: boolean;
94
+ isDragOver: boolean;
124
95
  }) => {
125
- const { node, isPropertyDragOver } = props;
96
+ const { node, isDragOver } = props;
126
97
  const switchOperation: React.MouseEventHandler<HTMLDivElement> = (
127
98
  event,
128
99
  ): void => {
@@ -134,29 +105,30 @@ const QueryBuilderFilterGroupConditionEditor = observer(
134
105
  );
135
106
  };
136
107
  return (
137
- <div className="query-builder-filter-tree__node__label__content dnd__overlay__container">
138
- {isPropertyDragOver && (
139
- <div className="query-builder-filter-tree__node__dnd__overlay">
140
- Add to Logical Group
141
- </div>
142
- )}
143
- <div
144
- className={clsx('query-builder-filter-tree__group-node', {
145
- 'query-builder-filter-tree__group-node--and':
146
- node.groupOperation === QUERY_BUILDER_GROUP_OPERATION.AND,
147
- 'query-builder-filter-tree__group-node--or':
148
- node.groupOperation === QUERY_BUILDER_GROUP_OPERATION.OR,
149
- })}
150
- title="Switch Operation"
151
- onClick={switchOperation}
108
+ <div className="query-builder-filter-tree__node__label__content">
109
+ <PanelEntryDropZonePlaceholder
110
+ showPlaceholder={isDragOver}
111
+ label="Add to Logical Group"
112
+ className="query-builder__dnd__placeholder"
152
113
  >
153
- <div className="query-builder-filter-tree__group-node__label">
154
- {node.groupOperation}
114
+ <div
115
+ className={clsx('query-builder-filter-tree__group-node', {
116
+ 'query-builder-filter-tree__group-node--and':
117
+ node.groupOperation === QUERY_BUILDER_GROUP_OPERATION.AND,
118
+ 'query-builder-filter-tree__group-node--or':
119
+ node.groupOperation === QUERY_BUILDER_GROUP_OPERATION.OR,
120
+ })}
121
+ title="Switch Operation"
122
+ onClick={switchOperation}
123
+ >
124
+ <div className="query-builder-filter-tree__group-node__label">
125
+ {node.groupOperation}
126
+ </div>
127
+ <button className="query-builder-filter-tree__group-node__action">
128
+ <FilledTriangleIcon />
129
+ </button>
155
130
  </div>
156
- <button className="query-builder-filter-tree__group-node__action">
157
- <FilledTriangleIcon />
158
- </button>
159
- </div>
131
+ </PanelEntryDropZonePlaceholder>
160
132
  </div>
161
133
  );
162
134
  },
@@ -165,11 +137,12 @@ const QueryBuilderFilterGroupConditionEditor = observer(
165
137
  const QueryBuilderFilterConditionEditor = observer(
166
138
  (props: {
167
139
  node: QueryBuilderFilterTreeConditionNodeData;
168
- isPropertyDragOver: boolean;
140
+ isDragOver: boolean;
169
141
  }) => {
170
- const { node, isPropertyDragOver } = props;
142
+ const { node, isDragOver } = props;
171
143
  const graph =
172
144
  node.condition.filterState.queryBuilderState.graphManagerState.graph;
145
+ const applicationStore = useApplicationStore();
173
146
  const changeOperator = (val: QueryBuilderFilterOperator) => (): void =>
174
147
  node.condition.changeOperator(val);
175
148
  const changeProperty = (
@@ -188,22 +161,39 @@ const QueryBuilderFilterConditionEditor = observer(
188
161
  // Drag and Drop on filter condition value
189
162
  const handleDrop = useCallback(
190
163
  (item: QueryBuilderParameterDragSource): void => {
191
- node.condition.setValue(item.variable.parameter);
164
+ const parameterType =
165
+ item.variable.parameter.genericType?.value.rawType;
166
+ const conditionValueType =
167
+ node.condition.propertyExpressionState.propertyExpression.func
168
+ .genericType.value.rawType;
169
+ if (
170
+ isTypeCompatibleWithConditionValueType(
171
+ parameterType,
172
+ conditionValueType,
173
+ )
174
+ ) {
175
+ node.condition.setValue(item.variable.parameter);
176
+ } else {
177
+ applicationStore.notifyWarning(
178
+ `Incompatible parameter type ${parameterType?.name}. ${parameterType?.name} is not compatible with type ${conditionValueType.name}.`,
179
+ );
180
+ }
192
181
  },
193
- [node],
182
+ [applicationStore, node.condition],
194
183
  );
195
- const [{ isFilterValueDragOver }, dropConnector] = useDrop(
184
+ const [{ isFilterValueDragOver }, dropConnector] = useDrop<
185
+ QueryBuilderParameterDragSource,
186
+ void,
187
+ { isFilterValueDragOver: boolean }
188
+ >(
196
189
  () => ({
197
- accept: [QUERY_BUILDER_PARAMETER_TREE_DND_TYPE.VARIABLE],
198
- drop: (
199
- item: QueryBuilderParameterDragSource,
200
- monitor: DropTargetMonitor,
201
- ): void => {
190
+ accept: [QUERY_BUILDER_PARAMETER_DND_TYPE],
191
+ drop: (item, monitor): void => {
202
192
  if (!monitor.didDrop()) {
203
193
  handleDrop(item);
204
- }
194
+ } // prevent drop event propagation to accomondate for nested DnD
205
195
  },
206
- collect: (monitor): { isFilterValueDragOver: boolean } => ({
196
+ collect: (monitor) => ({
207
197
  isFilterValueDragOver: monitor.isOver({ shallow: true }),
208
198
  }),
209
199
  }),
@@ -214,79 +204,100 @@ const QueryBuilderFilterConditionEditor = observer(
214
204
  node.condition.operator.getDefaultFilterConditionValue(node.condition),
215
205
  );
216
206
  };
207
+ const debouncedTypeaheadSearch = useMemo(
208
+ () =>
209
+ debounce(
210
+ (inputVal: string) => node.condition.handleTypeaheadSearch(),
211
+ 1000,
212
+ ),
213
+ [node],
214
+ );
215
+ const cleanUpReloadValues = (): void => {
216
+ node.condition.typeaheadSearchState.complete();
217
+ };
218
+ const changeValueSpecification = (val: ValueSpecification): void => {
219
+ node.condition.setValue(val);
220
+ };
221
+ const selectorConfig = {
222
+ values: node.condition.typeaheadSearchResults,
223
+ isLoading: node.condition.typeaheadSearchState.isInProgress,
224
+ reloadValues: debouncedTypeaheadSearch,
225
+ cleanUpReloadValues,
226
+ };
217
227
 
218
228
  return (
219
- <div className="query-builder-filter-tree__node__label__content dnd__overlay__container">
220
- {isPropertyDragOver && (
221
- <div className="query-builder-filter-tree__node__dnd__overlay">
222
- Add New Logical Group
223
- </div>
224
- )}
225
- <div className="query-builder-filter-tree__condition-node">
226
- <div className="query-builder-filter-tree__condition-node__property">
227
- <QueryBuilderPropertyExpressionBadge
228
- propertyExpressionState={node.condition.propertyExpressionState}
229
- onPropertyExpressionChange={changeProperty}
230
- />
231
- </div>
232
- <DropdownMenu
233
- className="query-builder-filter-tree__condition-node__operator"
234
- content={
235
- <MenuContent>
236
- {node.condition.operators.map((op) => (
237
- <MenuContentItem
238
- key={op.uuid}
239
- className="query-builder-filter-tree__condition-node__operator__dropdown__option"
240
- onClick={changeOperator(op)}
241
- >
242
- {op.getLabel(node.condition)}
243
- </MenuContentItem>
244
- ))}
245
- </MenuContent>
246
- }
247
- menuProps={{
248
- anchorOrigin: { vertical: 'bottom', horizontal: 'left' },
249
- transformOrigin: { vertical: 'top', horizontal: 'left' },
250
- elevation: 7,
251
- }}
252
- >
253
- <div className="query-builder-filter-tree__condition-node__operator__label">
254
- {node.condition.operator.getLabel(node.condition)}
255
- </div>
256
- <button
257
- className="query-builder-filter-tree__condition-node__operator__dropdown__trigger"
258
- tabIndex={-1}
259
- title="Choose Operator..."
260
- >
261
- <CaretDownIcon />
262
- </button>
263
- </DropdownMenu>
264
- {node.condition.value && (
265
- <div
266
- ref={dropConnector}
267
- className="query-builder-filter-tree__condition-node__value dnd__overlay__container"
268
- >
269
- {isFilterValueDragOver && (
270
- <div className="query-builder-filter-tree__node__dnd__overlay">
271
- Change Filter Value
272
- </div>
273
- )}
274
- <BasicValueSpecificationEditor
275
- valueSpecification={node.condition.value}
276
- setValueSpecification={(val: ValueSpecification): void =>
277
- node.condition.setValue(val)
278
- }
279
- graph={graph}
280
- typeCheckOption={{
281
- expectedType:
282
- node.condition.propertyExpressionState.propertyExpression
283
- .func.genericType.value.rawType,
284
- }}
285
- resetValue={resetNode}
229
+ <div className="query-builder-filter-tree__node__label__content">
230
+ <PanelEntryDropZonePlaceholder
231
+ showPlaceholder={isDragOver}
232
+ label="Add New Logical Group"
233
+ className="query-builder__dnd__placeholder"
234
+ >
235
+ <div className="query-builder-filter-tree__condition-node">
236
+ <div className="query-builder-filter-tree__condition-node__property">
237
+ <QueryBuilderPropertyExpressionBadge
238
+ propertyExpressionState={node.condition.propertyExpressionState}
239
+ onPropertyExpressionChange={changeProperty}
286
240
  />
287
241
  </div>
288
- )}
289
- </div>
242
+ <DropdownMenu
243
+ className="query-builder-filter-tree__condition-node__operator"
244
+ content={
245
+ <MenuContent>
246
+ {node.condition.operators.map((op) => (
247
+ <MenuContentItem
248
+ key={op.uuid}
249
+ className="query-builder-filter-tree__condition-node__operator__dropdown__option"
250
+ onClick={changeOperator(op)}
251
+ >
252
+ {op.getLabel(node.condition)}
253
+ </MenuContentItem>
254
+ ))}
255
+ </MenuContent>
256
+ }
257
+ menuProps={{
258
+ anchorOrigin: { vertical: 'bottom', horizontal: 'left' },
259
+ transformOrigin: { vertical: 'top', horizontal: 'left' },
260
+ elevation: 7,
261
+ }}
262
+ >
263
+ <div className="query-builder-filter-tree__condition-node__operator__label">
264
+ {node.condition.operator.getLabel(node.condition)}
265
+ </div>
266
+ <button
267
+ className="query-builder-filter-tree__condition-node__operator__dropdown__trigger"
268
+ tabIndex={-1}
269
+ title="Choose Operator..."
270
+ >
271
+ <CaretDownIcon />
272
+ </button>
273
+ </DropdownMenu>
274
+ {node.condition.value && (
275
+ <div
276
+ ref={dropConnector}
277
+ className="query-builder-filter-tree__condition-node__value"
278
+ >
279
+ <PanelEntryDropZonePlaceholder
280
+ showPlaceholder={isFilterValueDragOver}
281
+ label="Change Filter Value"
282
+ className="query-builder__dnd__placeholder"
283
+ >
284
+ <BasicValueSpecificationEditor
285
+ valueSpecification={node.condition.value}
286
+ setValueSpecification={changeValueSpecification}
287
+ graph={graph}
288
+ typeCheckOption={{
289
+ expectedType:
290
+ node.condition.propertyExpressionState
291
+ .propertyExpression.func.genericType.value.rawType,
292
+ }}
293
+ resetValue={resetNode}
294
+ selectorConfig={selectorConfig}
295
+ />
296
+ </PanelEntryDropZonePlaceholder>
297
+ </div>
298
+ )}
299
+ </div>
300
+ </PanelEntryDropZonePlaceholder>
290
301
  </div>
291
302
  );
292
303
  },
@@ -295,17 +306,18 @@ const QueryBuilderFilterConditionEditor = observer(
295
306
  const QueryBuilderFilterBlankConditionEditor = observer(
296
307
  (props: {
297
308
  node: QueryBuilderFilterTreeBlankConditionNodeData;
298
- isPropertyDragOver: boolean;
309
+ isDragOver: boolean;
299
310
  }) => {
300
- const { isPropertyDragOver } = props;
311
+ const { isDragOver } = props;
301
312
  return (
302
- <div className="query-builder-filter-tree__node__label__content dnd__overlay__container">
303
- {isPropertyDragOver && (
304
- <div className="query-builder-filter-tree__node__dnd__overlay">
305
- Create Condition
306
- </div>
307
- )}
308
- <div className="query-builder-filter-tree__blank-node">blank</div>
313
+ <div className="query-builder-filter-tree__node__label__content">
314
+ <PanelEntryDropZonePlaceholder
315
+ showPlaceholder={isDragOver}
316
+ label="Create Condition"
317
+ className="query-builder__dnd__placeholder"
318
+ >
319
+ <div className="query-builder-filter-tree__blank-node">blank</div>
320
+ </PanelEntryDropZonePlaceholder>
309
321
  </div>
310
322
  );
311
323
  },
@@ -440,50 +452,45 @@ const QueryBuilderFilterTreeNodeContainer = observer(
440
452
  },
441
453
  [applicationStore, filterState, node],
442
454
  );
443
- const [{ isPropertyDragOver }, dropConnector] = useDrop(
455
+ const [{ isDragOver }, dropConnector] = useDrop<
456
+ QueryBuilderFilterConditionDragSource,
457
+ void,
458
+ { isDragOver: boolean }
459
+ >(
444
460
  () => ({
445
461
  accept: [
446
462
  ...Object.values(QUERY_BUILDER_FILTER_DND_TYPE),
447
463
  QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY,
448
464
  QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY,
449
465
  ],
450
- drop: (
451
- item: QueryBuilderFilterConditionDragSource,
452
- monitor: DropTargetMonitor,
453
- ): void => {
466
+ drop: (item, monitor): void => {
454
467
  if (!monitor.didDrop()) {
455
468
  handleDrop(item, monitor.getItemType() as string);
456
469
  } // prevent drop event propagation to accomondate for nested DnD
457
470
  },
458
- // canDrop: (item: QueryBuilderFilterConditionDragSource, monitor: DropTargetMonitor): boolean => {
459
- // // prevent drop inside of children
460
- // // prevent dropping inside my direct ancestor
461
- // return true;
462
- // },
463
- collect: (monitor): { isPropertyDragOver: boolean } => ({
464
- isPropertyDragOver: monitor.isOver({ shallow: true }),
471
+ collect: (monitor) => ({
472
+ isDragOver: monitor.isOver({ shallow: true }),
465
473
  }),
466
474
  }),
467
475
  [handleDrop],
468
476
  );
469
- const [, dragConnector, dragPreviewConnector] = useDrag(
470
- () => ({
471
- type:
472
- node instanceof QueryBuilderFilterTreeGroupNodeData
473
- ? QUERY_BUILDER_FILTER_DND_TYPE.GROUP_CONDITION
474
- : node instanceof QueryBuilderFilterTreeConditionNodeData
475
- ? QUERY_BUILDER_FILTER_DND_TYPE.CONDITION
476
- : QUERY_BUILDER_FILTER_DND_TYPE.BLANK_CONDITION,
477
- item: (): QueryBuilderFilterConditionDragSource => ({ node }),
478
- end: (): void => filterState.setRearrangingConditions(false),
479
- }),
480
- [node, filterState],
481
- );
477
+ const [, dragConnector, dragPreviewConnector] =
478
+ useDrag<QueryBuilderFilterConditionDragSource>(
479
+ () => ({
480
+ type:
481
+ node instanceof QueryBuilderFilterTreeGroupNodeData
482
+ ? QUERY_BUILDER_FILTER_DND_TYPE.GROUP_CONDITION
483
+ : node instanceof QueryBuilderFilterTreeConditionNodeData
484
+ ? QUERY_BUILDER_FILTER_DND_TYPE.CONDITION
485
+ : QUERY_BUILDER_FILTER_DND_TYPE.BLANK_CONDITION,
486
+ item: () => ({ node }),
487
+ end: (): void => filterState.setRearrangingConditions(false),
488
+ }),
489
+ [node, filterState],
490
+ );
482
491
  dragConnector(dropConnector(ref));
483
- // hide default HTML5 preview image
484
- useEffect(() => {
485
- dragPreviewConnector(getEmptyImage(), { captureDraggingState: true });
486
- }, [dragPreviewConnector]);
492
+ useDragPreviewLayer(dragPreviewConnector);
493
+
487
494
  // context menu
488
495
  const onContextMenuOpen = (): void => setIsSelectedFromContextMenu(true);
489
496
  const onContextMenuClose = (): void => setIsSelectedFromContextMenu(false);
@@ -542,19 +549,19 @@ const QueryBuilderFilterTreeNodeContainer = observer(
542
549
  {node instanceof QueryBuilderFilterTreeGroupNodeData && (
543
550
  <QueryBuilderFilterGroupConditionEditor
544
551
  node={node}
545
- isPropertyDragOver={isPropertyDragOver}
552
+ isDragOver={isDragOver}
546
553
  />
547
554
  )}
548
555
  {node instanceof QueryBuilderFilterTreeConditionNodeData && (
549
556
  <QueryBuilderFilterConditionEditor
550
557
  node={node}
551
- isPropertyDragOver={isPropertyDragOver}
558
+ isDragOver={isDragOver}
552
559
  />
553
560
  )}
554
561
  {node instanceof QueryBuilderFilterTreeBlankConditionNodeData && (
555
562
  <QueryBuilderFilterBlankConditionEditor
556
563
  node={node}
557
- isPropertyDragOver={isPropertyDragOver}
564
+ isDragOver={isDragOver}
558
565
  />
559
566
  )}
560
567
  </div>
@@ -708,18 +715,37 @@ export const QueryBuilderFilterPanel = observer(
708
715
  };
709
716
  // Drag and Drop
710
717
  const handleDrop = useCallback(
711
- (item: QueryBuilderFilterDropTarget): void => {
718
+ (item: QueryBuilderFilterDropTarget, type: string): void => {
712
719
  let filterConditionState: FilterConditionState;
713
720
  try {
721
+ let propertyExpression;
722
+ if (type === QUERY_BUILDER_PROJECTION_COLUMN_DND_TYPE) {
723
+ if (
724
+ (item as QueryBuilderProjectionColumnDragSource)
725
+ .columnState instanceof QueryBuilderSimpleProjectionColumnState
726
+ ) {
727
+ propertyExpression = (
728
+ (item as QueryBuilderProjectionColumnDragSource)
729
+ .columnState as QueryBuilderSimpleProjectionColumnState
730
+ ).propertyExpressionState.propertyExpression;
731
+ } else {
732
+ throw new UnsupportedOperationError(
733
+ `Dragging and Dropping derivation projection column is not supported.`,
734
+ );
735
+ }
736
+ } else {
737
+ propertyExpression =
738
+ buildPropertyExpressionFromExplorerTreeNodeData(
739
+ filterState.queryBuilderState.explorerState.nonNullableTreeData,
740
+ (item as QueryBuilderExplorerTreeDragSource).node,
741
+ filterState.queryBuilderState.graphManagerState.graph,
742
+ filterState.queryBuilderState.explorerState
743
+ .propertySearchPanelState.allMappedPropertyNodes,
744
+ );
745
+ }
714
746
  filterConditionState = new FilterConditionState(
715
747
  filterState,
716
- buildPropertyExpressionFromExplorerTreeNodeData(
717
- filterState.queryBuilderState.explorerState.nonNullableTreeData,
718
- (item as QueryBuilderExplorerTreeDragSource).node,
719
- filterState.queryBuilderState.graphManagerState.graph,
720
- filterState.queryBuilderState.explorerState
721
- .propertySearchPanelState.allMappedPropertyNodes,
722
- ),
748
+ propertyExpression,
723
749
  );
724
750
  } catch (error) {
725
751
  assertErrorThrown(error);
@@ -738,22 +764,29 @@ export const QueryBuilderFilterPanel = observer(
738
764
  },
739
765
  [applicationStore, filterState],
740
766
  );
741
- const [{ isPropertyDragOver }, dropConnector] = useDrop(
767
+ const [{ isDragOver }, dropTargetConnector] = useDrop<
768
+ QueryBuilderExplorerTreeDragSource,
769
+ void,
770
+ { isDragOver: boolean }
771
+ >(
742
772
  () => ({
743
- accept: [
744
- QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY,
745
- QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY,
746
- ],
747
- drop: (
748
- item: QueryBuilderExplorerTreeDragSource,
749
- monitor: DropTargetMonitor,
750
- ): void => {
773
+ accept: queryBuilderState.mode.isDnDProjectionToFilterSupported
774
+ ? [
775
+ QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY,
776
+ QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY,
777
+ QUERY_BUILDER_PROJECTION_COLUMN_DND_TYPE,
778
+ ]
779
+ : [
780
+ QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY,
781
+ QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY,
782
+ ],
783
+ drop: (item, monitor): void => {
751
784
  if (!monitor.didDrop()) {
752
- handleDrop(item);
785
+ handleDrop(item, monitor.getItemType() as string);
753
786
  } // prevent drop event propagation to accomondate for nested DnD
754
787
  },
755
- collect: (monitor): { isPropertyDragOver: boolean } => ({
756
- isPropertyDragOver: monitor.isOver({ shallow: true }),
788
+ collect: (monitor) => ({
789
+ isDragOver: monitor.isOver({ shallow: true }),
757
790
  }),
758
791
  }),
759
792
  [handleDrop],
@@ -834,23 +867,29 @@ export const QueryBuilderFilterPanel = observer(
834
867
  </button>
835
868
  </div>
836
869
  </div>
837
- <div
838
- className="panel__content query-builder__filter__content dnd__overlay__container"
839
- ref={dropConnector}
840
- >
841
- <div className={clsx({ dnd__overlay: isPropertyDragOver })} />
842
- {filterState.isEmpty && (
843
- <BlankPanelPlaceholder
844
- placeholderText="Add a filter condition"
845
- tooltipText="Drag and drop properties here"
846
- />
847
- )}
848
- {!filterState.isEmpty && (
849
- <>
850
- <FilterConditionDragLayer />
851
- <QueryBuilderFilterTree queryBuilderState={queryBuilderState} />
852
- </>
853
- )}
870
+ <div className="panel__content query-builder__filter__content">
871
+ <PanelDropZone
872
+ isDragOver={isDragOver}
873
+ dropTargetConnector={dropTargetConnector}
874
+ >
875
+ {filterState.isEmpty && (
876
+ <BlankPanelPlaceholder
877
+ text="Add a filter condition"
878
+ tooltipText="Drag and drop properties here"
879
+ />
880
+ )}
881
+ {!filterState.isEmpty && (
882
+ <>
883
+ <DragPreviewLayer
884
+ labelGetter={(
885
+ item: QueryBuilderFilterConditionDragSource,
886
+ ): string => item.node.dragPreviewLabel}
887
+ types={Object.values(QUERY_BUILDER_FILTER_DND_TYPE)}
888
+ />
889
+ <QueryBuilderFilterTree queryBuilderState={queryBuilderState} />
890
+ </>
891
+ )}
892
+ </PanelDropZone>
854
893
  </div>
855
894
  </div>
856
895
  );