@finos/legend-query-builder 4.14.63 → 4.14.65
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.
- package/lib/components/__test-utils__/QueryBuilderComponentTestUtils.d.ts +3 -0
- package/lib/components/__test-utils__/QueryBuilderComponentTestUtils.d.ts.map +1 -1
- package/lib/components/__test-utils__/QueryBuilderComponentTestUtils.js +12 -1
- package/lib/components/__test-utils__/QueryBuilderComponentTestUtils.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +20 -19
- package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
- package/lib/components/filter/QueryBuilderFilterPanel.d.ts +7 -1
- package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
- package/lib/components/filter/QueryBuilderFilterPanel.js +137 -54
- package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
- package/lib/components/shared/QueryBuilderFilterHelper.d.ts +19 -0
- package/lib/components/shared/QueryBuilderFilterHelper.d.ts.map +1 -0
- package/lib/components/shared/QueryBuilderFilterHelper.js +34 -0
- package/lib/components/shared/QueryBuilderFilterHelper.js.map +1 -0
- package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js +1 -1
- package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js.map +1 -1
- package/lib/index.css +17 -1
- package/lib/index.css.map +1 -1
- package/lib/package.json +3 -3
- package/lib/stores/QueryBuilderStateHashUtils.d.ts +2 -0
- package/lib/stores/QueryBuilderStateHashUtils.d.ts.map +1 -1
- package/lib/stores/QueryBuilderStateHashUtils.js +2 -0
- package/lib/stores/QueryBuilderStateHashUtils.js.map +1 -1
- package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_In.js +1 -1
- package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_In.js.map +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.d.ts +35 -5
- package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.js +181 -52
- package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
- package/lib/stores/filter/QueryBuilderFilterStateBuilder.js +2 -2
- package/lib/stores/filter/QueryBuilderFilterStateBuilder.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.js +21 -6
- package/lib/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.js +4 -3
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_Contain.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.js +4 -3
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_EndWith.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.js +5 -4
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_Equal.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.js +5 -4
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.js +5 -4
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.d.ts +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.js +33 -28
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.js +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.js +5 -4
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThan.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.js +5 -4
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.d.ts.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.js +4 -3
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_StartWith.js.map +1 -1
- package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts +2 -1
- package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts.map +1 -1
- package/lib/stores/shared/ValueSpecificationEditorHelper.js +9 -3
- package/lib/stores/shared/ValueSpecificationEditorHelper.js.map +1 -1
- package/package.json +11 -11
- package/src/components/__test-utils__/QueryBuilderComponentTestUtils.tsx +25 -0
- package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +29 -26
- package/src/components/filter/QueryBuilderFilterPanel.tsx +335 -106
- package/src/components/shared/QueryBuilderFilterHelper.ts +51 -0
- package/src/components/shared/QueryBuilderPropertyInfoTooltip.tsx +1 -1
- package/src/stores/QueryBuilderStateHashUtils.ts +2 -0
- package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_In.ts +1 -1
- package/src/stores/filter/QueryBuilderFilterState.ts +284 -74
- package/src/stores/filter/QueryBuilderFilterStateBuilder.ts +2 -2
- package/src/stores/filter/operators/QueryBuilderFilterOperatorValueSpecificationBuilder.ts +48 -9
- package/src/stores/filter/operators/QueryBuilderFilterOperator_Contain.ts +5 -4
- package/src/stores/filter/operators/QueryBuilderFilterOperator_EndWith.ts +5 -4
- package/src/stores/filter/operators/QueryBuilderFilterOperator_Equal.ts +4 -4
- package/src/stores/filter/operators/QueryBuilderFilterOperator_GreaterThan.ts +5 -7
- package/src/stores/filter/operators/QueryBuilderFilterOperator_GreaterThanEqual.ts +5 -7
- package/src/stores/filter/operators/QueryBuilderFilterOperator_In.ts +52 -47
- package/src/stores/filter/operators/QueryBuilderFilterOperator_IsEmpty.ts +1 -1
- package/src/stores/filter/operators/QueryBuilderFilterOperator_LessThan.ts +5 -7
- package/src/stores/filter/operators/QueryBuilderFilterOperator_LessThanEqual.ts +5 -7
- package/src/stores/filter/operators/QueryBuilderFilterOperator_StartWith.ts +5 -4
- package/src/stores/shared/ValueSpecificationEditorHelper.ts +28 -0
- package/tsconfig.json +1 -0
|
@@ -50,10 +50,11 @@ import {
|
|
|
50
50
|
MenuContentItemIcon,
|
|
51
51
|
MenuContentItemLabel,
|
|
52
52
|
InfoCircleIcon,
|
|
53
|
+
RefreshIcon,
|
|
53
54
|
} from '@finos/legend-art';
|
|
54
55
|
import {
|
|
55
56
|
type QueryBuilderFilterConditionDragSource,
|
|
56
|
-
type
|
|
57
|
+
type QueryBuilderFilterNodeDropTarget,
|
|
57
58
|
type QueryBuilderFilterTreeNodeData,
|
|
58
59
|
QUERY_BUILDER_FILTER_DND_TYPE,
|
|
59
60
|
FilterConditionState,
|
|
@@ -63,6 +64,10 @@ import {
|
|
|
63
64
|
QueryBuilderFilterTreeExistsNodeData,
|
|
64
65
|
QueryBuilderFilterTreeOperationNodeData,
|
|
65
66
|
type QueryBuilderFilterState,
|
|
67
|
+
FilterValueSpecConditionValueState,
|
|
68
|
+
FilterPropertyExpressionStateConditionValueState,
|
|
69
|
+
isCollectionProperty,
|
|
70
|
+
type QueryBuilderFilterValueDropTarget,
|
|
66
71
|
} from '../../stores/filter/QueryBuilderFilterState.js';
|
|
67
72
|
import { useDrag, useDragLayer, useDrop } from 'react-dnd';
|
|
68
73
|
import {
|
|
@@ -80,7 +85,6 @@ import {
|
|
|
80
85
|
assertTrue,
|
|
81
86
|
debounce,
|
|
82
87
|
generateEnumerableNameFromToken,
|
|
83
|
-
getNullableFirstEntry,
|
|
84
88
|
guaranteeNonNullable,
|
|
85
89
|
guaranteeType,
|
|
86
90
|
UnsupportedOperationError,
|
|
@@ -92,14 +96,17 @@ import {
|
|
|
92
96
|
useApplicationStore,
|
|
93
97
|
} from '@finos/legend-application';
|
|
94
98
|
import {
|
|
99
|
+
type Type,
|
|
100
|
+
type ValueSpecification,
|
|
95
101
|
AbstractPropertyExpression,
|
|
96
102
|
extractElementNameFromPath,
|
|
97
103
|
matchFunctionName,
|
|
98
104
|
Multiplicity,
|
|
99
105
|
SimpleFunctionExpression,
|
|
100
|
-
type ValueSpecification,
|
|
101
106
|
VariableExpression,
|
|
102
107
|
PrimitiveType,
|
|
108
|
+
Class,
|
|
109
|
+
Enumeration,
|
|
103
110
|
} from '@finos/legend-graph';
|
|
104
111
|
import {
|
|
105
112
|
type QueryBuilderProjectionColumnDragSource,
|
|
@@ -115,11 +122,24 @@ import {
|
|
|
115
122
|
EditableBasicValueSpecificationEditor,
|
|
116
123
|
} from '../shared/BasicValueSpecificationEditor.js';
|
|
117
124
|
import { QueryBuilderTelemetryHelper } from '../../__lib__/QueryBuilderTelemetryHelper.js';
|
|
118
|
-
import {
|
|
125
|
+
import {
|
|
126
|
+
QueryBuilderPropertyExpressionState,
|
|
127
|
+
getPropertyChainName,
|
|
128
|
+
} from '../../stores/QueryBuilderPropertyEditorState.js';
|
|
119
129
|
import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '../../graph/QueryBuilderMetaModelConst.js';
|
|
120
130
|
import { buildPropertyExpressionChain } from '../../stores/QueryBuilderValueSpecificationBuilderHelper.js';
|
|
121
131
|
import { QueryBuilderPanelIssueCountBadge } from '../shared/QueryBuilderPanelIssueCountBadge.js';
|
|
122
|
-
import {
|
|
132
|
+
import {
|
|
133
|
+
cloneAbstractPropertyExpression,
|
|
134
|
+
convertTextToPrimitiveInstanceValue,
|
|
135
|
+
} from '../../stores/shared/ValueSpecificationEditorHelper.js';
|
|
136
|
+
import {
|
|
137
|
+
QueryBuilderFilterOperator_In,
|
|
138
|
+
QueryBuilderFilterOperator_NotIn,
|
|
139
|
+
} from '../../stores/filter/operators/QueryBuilderFilterOperator_In.js';
|
|
140
|
+
import { renderPropertyTypeIcon } from '../fetch-structure/QueryBuilderTDSComponentHelper.js';
|
|
141
|
+
import { QueryBuilderPropertyInfoTooltip } from '../shared/QueryBuilderPropertyInfoTooltip.js';
|
|
142
|
+
import { getDNDItemType } from '../shared/QueryBuilderFilterHelper.js';
|
|
123
143
|
|
|
124
144
|
export const CAN_DROP_MAIN_GROUP_DND_TYPES_FETCH_SUPPORTED = [
|
|
125
145
|
QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY,
|
|
@@ -146,40 +166,12 @@ export const CAN_DROP_FILTER_NODE_DND_TYPES = [
|
|
|
146
166
|
];
|
|
147
167
|
|
|
148
168
|
export const CAN_DROP_FILTER_VALUE_DND_TYPES = [
|
|
169
|
+
QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY,
|
|
170
|
+
QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY,
|
|
171
|
+
QUERY_BUILDER_PROJECTION_COLUMN_DND_TYPE,
|
|
149
172
|
QUERY_BUILDER_VARIABLE_DND_TYPE,
|
|
150
173
|
];
|
|
151
174
|
|
|
152
|
-
const isCollectionProperty = (
|
|
153
|
-
propertyExpression: AbstractPropertyExpression,
|
|
154
|
-
): boolean => {
|
|
155
|
-
let currentExpression: ValueSpecification | undefined = propertyExpression;
|
|
156
|
-
while (currentExpression instanceof AbstractPropertyExpression) {
|
|
157
|
-
// Check if the property chain can results in column that have multiple values
|
|
158
|
-
if (
|
|
159
|
-
currentExpression.func.value.multiplicity.upperBound === undefined ||
|
|
160
|
-
currentExpression.func.value.multiplicity.upperBound > 1
|
|
161
|
-
) {
|
|
162
|
-
return true;
|
|
163
|
-
}
|
|
164
|
-
currentExpression = getNullableFirstEntry(
|
|
165
|
-
currentExpression.parametersValues,
|
|
166
|
-
);
|
|
167
|
-
// Take care of chains of subtype
|
|
168
|
-
while (
|
|
169
|
-
currentExpression instanceof SimpleFunctionExpression &&
|
|
170
|
-
matchFunctionName(
|
|
171
|
-
currentExpression.functionName,
|
|
172
|
-
QUERY_BUILDER_SUPPORTED_FUNCTIONS.SUBTYPE,
|
|
173
|
-
)
|
|
174
|
-
) {
|
|
175
|
-
currentExpression = getNullableFirstEntry(
|
|
176
|
-
currentExpression.parametersValues,
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
return false;
|
|
181
|
-
};
|
|
182
|
-
|
|
183
175
|
/**
|
|
184
176
|
* This function updates the filter state when we DnD a property that can accept multiple values.
|
|
185
177
|
*/
|
|
@@ -742,6 +734,91 @@ const QueryBuilderFilterExistsConditionEditor = observer(
|
|
|
742
734
|
},
|
|
743
735
|
);
|
|
744
736
|
|
|
737
|
+
export const QueryBuilderFilterPropertyExpressionBadge = observer(
|
|
738
|
+
(props: {
|
|
739
|
+
rightConditionValue: FilterPropertyExpressionStateConditionValueState;
|
|
740
|
+
resetNode: () => void;
|
|
741
|
+
}) => {
|
|
742
|
+
const { rightConditionValue, resetNode } = props;
|
|
743
|
+
const type = rightConditionValue.type;
|
|
744
|
+
|
|
745
|
+
return (
|
|
746
|
+
<div className="query-builder-filter-property-expression-badge">
|
|
747
|
+
<div className="query-builder-filter-property-expression-badge__content">
|
|
748
|
+
<div
|
|
749
|
+
className={clsx(
|
|
750
|
+
'query-builder-filter-property-expression-badge__type',
|
|
751
|
+
{
|
|
752
|
+
'query-builder-filter-property-expression-badge__type--class':
|
|
753
|
+
type instanceof Class,
|
|
754
|
+
'query-builder-filter-property-expression-badge__type--enumeration':
|
|
755
|
+
type instanceof Enumeration,
|
|
756
|
+
'query-builder-filter-property-expression-badge__type--primitive':
|
|
757
|
+
type instanceof PrimitiveType,
|
|
758
|
+
},
|
|
759
|
+
)}
|
|
760
|
+
>
|
|
761
|
+
{renderPropertyTypeIcon(type)}
|
|
762
|
+
</div>
|
|
763
|
+
<div
|
|
764
|
+
className="query-builder-filter-property-expression-badge__property"
|
|
765
|
+
title={
|
|
766
|
+
rightConditionValue.propertyExpressionState.propertyExpression
|
|
767
|
+
.func.value.name
|
|
768
|
+
}
|
|
769
|
+
>
|
|
770
|
+
<QueryBuilderPropertyExpressionBadge
|
|
771
|
+
propertyExpressionState={
|
|
772
|
+
rightConditionValue.propertyExpressionState
|
|
773
|
+
}
|
|
774
|
+
/>
|
|
775
|
+
</div>
|
|
776
|
+
<QueryBuilderPropertyInfoTooltip
|
|
777
|
+
title={
|
|
778
|
+
rightConditionValue.propertyExpressionState.propertyExpression
|
|
779
|
+
.func.value.name
|
|
780
|
+
}
|
|
781
|
+
property={
|
|
782
|
+
rightConditionValue.propertyExpressionState.propertyExpression
|
|
783
|
+
.func.value
|
|
784
|
+
}
|
|
785
|
+
path={rightConditionValue.propertyExpressionState.path}
|
|
786
|
+
isMapped={true}
|
|
787
|
+
placement="bottom-end"
|
|
788
|
+
>
|
|
789
|
+
<div className="query-builder-filter-property-expression-badge__property__info">
|
|
790
|
+
<InfoCircleIcon />
|
|
791
|
+
</div>
|
|
792
|
+
</QueryBuilderPropertyInfoTooltip>
|
|
793
|
+
<button
|
|
794
|
+
className="query-builder-filter-property-expression-badge__action"
|
|
795
|
+
name="Reset"
|
|
796
|
+
title="Reset"
|
|
797
|
+
onClick={resetNode}
|
|
798
|
+
>
|
|
799
|
+
<RefreshIcon />
|
|
800
|
+
</button>
|
|
801
|
+
</div>
|
|
802
|
+
</div>
|
|
803
|
+
);
|
|
804
|
+
},
|
|
805
|
+
);
|
|
806
|
+
|
|
807
|
+
const canDropTypeOntoNodeValue = (
|
|
808
|
+
type: Type | undefined,
|
|
809
|
+
condition: FilterConditionState,
|
|
810
|
+
): boolean => {
|
|
811
|
+
const conditionOperator = condition.operator;
|
|
812
|
+
const conditionValueType =
|
|
813
|
+
condition.propertyExpressionState.propertyExpression.func.value.genericType
|
|
814
|
+
.value.rawType;
|
|
815
|
+
return (
|
|
816
|
+
!(conditionOperator instanceof QueryBuilderFilterOperator_In) &&
|
|
817
|
+
!(conditionOperator instanceof QueryBuilderFilterOperator_NotIn) &&
|
|
818
|
+
isTypeCompatibleForAssignment(type, conditionValueType)
|
|
819
|
+
);
|
|
820
|
+
};
|
|
821
|
+
|
|
745
822
|
const QueryBuilderFilterConditionEditor = observer(
|
|
746
823
|
(props: {
|
|
747
824
|
node: QueryBuilderFilterTreeConditionNodeData;
|
|
@@ -751,26 +828,114 @@ const QueryBuilderFilterConditionEditor = observer(
|
|
|
751
828
|
const graph =
|
|
752
829
|
node.condition.filterState.queryBuilderState.graphManagerState.graph;
|
|
753
830
|
const queryBuilderState = node.condition.filterState.queryBuilderState;
|
|
831
|
+
const rightConditionValue = node.condition.rightConditionValue;
|
|
754
832
|
const applicationStore = useApplicationStore();
|
|
755
|
-
|
|
756
|
-
node.condition.changeOperator(val);
|
|
833
|
+
|
|
757
834
|
// Drag and Drop on filter condition value
|
|
758
835
|
const handleDrop = useCallback(
|
|
759
|
-
(item:
|
|
760
|
-
const
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
836
|
+
(item: QueryBuilderFilterValueDropTarget, type: string): void => {
|
|
837
|
+
const itemType = getDNDItemType(item, type);
|
|
838
|
+
if (
|
|
839
|
+
itemType !== undefined &&
|
|
840
|
+
canDropTypeOntoNodeValue(itemType, node.condition)
|
|
841
|
+
) {
|
|
842
|
+
try {
|
|
843
|
+
if (
|
|
844
|
+
(type === QUERY_BUILDER_PROJECTION_COLUMN_DND_TYPE ||
|
|
845
|
+
type === QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY ||
|
|
846
|
+
type ===
|
|
847
|
+
QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY) &&
|
|
848
|
+
node.isExistsNodeChild
|
|
849
|
+
) {
|
|
850
|
+
throw new UnsupportedOperationError(
|
|
851
|
+
'Collection filter does not support property for filter condition value.',
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
if (type === QUERY_BUILDER_PROJECTION_COLUMN_DND_TYPE) {
|
|
855
|
+
const columnState = (
|
|
856
|
+
item as QueryBuilderProjectionColumnDragSource
|
|
857
|
+
).columnState;
|
|
858
|
+
if (
|
|
859
|
+
columnState instanceof QueryBuilderSimpleProjectionColumnState
|
|
860
|
+
) {
|
|
861
|
+
const columnPropertyExpression =
|
|
862
|
+
columnState.propertyExpressionState.propertyExpression;
|
|
863
|
+
if (isCollectionProperty(columnPropertyExpression)) {
|
|
864
|
+
throw new UnsupportedOperationError(
|
|
865
|
+
'Collection types are not supported for filter condition values.',
|
|
866
|
+
);
|
|
867
|
+
} else {
|
|
868
|
+
node.condition.buildRightConditionValueFromPropertyExpressionState(
|
|
869
|
+
new QueryBuilderPropertyExpressionState(
|
|
870
|
+
queryBuilderState,
|
|
871
|
+
cloneAbstractPropertyExpression(
|
|
872
|
+
columnPropertyExpression,
|
|
873
|
+
queryBuilderState.observerContext,
|
|
874
|
+
),
|
|
875
|
+
),
|
|
876
|
+
);
|
|
877
|
+
}
|
|
878
|
+
} else {
|
|
879
|
+
throw new UnsupportedOperationError(
|
|
880
|
+
'Derivation projection columns are not supported for filter condition values.',
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
} else if (
|
|
884
|
+
type === QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY ||
|
|
885
|
+
type === QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY
|
|
886
|
+
) {
|
|
887
|
+
const explorerNode = (item as QueryBuilderExplorerTreeDragSource)
|
|
888
|
+
.node;
|
|
889
|
+
const propertyExpressionState =
|
|
890
|
+
new QueryBuilderPropertyExpressionState(
|
|
891
|
+
queryBuilderState,
|
|
892
|
+
buildPropertyExpressionFromExplorerTreeNodeData(
|
|
893
|
+
explorerNode,
|
|
894
|
+
node.condition.filterState.queryBuilderState.explorerState,
|
|
895
|
+
),
|
|
896
|
+
);
|
|
897
|
+
if (
|
|
898
|
+
isCollectionProperty(propertyExpressionState.propertyExpression)
|
|
899
|
+
) {
|
|
900
|
+
throw new UnsupportedOperationError(
|
|
901
|
+
'Collection types are not supported for filter condition values.',
|
|
902
|
+
);
|
|
903
|
+
} else {
|
|
904
|
+
node.condition.buildRightConditionValueFromPropertyExpressionState(
|
|
905
|
+
propertyExpressionState,
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
} else if (type === QUERY_BUILDER_VARIABLE_DND_TYPE) {
|
|
909
|
+
const variable = (item as QueryBuilderVariableDragSource)
|
|
910
|
+
.variable;
|
|
911
|
+
node.condition.buildRightConditionValueFromValueSpec(variable);
|
|
912
|
+
} else {
|
|
913
|
+
applicationStore.notificationService.notifyWarning(
|
|
914
|
+
`Dragging and Dropping ${type} to filter panel is not supported.`,
|
|
915
|
+
);
|
|
916
|
+
}
|
|
917
|
+
} catch (error) {
|
|
918
|
+
assertErrorThrown(error);
|
|
919
|
+
applicationStore.notificationService.notifyWarning(error.message);
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
766
922
|
} else {
|
|
923
|
+
const conditionValueType =
|
|
924
|
+
node.condition.propertyExpressionState.propertyExpression.func.value
|
|
925
|
+
.genericType.value.rawType;
|
|
767
926
|
applicationStore.notificationService.notifyWarning(
|
|
768
|
-
`Incompatible parameter type ${
|
|
927
|
+
`Incompatible parameter type ${itemType?.name}. ${itemType?.name} is not compatible with type ${conditionValueType.name}.`,
|
|
769
928
|
);
|
|
770
929
|
}
|
|
771
930
|
},
|
|
772
|
-
[
|
|
931
|
+
[
|
|
932
|
+
applicationStore,
|
|
933
|
+
queryBuilderState,
|
|
934
|
+
node.condition,
|
|
935
|
+
node.isExistsNodeChild,
|
|
936
|
+
],
|
|
773
937
|
);
|
|
938
|
+
|
|
774
939
|
const [{ isFilterValueDragOver }, dropConnector] = useDrop<
|
|
775
940
|
QueryBuilderVariableDragSource,
|
|
776
941
|
void,
|
|
@@ -778,23 +943,54 @@ const QueryBuilderFilterConditionEditor = observer(
|
|
|
778
943
|
>(
|
|
779
944
|
() => ({
|
|
780
945
|
accept: CAN_DROP_FILTER_VALUE_DND_TYPES,
|
|
946
|
+
canDrop: (item, monitor): boolean =>
|
|
947
|
+
canDropTypeOntoNodeValue(
|
|
948
|
+
getDNDItemType(item, monitor.getItemType() as string),
|
|
949
|
+
node.condition,
|
|
950
|
+
),
|
|
781
951
|
drop: (item, monitor): void => {
|
|
782
952
|
if (!monitor.didDrop()) {
|
|
783
|
-
handleDrop(item);
|
|
953
|
+
handleDrop(item, monitor.getItemType() as string);
|
|
784
954
|
} // prevent drop event propagation to accomondate for nested DnD
|
|
785
955
|
},
|
|
786
956
|
collect: (monitor) => ({
|
|
787
|
-
isFilterValueDragOver:
|
|
957
|
+
isFilterValueDragOver:
|
|
958
|
+
monitor.isOver({ shallow: true }) && monitor.canDrop(),
|
|
788
959
|
}),
|
|
789
960
|
}),
|
|
790
961
|
[handleDrop],
|
|
791
962
|
);
|
|
792
963
|
|
|
964
|
+
const { isFilterValueDroppable } = useDragLayer((monitor) => ({
|
|
965
|
+
isFilterValueDroppable:
|
|
966
|
+
monitor.isDragging() &&
|
|
967
|
+
CAN_DROP_FILTER_VALUE_DND_TYPES.includes(
|
|
968
|
+
monitor.getItemType()?.toString() ?? '',
|
|
969
|
+
) &&
|
|
970
|
+
canDropTypeOntoNodeValue(
|
|
971
|
+
getDNDItemType(monitor.getItem(), monitor.getItemType() as string),
|
|
972
|
+
node.condition,
|
|
973
|
+
),
|
|
974
|
+
}));
|
|
975
|
+
|
|
976
|
+
// actions
|
|
977
|
+
const changeOperator = (val: QueryBuilderFilterOperator) => (): void =>
|
|
978
|
+
node.condition.changeOperator(val);
|
|
979
|
+
|
|
793
980
|
const resetNode = (): void => {
|
|
794
|
-
node.condition.
|
|
981
|
+
node.condition.buildRightConditionValueFromValueSpec(
|
|
795
982
|
node.condition.operator.getDefaultFilterConditionValue(node.condition),
|
|
796
983
|
);
|
|
797
984
|
};
|
|
985
|
+
|
|
986
|
+
const cleanUpReloadValues = (): void => {
|
|
987
|
+
node.condition.typeaheadSearchState.complete();
|
|
988
|
+
};
|
|
989
|
+
|
|
990
|
+
const changeValueSpecification = (val: ValueSpecification): void => {
|
|
991
|
+
node.condition.buildRightConditionValueFromValueSpec(val);
|
|
992
|
+
};
|
|
993
|
+
|
|
798
994
|
const debouncedTypeaheadSearch = useMemo(
|
|
799
995
|
() =>
|
|
800
996
|
debounce((inputValue: string) => {
|
|
@@ -809,12 +1005,7 @@ const QueryBuilderFilterConditionEditor = observer(
|
|
|
809
1005
|
}, 1000),
|
|
810
1006
|
[node, queryBuilderState.observerContext],
|
|
811
1007
|
);
|
|
812
|
-
|
|
813
|
-
node.condition.typeaheadSearchState.complete();
|
|
814
|
-
};
|
|
815
|
-
const changeValueSpecification = (val: ValueSpecification): void => {
|
|
816
|
-
node.condition.setValue(val);
|
|
817
|
-
};
|
|
1008
|
+
|
|
818
1009
|
const selectorConfig = {
|
|
819
1010
|
values: node.condition.typeaheadSearchResults,
|
|
820
1011
|
isLoading: node.condition.typeaheadSearchState.isInProgress,
|
|
@@ -822,6 +1013,69 @@ const QueryBuilderFilterConditionEditor = observer(
|
|
|
822
1013
|
cleanUpReloadValues,
|
|
823
1014
|
};
|
|
824
1015
|
|
|
1016
|
+
const renderRightValue = (): React.ReactNode => {
|
|
1017
|
+
if (
|
|
1018
|
+
rightConditionValue instanceof FilterValueSpecConditionValueState &&
|
|
1019
|
+
rightConditionValue.value
|
|
1020
|
+
) {
|
|
1021
|
+
return (
|
|
1022
|
+
<div
|
|
1023
|
+
ref={dropConnector}
|
|
1024
|
+
data-testid={
|
|
1025
|
+
QUERY_BUILDER_TEST_ID.QUERY_BUILDER_FILTER_TREE_CONDITION_NODE_VALUE
|
|
1026
|
+
}
|
|
1027
|
+
className="query-builder-filter-tree__condition-node__value"
|
|
1028
|
+
>
|
|
1029
|
+
<PanelEntryDropZonePlaceholder
|
|
1030
|
+
isDragOver={isFilterValueDragOver}
|
|
1031
|
+
isDroppable={isFilterValueDroppable}
|
|
1032
|
+
label="Change Filter Value"
|
|
1033
|
+
>
|
|
1034
|
+
<EditableBasicValueSpecificationEditor
|
|
1035
|
+
valueSpecification={rightConditionValue.value}
|
|
1036
|
+
setValueSpecification={changeValueSpecification}
|
|
1037
|
+
graph={graph}
|
|
1038
|
+
observerContext={queryBuilderState.observerContext}
|
|
1039
|
+
typeCheckOption={{
|
|
1040
|
+
expectedType:
|
|
1041
|
+
node.condition.propertyExpressionState.propertyExpression
|
|
1042
|
+
.func.value.genericType.value.rawType,
|
|
1043
|
+
}}
|
|
1044
|
+
resetValue={resetNode}
|
|
1045
|
+
selectorConfig={selectorConfig}
|
|
1046
|
+
isConstant={queryBuilderState.constantState.isValueSpecConstant(
|
|
1047
|
+
rightConditionValue.value,
|
|
1048
|
+
)}
|
|
1049
|
+
initializeAsEditable={node.isNewlyAdded}
|
|
1050
|
+
/>
|
|
1051
|
+
</PanelEntryDropZonePlaceholder>
|
|
1052
|
+
</div>
|
|
1053
|
+
);
|
|
1054
|
+
} else if (
|
|
1055
|
+
rightConditionValue instanceof
|
|
1056
|
+
FilterPropertyExpressionStateConditionValueState
|
|
1057
|
+
) {
|
|
1058
|
+
return (
|
|
1059
|
+
<div
|
|
1060
|
+
ref={dropConnector}
|
|
1061
|
+
className="query-builder-filter-tree__condition-node__value"
|
|
1062
|
+
>
|
|
1063
|
+
<PanelEntryDropZonePlaceholder
|
|
1064
|
+
isDragOver={isFilterValueDragOver}
|
|
1065
|
+
isDroppable={isFilterValueDroppable}
|
|
1066
|
+
label="Change Filter Value"
|
|
1067
|
+
>
|
|
1068
|
+
<QueryBuilderFilterPropertyExpressionBadge
|
|
1069
|
+
rightConditionValue={rightConditionValue}
|
|
1070
|
+
resetNode={resetNode}
|
|
1071
|
+
/>
|
|
1072
|
+
</PanelEntryDropZonePlaceholder>
|
|
1073
|
+
</div>
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
return null;
|
|
1077
|
+
};
|
|
1078
|
+
|
|
825
1079
|
useEffect(() => {
|
|
826
1080
|
node.setIsNewlyAdded(false);
|
|
827
1081
|
}, [node]);
|
|
@@ -834,8 +1088,8 @@ const QueryBuilderFilterConditionEditor = observer(
|
|
|
834
1088
|
}
|
|
835
1089
|
>
|
|
836
1090
|
<PanelEntryDropZonePlaceholder
|
|
837
|
-
isDragOver={isDragOver}
|
|
838
|
-
|
|
1091
|
+
isDragOver={isDragOver && !isFilterValueDragOver}
|
|
1092
|
+
alwaysShowChildren={true}
|
|
839
1093
|
>
|
|
840
1094
|
<div className="query-builder-filter-tree__condition-node">
|
|
841
1095
|
<div className="query-builder-filter-tree__condition-node__property">
|
|
@@ -872,39 +1126,7 @@ const QueryBuilderFilterConditionEditor = observer(
|
|
|
872
1126
|
<CaretDownIcon />
|
|
873
1127
|
</div>
|
|
874
1128
|
</ControlledDropdownMenu>
|
|
875
|
-
{
|
|
876
|
-
<div
|
|
877
|
-
ref={dropConnector}
|
|
878
|
-
data-testid={
|
|
879
|
-
QUERY_BUILDER_TEST_ID.QUERY_BUILDER_FILTER_TREE_CONDITION_NODE_VALUE
|
|
880
|
-
}
|
|
881
|
-
className="query-builder-filter-tree__condition-node__value"
|
|
882
|
-
>
|
|
883
|
-
<PanelEntryDropZonePlaceholder
|
|
884
|
-
isDragOver={isFilterValueDragOver}
|
|
885
|
-
label="Change Filter Value"
|
|
886
|
-
>
|
|
887
|
-
<EditableBasicValueSpecificationEditor
|
|
888
|
-
valueSpecification={node.condition.value}
|
|
889
|
-
setValueSpecification={changeValueSpecification}
|
|
890
|
-
graph={graph}
|
|
891
|
-
observerContext={queryBuilderState.observerContext}
|
|
892
|
-
typeCheckOption={{
|
|
893
|
-
expectedType:
|
|
894
|
-
node.condition.propertyExpressionState
|
|
895
|
-
.propertyExpression.func.value.genericType.value
|
|
896
|
-
.rawType,
|
|
897
|
-
}}
|
|
898
|
-
resetValue={resetNode}
|
|
899
|
-
selectorConfig={selectorConfig}
|
|
900
|
-
isConstant={queryBuilderState.constantState.isValueSpecConstant(
|
|
901
|
-
node.condition.value,
|
|
902
|
-
)}
|
|
903
|
-
initializeAsEditable={node.isNewlyAdded}
|
|
904
|
-
/>
|
|
905
|
-
</PanelEntryDropZonePlaceholder>
|
|
906
|
-
</div>
|
|
907
|
-
)}
|
|
1129
|
+
{renderRightValue()}
|
|
908
1130
|
</div>
|
|
909
1131
|
</PanelEntryDropZonePlaceholder>
|
|
910
1132
|
</div>
|
|
@@ -1005,7 +1227,7 @@ const QueryBuilderFilterTreeNodeContainer = observer(
|
|
|
1005
1227
|
|
|
1006
1228
|
// Drag and Drop
|
|
1007
1229
|
const handleDrop = useCallback(
|
|
1008
|
-
(item:
|
|
1230
|
+
(item: QueryBuilderFilterNodeDropTarget, type: string): void => {
|
|
1009
1231
|
if (QUERY_BUILDER_FILTER_DND_TYPE.CONDITION === type) {
|
|
1010
1232
|
const nodeBeingDragged = (
|
|
1011
1233
|
item as QueryBuilderFilterConditionDragSource
|
|
@@ -1041,10 +1263,13 @@ const QueryBuilderFilterTreeNodeContainer = observer(
|
|
|
1041
1263
|
.columnState instanceof
|
|
1042
1264
|
QueryBuilderSimpleProjectionColumnState
|
|
1043
1265
|
) {
|
|
1044
|
-
propertyExpression = (
|
|
1045
|
-
(
|
|
1046
|
-
|
|
1047
|
-
|
|
1266
|
+
propertyExpression = cloneAbstractPropertyExpression(
|
|
1267
|
+
(
|
|
1268
|
+
(item as QueryBuilderProjectionColumnDragSource)
|
|
1269
|
+
.columnState as QueryBuilderSimpleProjectionColumnState
|
|
1270
|
+
).propertyExpressionState.propertyExpression,
|
|
1271
|
+
queryBuilderState.observerContext,
|
|
1272
|
+
);
|
|
1048
1273
|
} else {
|
|
1049
1274
|
throw new UnsupportedOperationError(
|
|
1050
1275
|
`Dragging and Dropping derivation projection column is not supported.`,
|
|
@@ -1089,12 +1314,12 @@ const QueryBuilderFilterTreeNodeContainer = observer(
|
|
|
1089
1314
|
}
|
|
1090
1315
|
}
|
|
1091
1316
|
},
|
|
1092
|
-
[applicationStore, filterState, node],
|
|
1317
|
+
[applicationStore, filterState, node, queryBuilderState.observerContext],
|
|
1093
1318
|
);
|
|
1094
|
-
const [{ isDragOver }, dropConnector] = useDrop<
|
|
1319
|
+
const [{ isDragOver, deepIsDragOver }, dropConnector] = useDrop<
|
|
1095
1320
|
QueryBuilderFilterConditionDragSource,
|
|
1096
1321
|
void,
|
|
1097
|
-
{ isDragOver: boolean }
|
|
1322
|
+
{ isDragOver: boolean; deepIsDragOver: boolean }
|
|
1098
1323
|
>(
|
|
1099
1324
|
() => ({
|
|
1100
1325
|
accept:
|
|
@@ -1108,6 +1333,7 @@ const QueryBuilderFilterTreeNodeContainer = observer(
|
|
|
1108
1333
|
},
|
|
1109
1334
|
collect: (monitor) => ({
|
|
1110
1335
|
isDragOver: monitor.isOver({ shallow: true }),
|
|
1336
|
+
deepIsDragOver: monitor.isOver({ shallow: false }),
|
|
1111
1337
|
}),
|
|
1112
1338
|
}),
|
|
1113
1339
|
[handleDrop],
|
|
@@ -1222,7 +1448,7 @@ const QueryBuilderFilterTreeNodeContainer = observer(
|
|
|
1222
1448
|
{node instanceof QueryBuilderFilterTreeConditionNodeData && (
|
|
1223
1449
|
<QueryBuilderFilterConditionEditor
|
|
1224
1450
|
node={node}
|
|
1225
|
-
isDragOver={
|
|
1451
|
+
isDragOver={deepIsDragOver}
|
|
1226
1452
|
/>
|
|
1227
1453
|
)}
|
|
1228
1454
|
{node instanceof QueryBuilderFilterTreeBlankConditionNodeData && (
|
|
@@ -1430,7 +1656,7 @@ export const QueryBuilderFilterPanel = observer(
|
|
|
1430
1656
|
|
|
1431
1657
|
// Drag and Drop
|
|
1432
1658
|
const handleDrop = useCallback(
|
|
1433
|
-
(item:
|
|
1659
|
+
(item: QueryBuilderFilterNodeDropTarget, type: string): void => {
|
|
1434
1660
|
try {
|
|
1435
1661
|
let propertyExpression;
|
|
1436
1662
|
if (type === QUERY_BUILDER_PROJECTION_COLUMN_DND_TYPE) {
|
|
@@ -1438,10 +1664,13 @@ export const QueryBuilderFilterPanel = observer(
|
|
|
1438
1664
|
(item as QueryBuilderProjectionColumnDragSource)
|
|
1439
1665
|
.columnState instanceof QueryBuilderSimpleProjectionColumnState
|
|
1440
1666
|
) {
|
|
1441
|
-
propertyExpression = (
|
|
1442
|
-
(
|
|
1443
|
-
|
|
1444
|
-
|
|
1667
|
+
propertyExpression = cloneAbstractPropertyExpression(
|
|
1668
|
+
(
|
|
1669
|
+
(item as QueryBuilderProjectionColumnDragSource)
|
|
1670
|
+
.columnState as QueryBuilderSimpleProjectionColumnState
|
|
1671
|
+
).propertyExpressionState.propertyExpression,
|
|
1672
|
+
queryBuilderState.observerContext,
|
|
1673
|
+
);
|
|
1445
1674
|
} else {
|
|
1446
1675
|
throw new UnsupportedOperationError(
|
|
1447
1676
|
`Dragging and Dropping derivation projection column is not supported.`,
|
|
@@ -1463,7 +1692,7 @@ export const QueryBuilderFilterPanel = observer(
|
|
|
1463
1692
|
return;
|
|
1464
1693
|
}
|
|
1465
1694
|
},
|
|
1466
|
-
[applicationStore, filterState],
|
|
1695
|
+
[applicationStore, filterState, queryBuilderState.observerContext],
|
|
1467
1696
|
);
|
|
1468
1697
|
|
|
1469
1698
|
const [{ isDragOver }, dropTargetConnector] = useDrop<
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2020-present, Goldman Sachs
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { Type } from '@finos/legend-graph';
|
|
18
|
+
import {
|
|
19
|
+
QUERY_BUILDER_EXPLORER_TREE_DND_TYPE,
|
|
20
|
+
type QueryBuilderExplorerTreeDragSource,
|
|
21
|
+
} from '../../stores/explorer/QueryBuilderExplorerState.js';
|
|
22
|
+
import {
|
|
23
|
+
QUERY_BUILDER_PROJECTION_COLUMN_DND_TYPE,
|
|
24
|
+
type QueryBuilderProjectionColumnDragSource,
|
|
25
|
+
} from '../../stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.js';
|
|
26
|
+
import type { QueryBuilderFilterValueDropTarget } from '../../stores/filter/QueryBuilderFilterState.js';
|
|
27
|
+
import {
|
|
28
|
+
QUERY_BUILDER_VARIABLE_DND_TYPE,
|
|
29
|
+
type QueryBuilderVariableDragSource,
|
|
30
|
+
} from './BasicValueSpecificationEditor.js';
|
|
31
|
+
|
|
32
|
+
export const getDNDItemType = (
|
|
33
|
+
item: QueryBuilderFilterValueDropTarget,
|
|
34
|
+
type: string,
|
|
35
|
+
): Type | undefined => {
|
|
36
|
+
switch (type) {
|
|
37
|
+
case QUERY_BUILDER_PROJECTION_COLUMN_DND_TYPE:
|
|
38
|
+
return (
|
|
39
|
+
item as QueryBuilderProjectionColumnDragSource
|
|
40
|
+
).columnState.getColumnType();
|
|
41
|
+
case QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.ENUM_PROPERTY:
|
|
42
|
+
case QUERY_BUILDER_EXPLORER_TREE_DND_TYPE.PRIMITIVE_PROPERTY:
|
|
43
|
+
return (item as QueryBuilderExplorerTreeDragSource).node.property
|
|
44
|
+
.genericType.value.rawType;
|
|
45
|
+
case QUERY_BUILDER_VARIABLE_DND_TYPE:
|
|
46
|
+
return (item as QueryBuilderVariableDragSource).variable.genericType
|
|
47
|
+
?.value.rawType;
|
|
48
|
+
default:
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
@@ -91,6 +91,8 @@ export enum QUERY_BUILDER_STATE_HASH_STRUCTURE {
|
|
|
91
91
|
FILTER_TREE_CONDIITION_NODE_DATA = 'FILTER_TREE_CONDITION_NODE_DATA',
|
|
92
92
|
FILTER_TREE_BLANK_CONDITION_NODE_DATA = 'FILTER_TREE_BLANK_CONDITION_NODE_DATA',
|
|
93
93
|
FILTER_CONDITION_STATE = 'FILTER_CONDITION_STATE',
|
|
94
|
+
FILTER_CONDITION_RIGHT_VALUE = 'FILTER_CONDITION_RIGHT_VALUE',
|
|
95
|
+
FILTER_CONDITION_RIGHT_VALUE_SPEC = 'FILTER_CONDITION_RIGHT_VALUE_SPEC',
|
|
94
96
|
FILTER_OPERATOR_CONTAIN = 'FILTER_OPERATOR_CONTAIN',
|
|
95
97
|
FILTER_OPERATOR_NOT_CONTAIN = 'FILTER_OPERATOR_NOT_CONTAIN',
|
|
96
98
|
FILTER_OPERATOR_END_WITH = 'FILTER_OPERATOR_END_WITH',
|