@finos/legend-query-builder 4.14.63 → 4.14.65
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|