@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
package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_In.ts
CHANGED
|
@@ -79,7 +79,7 @@ export class QueryBuilderPostFilterOperator_In
|
|
|
79
79
|
postFilterConditionState.leftConditionValue.getColumnType(),
|
|
80
80
|
);
|
|
81
81
|
const rightSide = postFilterConditionState.rightConditionValue;
|
|
82
|
-
// `in`/`not in`
|
|
82
|
+
// `in`/`not in` does not support right hand value being column state as the multipliticy for columns are [0..1]
|
|
83
83
|
if (rightSide instanceof PostFilterValueSpecConditionValueState) {
|
|
84
84
|
const valueSpec = rightSide.value;
|
|
85
85
|
if (valueSpec instanceof CollectionInstanceValue) {
|
|
@@ -38,12 +38,15 @@ import { QueryBuilderPropertyExpressionState } from '../QueryBuilderPropertyEdit
|
|
|
38
38
|
import type { QueryBuilderState } from '../QueryBuilderState.js';
|
|
39
39
|
import {
|
|
40
40
|
type ExecutionResult,
|
|
41
|
-
|
|
41
|
+
AbstractPropertyExpression,
|
|
42
42
|
type ValueSpecification,
|
|
43
43
|
type VariableExpression,
|
|
44
|
+
type Type,
|
|
44
45
|
observe_ValueSpecification,
|
|
45
46
|
CollectionInstanceValue,
|
|
46
47
|
InstanceValue,
|
|
48
|
+
SimpleFunctionExpression,
|
|
49
|
+
matchFunctionName,
|
|
47
50
|
} from '@finos/legend-graph';
|
|
48
51
|
import { DEFAULT_LAMBDA_VARIABLE_NAME } from '../QueryBuilderConfig.js';
|
|
49
52
|
import type { QueryBuilderProjectionColumnDragSource } from '../fetch-structure/tds/projection/QueryBuilderProjectionColumnState.js';
|
|
@@ -56,10 +59,14 @@ import type { QueryBuilderFilterOperator } from './QueryBuilderFilterOperator.js
|
|
|
56
59
|
import { QUERY_BUILDER_GROUP_OPERATION } from '../QueryBuilderGroupOperationHelper.js';
|
|
57
60
|
import { QUERY_BUILDER_STATE_HASH_STRUCTURE } from '../QueryBuilderStateHashUtils.js';
|
|
58
61
|
import {
|
|
62
|
+
getCollectionValueSpecificationType,
|
|
63
|
+
getNonCollectionValueSpecificationType,
|
|
59
64
|
isValidInstanceValue,
|
|
60
65
|
isValueExpressionReferencedInValue,
|
|
61
66
|
} from '../QueryBuilderValueSpecificationHelper.js';
|
|
62
67
|
import { instanceValue_setValues } from '../shared/ValueSpecificationModifierHelper.js';
|
|
68
|
+
import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '../../graph/QueryBuilderMetaModelConst.js';
|
|
69
|
+
import type { QueryBuilderVariableDragSource } from '../../components/shared/BasicValueSpecificationEditor.js';
|
|
63
70
|
|
|
64
71
|
export enum QUERY_BUILDER_FILTER_DND_TYPE {
|
|
65
72
|
GROUP_CONDITION = 'QUERY_BUILDER_FILTER_DND_TYPE.GROUP_CONDITION',
|
|
@@ -71,18 +78,167 @@ export interface QueryBuilderFilterConditionDragSource {
|
|
|
71
78
|
node: QueryBuilderFilterTreeNodeData;
|
|
72
79
|
}
|
|
73
80
|
|
|
74
|
-
export type
|
|
81
|
+
export type QueryBuilderFilterNodeDropTarget =
|
|
75
82
|
| QueryBuilderExplorerTreeDragSource
|
|
76
83
|
| QueryBuilderProjectionColumnDragSource
|
|
77
84
|
| QueryBuilderFilterConditionDragSource;
|
|
85
|
+
|
|
86
|
+
export type QueryBuilderFilterValueDropTarget =
|
|
87
|
+
| QueryBuilderVariableDragSource
|
|
88
|
+
| QueryBuilderProjectionColumnDragSource
|
|
89
|
+
| QueryBuilderExplorerTreeDragSource;
|
|
90
|
+
|
|
78
91
|
export type QueryBuilderFilterConditionRearrangeDropTarget =
|
|
79
92
|
QueryBuilderFilterConditionDragSource;
|
|
80
93
|
|
|
94
|
+
export const isCollectionProperty = (
|
|
95
|
+
propertyExpression: AbstractPropertyExpression,
|
|
96
|
+
): boolean => {
|
|
97
|
+
let currentExpression: ValueSpecification | undefined = propertyExpression;
|
|
98
|
+
while (currentExpression instanceof AbstractPropertyExpression) {
|
|
99
|
+
// Check if the property chain can results in column that have multiple values
|
|
100
|
+
if (
|
|
101
|
+
currentExpression.func.value.multiplicity.upperBound === undefined ||
|
|
102
|
+
currentExpression.func.value.multiplicity.upperBound > 1
|
|
103
|
+
) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
currentExpression = getNullableFirstEntry(
|
|
107
|
+
currentExpression.parametersValues,
|
|
108
|
+
);
|
|
109
|
+
// Take care of chains of subtype
|
|
110
|
+
while (
|
|
111
|
+
currentExpression instanceof SimpleFunctionExpression &&
|
|
112
|
+
matchFunctionName(
|
|
113
|
+
currentExpression.functionName,
|
|
114
|
+
QUERY_BUILDER_SUPPORTED_FUNCTIONS.SUBTYPE,
|
|
115
|
+
)
|
|
116
|
+
) {
|
|
117
|
+
currentExpression = getNullableFirstEntry(
|
|
118
|
+
currentExpression.parametersValues,
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export abstract class FilterConditionValueState implements Hashable {
|
|
126
|
+
conditionState: FilterConditionState;
|
|
127
|
+
|
|
128
|
+
constructor(conditionState: FilterConditionState) {
|
|
129
|
+
this.conditionState = conditionState;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
get type(): Type | undefined {
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
get isCollection(): boolean {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
get hashCode(): string {
|
|
141
|
+
return hashArray([
|
|
142
|
+
QUERY_BUILDER_STATE_HASH_STRUCTURE.FILTER_CONDITION_RIGHT_VALUE,
|
|
143
|
+
]);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// This class is used to represent the value of a filter condition when the value is
|
|
148
|
+
// a ValueSpecification.
|
|
149
|
+
export class FilterValueSpecConditionValueState extends FilterConditionValueState {
|
|
150
|
+
value?: ValueSpecification | undefined;
|
|
151
|
+
|
|
152
|
+
constructor(
|
|
153
|
+
conditionState: FilterConditionState,
|
|
154
|
+
value?: ValueSpecification | undefined,
|
|
155
|
+
) {
|
|
156
|
+
super(conditionState);
|
|
157
|
+
makeObservable(this, {
|
|
158
|
+
value: observable,
|
|
159
|
+
setValue: action,
|
|
160
|
+
});
|
|
161
|
+
this.value = this.setValue(value);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
override get type(): Type | undefined {
|
|
165
|
+
if (this.value instanceof CollectionInstanceValue) {
|
|
166
|
+
return getCollectionValueSpecificationType(
|
|
167
|
+
this.conditionState.filterState.queryBuilderState.graphManagerState
|
|
168
|
+
.graph,
|
|
169
|
+
this.value.values,
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
return this.value
|
|
173
|
+
? getNonCollectionValueSpecificationType(this.value)
|
|
174
|
+
: undefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
setValue(
|
|
178
|
+
val: ValueSpecification | undefined,
|
|
179
|
+
): ValueSpecification | undefined {
|
|
180
|
+
this.value = val
|
|
181
|
+
? observe_ValueSpecification(
|
|
182
|
+
val,
|
|
183
|
+
this.conditionState.filterState.queryBuilderState.observerContext,
|
|
184
|
+
)
|
|
185
|
+
: undefined;
|
|
186
|
+
return this.value;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
override get isCollection(): boolean {
|
|
190
|
+
return this.value instanceof CollectionInstanceValue;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
override get hashCode(): string {
|
|
194
|
+
return hashArray([
|
|
195
|
+
QUERY_BUILDER_STATE_HASH_STRUCTURE.FILTER_CONDITION_RIGHT_VALUE_SPEC,
|
|
196
|
+
this.value,
|
|
197
|
+
]);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// This class is used to represent the value of a filter condition when the value is a
|
|
202
|
+
// PropertyExpressionState (which comes from DND a property node from the explorer tree
|
|
203
|
+
// or a column from the fetch structure panel).
|
|
204
|
+
export class FilterPropertyExpressionStateConditionValueState extends FilterConditionValueState {
|
|
205
|
+
propertyExpressionState: QueryBuilderPropertyExpressionState;
|
|
206
|
+
|
|
207
|
+
constructor(
|
|
208
|
+
conditionState: FilterConditionState,
|
|
209
|
+
propertyExpressionState: QueryBuilderPropertyExpressionState,
|
|
210
|
+
) {
|
|
211
|
+
super(conditionState);
|
|
212
|
+
makeObservable(this, {
|
|
213
|
+
propertyExpressionState: observable,
|
|
214
|
+
changePropertyExpressionState: action,
|
|
215
|
+
});
|
|
216
|
+
this.propertyExpressionState = propertyExpressionState;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
override get type(): Type {
|
|
220
|
+
return this.propertyExpressionState.propertyExpression.func.value
|
|
221
|
+
.genericType.value.rawType;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
override get isCollection(): boolean {
|
|
225
|
+
return isCollectionProperty(
|
|
226
|
+
this.propertyExpressionState.propertyExpression,
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
changePropertyExpressionState(
|
|
231
|
+
propertyExpressionState: QueryBuilderPropertyExpressionState,
|
|
232
|
+
): void {
|
|
233
|
+
this.propertyExpressionState = propertyExpressionState;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
81
237
|
export class FilterConditionState implements Hashable {
|
|
82
238
|
readonly filterState: QueryBuilderFilterState;
|
|
83
239
|
propertyExpressionState: QueryBuilderPropertyExpressionState;
|
|
84
240
|
operator!: QueryBuilderFilterOperator;
|
|
85
|
-
|
|
241
|
+
rightConditionValue?: FilterConditionValueState | undefined;
|
|
86
242
|
existsLambdaParamNames: string[] = [];
|
|
87
243
|
typeaheadSearchResults: string[] | undefined;
|
|
88
244
|
typeaheadSearchState = ActionState.create();
|
|
@@ -94,16 +250,17 @@ export class FilterConditionState implements Hashable {
|
|
|
94
250
|
makeObservable(this, {
|
|
95
251
|
propertyExpressionState: observable,
|
|
96
252
|
operator: observable,
|
|
97
|
-
|
|
253
|
+
rightConditionValue: observable,
|
|
98
254
|
existsLambdaParamNames: observable,
|
|
99
255
|
typeaheadSearchResults: observable,
|
|
100
|
-
operators: computed,
|
|
101
|
-
changeProperty: action,
|
|
102
256
|
changeOperator: action,
|
|
103
257
|
setOperator: action,
|
|
104
|
-
|
|
258
|
+
setRightConditionValue: action,
|
|
105
259
|
addExistsLambdaParamNames: action,
|
|
260
|
+
buildRightConditionValueFromValueSpec: action,
|
|
261
|
+
buildRightConditionValueFromPropertyExpressionState: action,
|
|
106
262
|
handleTypeaheadSearch: flow,
|
|
263
|
+
operators: computed,
|
|
107
264
|
hashCode: computed,
|
|
108
265
|
});
|
|
109
266
|
|
|
@@ -119,7 +276,9 @@ export class FilterConditionState implements Hashable {
|
|
|
119
276
|
`Can't find an operator for property '${this.propertyExpressionState.path}': no operators registered`,
|
|
120
277
|
);
|
|
121
278
|
this.operator = this.operators[0] as QueryBuilderFilterOperator;
|
|
122
|
-
this.
|
|
279
|
+
this.buildRightConditionValueFromValueSpec(
|
|
280
|
+
this.operator.getDefaultFilterConditionValue(this),
|
|
281
|
+
);
|
|
123
282
|
}
|
|
124
283
|
|
|
125
284
|
get operators(): QueryBuilderFilterOperator[] {
|
|
@@ -131,10 +290,14 @@ export class FilterConditionState implements Hashable {
|
|
|
131
290
|
*handleTypeaheadSearch(
|
|
132
291
|
searchValue?: ValueSpecification | undefined,
|
|
133
292
|
): GeneratorFn<void> {
|
|
134
|
-
const value = searchValue ?? this.value;
|
|
135
293
|
try {
|
|
136
294
|
this.typeaheadSearchState.inProgress();
|
|
137
295
|
this.typeaheadSearchResults = undefined;
|
|
296
|
+
const rightConditionValue = guaranteeType(
|
|
297
|
+
this.rightConditionValue,
|
|
298
|
+
FilterValueSpecConditionValueState,
|
|
299
|
+
);
|
|
300
|
+
const value = searchValue ?? rightConditionValue.value;
|
|
138
301
|
if (performTypeahead(value)) {
|
|
139
302
|
const result =
|
|
140
303
|
(yield this.filterState.queryBuilderState.graphManagerState.graphManager.runQuery(
|
|
@@ -164,65 +327,34 @@ export class FilterConditionState implements Hashable {
|
|
|
164
327
|
}
|
|
165
328
|
}
|
|
166
329
|
|
|
167
|
-
changeProperty(propertyExpression: AbstractPropertyExpression): void {
|
|
168
|
-
try {
|
|
169
|
-
// first, check if the new property is supported
|
|
170
|
-
new FilterConditionState(this.filterState, propertyExpression);
|
|
171
|
-
} catch (error) {
|
|
172
|
-
assertErrorThrown(error);
|
|
173
|
-
this.filterState.queryBuilderState.applicationStore.notificationService.notifyError(
|
|
174
|
-
error,
|
|
175
|
-
);
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// observe the property expression
|
|
180
|
-
observe_ValueSpecification(
|
|
181
|
-
propertyExpression,
|
|
182
|
-
this.filterState.queryBuilderState.observerContext,
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
this.propertyExpressionState = new QueryBuilderPropertyExpressionState(
|
|
186
|
-
this.filterState.queryBuilderState,
|
|
187
|
-
propertyExpression,
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
const newCompatibleOperators = this.operators;
|
|
191
|
-
assertTrue(
|
|
192
|
-
newCompatibleOperators.length !== 0,
|
|
193
|
-
`Can't find an operator for property '${this.propertyExpressionState.path}': no operators registered`,
|
|
194
|
-
);
|
|
195
|
-
if (!newCompatibleOperators.includes(this.operator)) {
|
|
196
|
-
this.changeOperator(
|
|
197
|
-
newCompatibleOperators[0] as QueryBuilderFilterOperator,
|
|
198
|
-
);
|
|
199
|
-
} else if (!this.operator.isCompatibleWithFilterConditionValue(this)) {
|
|
200
|
-
this.setValue(this.operator.getDefaultFilterConditionValue(this));
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
330
|
changeOperator(val: QueryBuilderFilterOperator): void {
|
|
205
331
|
this.setOperator(val);
|
|
206
332
|
if (!this.operator.isCompatibleWithFilterConditionValue(this)) {
|
|
207
333
|
let defaultValue = this.operator.getDefaultFilterConditionValue(this);
|
|
334
|
+
// Don't allow invalid InstanceValues or empty strings to be set as list element
|
|
208
335
|
if (
|
|
209
336
|
defaultValue instanceof CollectionInstanceValue &&
|
|
210
|
-
this.
|
|
211
|
-
|
|
337
|
+
this.rightConditionValue instanceof
|
|
338
|
+
FilterValueSpecConditionValueState &&
|
|
339
|
+
this.rightConditionValue.value instanceof InstanceValue &&
|
|
340
|
+
isValidInstanceValue(this.rightConditionValue.value) &&
|
|
341
|
+
this.rightConditionValue.value.values[0] !== ''
|
|
212
342
|
) {
|
|
213
343
|
instanceValue_setValues(
|
|
214
344
|
defaultValue,
|
|
215
|
-
[this.value],
|
|
345
|
+
[this.rightConditionValue.value],
|
|
216
346
|
this.filterState.queryBuilderState.observerContext,
|
|
217
347
|
);
|
|
218
348
|
} else if (
|
|
219
349
|
defaultValue instanceof InstanceValue &&
|
|
220
|
-
this.
|
|
221
|
-
|
|
350
|
+
this.rightConditionValue instanceof
|
|
351
|
+
FilterValueSpecConditionValueState &&
|
|
352
|
+
this.rightConditionValue.value instanceof CollectionInstanceValue &&
|
|
353
|
+
this.rightConditionValue.value.values.length
|
|
222
354
|
) {
|
|
223
|
-
defaultValue = this.value.values[0];
|
|
355
|
+
defaultValue = this.rightConditionValue.value.values[0];
|
|
224
356
|
}
|
|
225
|
-
this.
|
|
357
|
+
this.buildRightConditionValueFromValueSpec(defaultValue);
|
|
226
358
|
}
|
|
227
359
|
}
|
|
228
360
|
|
|
@@ -230,24 +362,53 @@ export class FilterConditionState implements Hashable {
|
|
|
230
362
|
this.operator = val;
|
|
231
363
|
}
|
|
232
364
|
|
|
233
|
-
|
|
234
|
-
this.
|
|
235
|
-
? observe_ValueSpecification(
|
|
236
|
-
val,
|
|
237
|
-
this.filterState.queryBuilderState.observerContext,
|
|
238
|
-
)
|
|
239
|
-
: undefined;
|
|
365
|
+
setRightConditionValue(val: FilterConditionValueState | undefined): void {
|
|
366
|
+
this.rightConditionValue = val;
|
|
240
367
|
}
|
|
241
368
|
|
|
242
369
|
addExistsLambdaParamNames(val: string): void {
|
|
243
370
|
this.existsLambdaParamNames.push(val);
|
|
244
371
|
}
|
|
245
372
|
|
|
373
|
+
buildRightConditionValueFromValueSpec(
|
|
374
|
+
val: ValueSpecification | undefined,
|
|
375
|
+
): void {
|
|
376
|
+
if (
|
|
377
|
+
this.rightConditionValue instanceof FilterValueSpecConditionValueState
|
|
378
|
+
) {
|
|
379
|
+
this.rightConditionValue.setValue(val);
|
|
380
|
+
} else {
|
|
381
|
+
this.setRightConditionValue(
|
|
382
|
+
new FilterValueSpecConditionValueState(this, val),
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
buildRightConditionValueFromPropertyExpressionState(
|
|
388
|
+
propertyExpressionState: QueryBuilderPropertyExpressionState,
|
|
389
|
+
): void {
|
|
390
|
+
if (
|
|
391
|
+
this.rightConditionValue instanceof
|
|
392
|
+
FilterPropertyExpressionStateConditionValueState
|
|
393
|
+
) {
|
|
394
|
+
this.rightConditionValue.changePropertyExpressionState(
|
|
395
|
+
propertyExpressionState,
|
|
396
|
+
);
|
|
397
|
+
} else {
|
|
398
|
+
this.setRightConditionValue(
|
|
399
|
+
new FilterPropertyExpressionStateConditionValueState(
|
|
400
|
+
this,
|
|
401
|
+
propertyExpressionState,
|
|
402
|
+
),
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
246
407
|
get hashCode(): string {
|
|
247
408
|
return hashArray([
|
|
248
409
|
QUERY_BUILDER_STATE_HASH_STRUCTURE.FILTER_CONDITION_STATE,
|
|
249
410
|
this.propertyExpressionState,
|
|
250
|
-
this.
|
|
411
|
+
this.rightConditionValue ?? '',
|
|
251
412
|
this.operator,
|
|
252
413
|
]);
|
|
253
414
|
}
|
|
@@ -435,6 +596,17 @@ export class QueryBuilderFilterTreeConditionNodeData
|
|
|
435
596
|
this.isNewlyAdded = val;
|
|
436
597
|
}
|
|
437
598
|
|
|
599
|
+
get isExistsNodeChild(): boolean {
|
|
600
|
+
let parentNode = this.condition.filterState.getParentNode(this);
|
|
601
|
+
while (parentNode !== undefined) {
|
|
602
|
+
if (parentNode instanceof QueryBuilderFilterTreeExistsNodeData) {
|
|
603
|
+
return true;
|
|
604
|
+
}
|
|
605
|
+
parentNode = this.condition.filterState.getParentNode(parentNode);
|
|
606
|
+
}
|
|
607
|
+
return false;
|
|
608
|
+
}
|
|
609
|
+
|
|
438
610
|
get dragPreviewLabel(): string {
|
|
439
611
|
return this.condition.propertyExpressionState.title;
|
|
440
612
|
}
|
|
@@ -965,48 +1137,86 @@ export class QueryBuilderFilterState
|
|
|
965
1137
|
return Boolean(
|
|
966
1138
|
Array.from(this.nodes.values())
|
|
967
1139
|
.filter(filterByType(QueryBuilderFilterTreeConditionNodeData))
|
|
968
|
-
.map((node) =>
|
|
1140
|
+
.map((node) =>
|
|
1141
|
+
node.condition.rightConditionValue instanceof
|
|
1142
|
+
FilterValueSpecConditionValueState
|
|
1143
|
+
? node.condition.rightConditionValue.value
|
|
1144
|
+
: undefined,
|
|
1145
|
+
)
|
|
969
1146
|
.filter(isNonNullable)
|
|
970
1147
|
.find((value) => isValueExpressionReferencedInValue(variable, value)),
|
|
971
1148
|
);
|
|
972
1149
|
}
|
|
973
1150
|
|
|
1151
|
+
isInvalidFilterPropertyExpressionState(
|
|
1152
|
+
node: QueryBuilderFilterTreeNodeData,
|
|
1153
|
+
): boolean {
|
|
1154
|
+
return (
|
|
1155
|
+
node instanceof QueryBuilderFilterTreeConditionNodeData &&
|
|
1156
|
+
!node.condition.propertyExpressionState.isValid
|
|
1157
|
+
);
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
isInvalidValueSpecFilterValue(node: QueryBuilderFilterTreeNodeData): boolean {
|
|
1161
|
+
return (
|
|
1162
|
+
node instanceof QueryBuilderFilterTreeConditionNodeData &&
|
|
1163
|
+
node.condition.rightConditionValue instanceof
|
|
1164
|
+
FilterValueSpecConditionValueState &&
|
|
1165
|
+
node.condition.rightConditionValue.value instanceof InstanceValue &&
|
|
1166
|
+
!isValidInstanceValue(node.condition.rightConditionValue.value)
|
|
1167
|
+
);
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
isInvalidPropertyExpressionStateFilterValue(
|
|
1171
|
+
node: QueryBuilderFilterTreeNodeData,
|
|
1172
|
+
): boolean {
|
|
1173
|
+
return (
|
|
1174
|
+
node instanceof QueryBuilderFilterTreeConditionNodeData &&
|
|
1175
|
+
node.condition.rightConditionValue instanceof
|
|
1176
|
+
FilterPropertyExpressionStateConditionValueState &&
|
|
1177
|
+
!node.condition.rightConditionValue.propertyExpressionState.isValid
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
|
|
974
1181
|
get allValidationIssues(): string[] {
|
|
975
1182
|
const validationIssues: string[] = [];
|
|
976
1183
|
Array.from(this.nodes.values()).forEach((node) => {
|
|
977
1184
|
if (node instanceof QueryBuilderFilterTreeConditionNodeData) {
|
|
978
|
-
if (
|
|
979
|
-
node.condition.value instanceof InstanceValue &&
|
|
980
|
-
!isValidInstanceValue(node.condition.value)
|
|
981
|
-
) {
|
|
1185
|
+
if (this.isInvalidValueSpecFilterValue(node)) {
|
|
982
1186
|
validationIssues.push(
|
|
983
1187
|
`Filter value for ${node.condition.propertyExpressionState.title} is missing or invalid`,
|
|
984
1188
|
);
|
|
985
1189
|
}
|
|
986
|
-
if (
|
|
1190
|
+
if (this.isInvalidFilterPropertyExpressionState(node)) {
|
|
987
1191
|
validationIssues.push(
|
|
988
1192
|
`Derived property parameter value for ${node.condition.propertyExpressionState.title} is missing or invalid`,
|
|
989
1193
|
);
|
|
990
1194
|
}
|
|
1195
|
+
if (
|
|
1196
|
+
node.condition.rightConditionValue instanceof
|
|
1197
|
+
FilterPropertyExpressionStateConditionValueState &&
|
|
1198
|
+
this.isInvalidPropertyExpressionStateFilterValue(node)
|
|
1199
|
+
) {
|
|
1200
|
+
validationIssues.push(
|
|
1201
|
+
`Derived property parameter value for ${node.condition.rightConditionValue.propertyExpressionState.title} is missing or invalid`,
|
|
1202
|
+
);
|
|
1203
|
+
}
|
|
991
1204
|
}
|
|
992
1205
|
});
|
|
993
1206
|
return validationIssues;
|
|
994
1207
|
}
|
|
995
1208
|
|
|
996
1209
|
get hasInvalidFilterValues(): boolean {
|
|
997
|
-
return Array.from(this.nodes.values()).some(
|
|
998
|
-
(node)
|
|
999
|
-
node instanceof QueryBuilderFilterTreeConditionNodeData &&
|
|
1000
|
-
node.condition.value instanceof InstanceValue &&
|
|
1001
|
-
!isValidInstanceValue(node.condition.value),
|
|
1210
|
+
return Array.from(this.nodes.values()).some((node) =>
|
|
1211
|
+
this.isInvalidValueSpecFilterValue(node),
|
|
1002
1212
|
);
|
|
1003
1213
|
}
|
|
1004
1214
|
|
|
1005
1215
|
get hasInvalidDerivedPropertyParameters(): boolean {
|
|
1006
1216
|
return Array.from(this.nodes.values()).some(
|
|
1007
1217
|
(node) =>
|
|
1008
|
-
node
|
|
1009
|
-
|
|
1218
|
+
this.isInvalidFilterPropertyExpressionState(node) ||
|
|
1219
|
+
this.isInvalidPropertyExpressionStateFilterValue(node),
|
|
1010
1220
|
);
|
|
1011
1221
|
}
|
|
1012
1222
|
|
|
@@ -314,8 +314,8 @@ const processFilterTree = (
|
|
|
314
314
|
}
|
|
315
315
|
}
|
|
316
316
|
for (const operator of filterState.operators) {
|
|
317
|
-
// NOTE: this
|
|
318
|
-
// if there is a problem with building the lambda.
|
|
317
|
+
// NOTE: this allows plugin author to either return `undefined` or throw error
|
|
318
|
+
// if there is a problem with building the lambda. In either case, the plugin is
|
|
319
319
|
// considered as not supporting the lambda.
|
|
320
320
|
const filterConditionState = returnUndefOnError(() =>
|
|
321
321
|
operator.buildFilterConditionState(filterState, expression),
|
|
@@ -30,12 +30,15 @@ import {
|
|
|
30
30
|
} from '@finos/legend-shared';
|
|
31
31
|
import {
|
|
32
32
|
FilterConditionState,
|
|
33
|
+
FilterPropertyExpressionStateConditionValueState,
|
|
34
|
+
FilterValueSpecConditionValueState,
|
|
33
35
|
type QueryBuilderFilterState,
|
|
34
36
|
} from '../QueryBuilderFilterState.js';
|
|
35
37
|
import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '../../../graph/QueryBuilderMetaModelConst.js';
|
|
36
38
|
import { simplifyValueExpression } from '../../QueryBuilderValueSpecificationHelper.js';
|
|
37
39
|
import type { QueryBuilderFilterOperator } from '../QueryBuilderFilterOperator.js';
|
|
38
40
|
import { buildPropertyExpressionChain } from '../../QueryBuilderValueSpecificationBuilderHelper.js';
|
|
41
|
+
import { QueryBuilderPropertyExpressionState } from '../../QueryBuilderPropertyEditorState.js';
|
|
39
42
|
|
|
40
43
|
export const buildFilterConditionExpression = (
|
|
41
44
|
filterConditionState: FilterConditionState,
|
|
@@ -52,8 +55,28 @@ export const buildFilterConditionExpression = (
|
|
|
52
55
|
);
|
|
53
56
|
expression.parametersValues.push(guaranteeNonNullable(propertyExpression));
|
|
54
57
|
// NOTE: there are simple operators which do not require any params (e.g. isEmpty)
|
|
55
|
-
if (
|
|
56
|
-
|
|
58
|
+
if (
|
|
59
|
+
filterConditionState.rightConditionValue &&
|
|
60
|
+
filterConditionState.rightConditionValue instanceof
|
|
61
|
+
FilterValueSpecConditionValueState &&
|
|
62
|
+
filterConditionState.rightConditionValue.value !== undefined
|
|
63
|
+
) {
|
|
64
|
+
expression.parametersValues.push(
|
|
65
|
+
filterConditionState.rightConditionValue.value,
|
|
66
|
+
);
|
|
67
|
+
} else if (
|
|
68
|
+
filterConditionState.rightConditionValue &&
|
|
69
|
+
filterConditionState.rightConditionValue instanceof
|
|
70
|
+
FilterPropertyExpressionStateConditionValueState
|
|
71
|
+
) {
|
|
72
|
+
const rightConditionPropertyExpression = buildPropertyExpressionChain(
|
|
73
|
+
filterConditionState.rightConditionValue.propertyExpressionState
|
|
74
|
+
.propertyExpression,
|
|
75
|
+
filterConditionState.propertyExpressionState.queryBuilderState,
|
|
76
|
+
lambdaParameterName ??
|
|
77
|
+
filterConditionState.filterState.lambdaParameterName,
|
|
78
|
+
);
|
|
79
|
+
expression.parametersValues.push(rightConditionPropertyExpression);
|
|
57
80
|
}
|
|
58
81
|
return expression;
|
|
59
82
|
};
|
|
@@ -155,18 +178,34 @@ export const buildFilterConditionState = (
|
|
|
155
178
|
// value
|
|
156
179
|
const value = mainExpressionWithOperator.parametersValues[1];
|
|
157
180
|
if (hasNoValue || !value) {
|
|
158
|
-
filterConditionState.
|
|
181
|
+
filterConditionState.setRightConditionValue(undefined);
|
|
182
|
+
} else if (value instanceof AbstractPropertyExpression) {
|
|
183
|
+
filterConditionState.setRightConditionValue(
|
|
184
|
+
new FilterPropertyExpressionStateConditionValueState(
|
|
185
|
+
filterConditionState,
|
|
186
|
+
new QueryBuilderPropertyExpressionState(
|
|
187
|
+
filterState.queryBuilderState,
|
|
188
|
+
value,
|
|
189
|
+
),
|
|
190
|
+
),
|
|
191
|
+
);
|
|
159
192
|
} else {
|
|
160
|
-
filterConditionState.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
193
|
+
filterConditionState.setRightConditionValue(
|
|
194
|
+
new FilterValueSpecConditionValueState(
|
|
195
|
+
filterConditionState,
|
|
196
|
+
simplifyValueExpression(
|
|
197
|
+
value,
|
|
198
|
+
filterConditionState.filterState.queryBuilderState.observerContext,
|
|
199
|
+
),
|
|
164
200
|
),
|
|
165
201
|
);
|
|
166
202
|
}
|
|
167
203
|
if (!operator.isCompatibleWithFilterConditionValue(filterConditionState)) {
|
|
168
|
-
filterConditionState.
|
|
169
|
-
|
|
204
|
+
filterConditionState.setRightConditionValue(
|
|
205
|
+
new FilterValueSpecConditionValueState(
|
|
206
|
+
filterConditionState,
|
|
207
|
+
operator.getDefaultFilterConditionValue(filterConditionState),
|
|
208
|
+
),
|
|
170
209
|
);
|
|
171
210
|
}
|
|
172
211
|
return filterConditionState;
|
|
@@ -36,7 +36,6 @@ import {
|
|
|
36
36
|
} from './QueryBuilderFilterOperatorValueSpecificationBuilder.js';
|
|
37
37
|
import {
|
|
38
38
|
buildNotExpression,
|
|
39
|
-
getNonCollectionValueSpecificationType,
|
|
40
39
|
unwrapNotExpression,
|
|
41
40
|
} from '../../QueryBuilderValueSpecificationHelper.js';
|
|
42
41
|
import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '../../../graph/QueryBuilderMetaModelConst.js';
|
|
@@ -64,9 +63,11 @@ export class QueryBuilderFilterOperator_Contain
|
|
|
64
63
|
isCompatibleWithFilterConditionValue(
|
|
65
64
|
filterConditionState: FilterConditionState,
|
|
66
65
|
): boolean {
|
|
67
|
-
const type =
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
const type =
|
|
67
|
+
filterConditionState.rightConditionValue &&
|
|
68
|
+
!filterConditionState.rightConditionValue.isCollection
|
|
69
|
+
? filterConditionState.rightConditionValue.type
|
|
70
|
+
: undefined;
|
|
70
71
|
return PrimitiveType.STRING === type;
|
|
71
72
|
}
|
|
72
73
|
|
|
@@ -36,7 +36,6 @@ import {
|
|
|
36
36
|
} from './QueryBuilderFilterOperatorValueSpecificationBuilder.js';
|
|
37
37
|
import {
|
|
38
38
|
buildNotExpression,
|
|
39
|
-
getNonCollectionValueSpecificationType,
|
|
40
39
|
unwrapNotExpression,
|
|
41
40
|
} from '../../QueryBuilderValueSpecificationHelper.js';
|
|
42
41
|
import { QUERY_BUILDER_SUPPORTED_FUNCTIONS } from '../../../graph/QueryBuilderMetaModelConst.js';
|
|
@@ -64,9 +63,11 @@ export class QueryBuilderFilterOperator_EndWith
|
|
|
64
63
|
isCompatibleWithFilterConditionValue(
|
|
65
64
|
filterConditionState: FilterConditionState,
|
|
66
65
|
): boolean {
|
|
67
|
-
const type =
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
const type =
|
|
67
|
+
filterConditionState.rightConditionValue &&
|
|
68
|
+
!filterConditionState.rightConditionValue.isCollection
|
|
69
|
+
? filterConditionState.rightConditionValue.type
|
|
70
|
+
: undefined;
|
|
70
71
|
return PrimitiveType.STRING === type;
|
|
71
72
|
}
|
|
72
73
|
|