@finos/legend-query-builder 3.1.0 → 3.2.0
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/__lib__/QueryBuilderTelemetryHelper.d.ts +20 -20
- package/lib/__lib__/QueryBuilderTelemetryHelper.d.ts.map +1 -1
- package/lib/__lib__/QueryBuilderTelemetryHelper.js +40 -40
- package/lib/__lib__/QueryBuilderTelemetryHelper.js.map +1 -1
- package/lib/components/QueryLoader.d.ts +30 -0
- package/lib/components/QueryLoader.d.ts.map +1 -0
- package/lib/components/QueryLoader.js +160 -0
- package/lib/components/QueryLoader.js.map +1 -0
- package/lib/components/shared/QueryBuilderPanelIssueCountBadge.d.ts.map +1 -1
- package/lib/components/shared/QueryBuilderPanelIssueCountBadge.js +2 -1
- package/lib/components/shared/QueryBuilderPanelIssueCountBadge.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts +30 -0
- package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts.map +1 -0
- package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.js +17 -0
- package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.js.map +1 -0
- package/lib/stores/QueryLoaderState.d.ts +67 -0
- package/lib/stores/QueryLoaderState.d.ts.map +1 -0
- package/lib/stores/QueryLoaderState.js +205 -0
- package/lib/stores/QueryLoaderState.js.map +1 -0
- package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts +3 -1
- package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts.map +1 -1
- package/lib/stores/shared/ValueSpecificationEditorHelper.js +7 -1
- package/lib/stores/shared/ValueSpecificationEditorHelper.js.map +1 -1
- package/package.json +8 -8
- package/src/__lib__/QueryBuilderTelemetryHelper.ts +40 -59
- package/src/components/QueryLoader.tsx +501 -0
- package/src/components/shared/QueryBuilderPanelIssueCountBadge.tsx +2 -1
- package/src/index.ts +3 -0
- package/src/stores/QueryBuilder_LegendApplicationPlugin_Extension.ts +36 -0
- package/src/stores/QueryLoaderState.ts +298 -0
- package/src/stores/shared/ValueSpecificationEditorHelper.ts +39 -2
- package/tsconfig.json +3 -0
@@ -0,0 +1,298 @@
|
|
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 {
|
18
|
+
DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH,
|
19
|
+
type GenericLegendApplicationStore,
|
20
|
+
} from '@finos/legend-application';
|
21
|
+
import {
|
22
|
+
type LightQuery,
|
23
|
+
QuerySearchSpecification,
|
24
|
+
type QueryInfo,
|
25
|
+
type BasicGraphManagerState,
|
26
|
+
type Query,
|
27
|
+
} from '@finos/legend-graph';
|
28
|
+
import {
|
29
|
+
ActionState,
|
30
|
+
type GeneratorFn,
|
31
|
+
assertErrorThrown,
|
32
|
+
guaranteeNonNullable,
|
33
|
+
} from '@finos/legend-shared';
|
34
|
+
import { makeObservable, observable, action, flow } from 'mobx';
|
35
|
+
import type { QueryBuilderState } from './QueryBuilderState.js';
|
36
|
+
import type {
|
37
|
+
LoadQueryFilterOption,
|
38
|
+
QueryBuilder_LegendApplicationPlugin_Extension,
|
39
|
+
} from './QueryBuilder_LegendApplicationPlugin_Extension.js';
|
40
|
+
|
41
|
+
export const QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT = 20;
|
42
|
+
|
43
|
+
export class QueryLoaderState {
|
44
|
+
readonly applicationStore: GenericLegendApplicationStore;
|
45
|
+
readonly graphManagerState: BasicGraphManagerState;
|
46
|
+
|
47
|
+
readonly searchQueriesState = ActionState.create();
|
48
|
+
readonly renameQueryState = ActionState.create();
|
49
|
+
readonly deleteQueryState = ActionState.create();
|
50
|
+
readonly previewQueryState = ActionState.create();
|
51
|
+
|
52
|
+
readonly decorateSearchSpecification?:
|
53
|
+
| ((val: QuerySearchSpecification) => QuerySearchSpecification)
|
54
|
+
| undefined;
|
55
|
+
|
56
|
+
readonly loadQuery: (query: LightQuery) => void;
|
57
|
+
readonly fetchDefaultQueries?: (() => Promise<LightQuery[]>) | undefined;
|
58
|
+
readonly generateDefaultQueriesSummaryText?:
|
59
|
+
| ((queries: LightQuery[]) => string)
|
60
|
+
| undefined;
|
61
|
+
|
62
|
+
readonly isReadOnly?: boolean | undefined;
|
63
|
+
readonly onQueryRenamed?: ((query: LightQuery) => void) | undefined;
|
64
|
+
readonly onQueryDeleted?: ((query: LightQuery) => void) | undefined;
|
65
|
+
|
66
|
+
queryBuilderState?: QueryBuilderState | undefined;
|
67
|
+
|
68
|
+
searchText = '';
|
69
|
+
showCurrentUserQueriesOnly = false; // TODO: if we start having more native filters, we should make them part of `extraFilters`
|
70
|
+
extraFilters = new Map<string, boolean>();
|
71
|
+
extraFilterOptions: LoadQueryFilterOption[] = [];
|
72
|
+
queries: LightQuery[] = [];
|
73
|
+
|
74
|
+
isQueryLoaderDialogOpen = false;
|
75
|
+
showingDefaultQueries = true;
|
76
|
+
showPreviewViewer = false;
|
77
|
+
queryPreviewContent?: QueryInfo;
|
78
|
+
|
79
|
+
constructor(
|
80
|
+
applicationStore: GenericLegendApplicationStore,
|
81
|
+
graphManagerState: BasicGraphManagerState,
|
82
|
+
options: {
|
83
|
+
decorateSearchSpecification?:
|
84
|
+
| ((val: QuerySearchSpecification) => QuerySearchSpecification)
|
85
|
+
| undefined;
|
86
|
+
|
87
|
+
loadQuery: (query: LightQuery) => void;
|
88
|
+
fetchDefaultQueries?: (() => Promise<LightQuery[]>) | undefined;
|
89
|
+
generateDefaultQueriesSummaryText?:
|
90
|
+
| ((queries: LightQuery[]) => string)
|
91
|
+
| undefined;
|
92
|
+
|
93
|
+
isReadOnly?: boolean | undefined;
|
94
|
+
onQueryRenamed?: ((query: LightQuery) => void) | undefined;
|
95
|
+
onQueryDeleted?: ((query: LightQuery) => void) | undefined;
|
96
|
+
},
|
97
|
+
) {
|
98
|
+
makeObservable(this, {
|
99
|
+
isQueryLoaderDialogOpen: observable,
|
100
|
+
queryPreviewContent: observable,
|
101
|
+
showingDefaultQueries: observable,
|
102
|
+
queries: observable,
|
103
|
+
showCurrentUserQueriesOnly: observable,
|
104
|
+
showPreviewViewer: observable,
|
105
|
+
searchText: observable,
|
106
|
+
setSearchText: action,
|
107
|
+
setQueryLoaderDialogOpen: action,
|
108
|
+
setQueries: action,
|
109
|
+
setShowCurrentUserQueriesOnly: action,
|
110
|
+
setShowPreviewViewer: action,
|
111
|
+
searchQueries: flow,
|
112
|
+
getPreviewQueryContent: flow,
|
113
|
+
deleteQuery: flow,
|
114
|
+
renameQuery: flow,
|
115
|
+
initialize: flow,
|
116
|
+
});
|
117
|
+
|
118
|
+
this.applicationStore = applicationStore;
|
119
|
+
this.graphManagerState = graphManagerState;
|
120
|
+
|
121
|
+
this.loadQuery = options.loadQuery;
|
122
|
+
this.fetchDefaultQueries = options.fetchDefaultQueries;
|
123
|
+
this.generateDefaultQueriesSummaryText =
|
124
|
+
options.generateDefaultQueriesSummaryText;
|
125
|
+
this.decorateSearchSpecification = options.decorateSearchSpecification;
|
126
|
+
this.isReadOnly = options.isReadOnly;
|
127
|
+
this.onQueryRenamed = options.onQueryRenamed;
|
128
|
+
this.onQueryDeleted = options.onQueryDeleted;
|
129
|
+
}
|
130
|
+
|
131
|
+
setSearchText(val: string): void {
|
132
|
+
this.searchText = val;
|
133
|
+
}
|
134
|
+
|
135
|
+
setQueryLoaderDialogOpen(val: boolean): void {
|
136
|
+
this.isQueryLoaderDialogOpen = val;
|
137
|
+
}
|
138
|
+
|
139
|
+
setQueries(val: LightQuery[]): void {
|
140
|
+
this.queries = val;
|
141
|
+
}
|
142
|
+
|
143
|
+
setShowPreviewViewer(val: boolean): void {
|
144
|
+
this.showPreviewViewer = val;
|
145
|
+
}
|
146
|
+
|
147
|
+
setShowCurrentUserQueriesOnly(val: boolean): void {
|
148
|
+
this.showCurrentUserQueriesOnly = val;
|
149
|
+
}
|
150
|
+
|
151
|
+
reset(): void {
|
152
|
+
this.setShowCurrentUserQueriesOnly(false);
|
153
|
+
}
|
154
|
+
|
155
|
+
*initialize(queryBuilderState: QueryBuilderState): GeneratorFn<void> {
|
156
|
+
this.queryBuilderState = queryBuilderState;
|
157
|
+
this.extraFilterOptions = this.applicationStore.pluginManager
|
158
|
+
.getApplicationPlugins()
|
159
|
+
.flatMap(
|
160
|
+
(plugin) =>
|
161
|
+
(
|
162
|
+
plugin as QueryBuilder_LegendApplicationPlugin_Extension
|
163
|
+
).getExtraLoadQueryFilterOptions?.() ?? [],
|
164
|
+
);
|
165
|
+
const extraFilters = this.extraFilterOptions.map((filterOption) =>
|
166
|
+
filterOption.label(guaranteeNonNullable(this.queryBuilderState)),
|
167
|
+
);
|
168
|
+
extraFilters.forEach(
|
169
|
+
(filter) => filter && this.extraFilters.set(filter, false),
|
170
|
+
);
|
171
|
+
}
|
172
|
+
|
173
|
+
*searchQueries(searchText: string): GeneratorFn<void> {
|
174
|
+
if (
|
175
|
+
searchText.length < DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH &&
|
176
|
+
!this.showCurrentUserQueriesOnly &&
|
177
|
+
Array.from(this.extraFilters.values()).every((value) => value === false)
|
178
|
+
) {
|
179
|
+
// if no search text is specified, use fetch the default queries
|
180
|
+
if (!searchText) {
|
181
|
+
this.showingDefaultQueries = true;
|
182
|
+
this.searchQueriesState.inProgress();
|
183
|
+
this.queries = [];
|
184
|
+
try {
|
185
|
+
if (!this.fetchDefaultQueries) {
|
186
|
+
return;
|
187
|
+
}
|
188
|
+
this.queries = (yield this.fetchDefaultQueries()) as LightQuery[];
|
189
|
+
this.searchQueriesState.pass();
|
190
|
+
} catch (error) {
|
191
|
+
this.searchQueriesState.fail();
|
192
|
+
assertErrorThrown(error);
|
193
|
+
this.applicationStore.notificationService.notifyError(error);
|
194
|
+
}
|
195
|
+
}
|
196
|
+
|
197
|
+
// skip otherwise
|
198
|
+
return;
|
199
|
+
}
|
200
|
+
|
201
|
+
// search using the search term
|
202
|
+
this.showingDefaultQueries = false;
|
203
|
+
this.searchQueriesState.inProgress();
|
204
|
+
try {
|
205
|
+
let searchSpecification = new QuerySearchSpecification();
|
206
|
+
searchSpecification.searchTerm = searchText;
|
207
|
+
searchSpecification.limit = QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT + 1;
|
208
|
+
searchSpecification.showCurrentUserQueriesOnly =
|
209
|
+
this.showCurrentUserQueriesOnly;
|
210
|
+
if (this.queryBuilderState) {
|
211
|
+
Array.from(this.extraFilters.entries()).forEach(([key, value]) => {
|
212
|
+
if (value) {
|
213
|
+
const filterOption = this.extraFilterOptions.find(
|
214
|
+
(option) =>
|
215
|
+
option.label(guaranteeNonNullable(this.queryBuilderState)) ===
|
216
|
+
key,
|
217
|
+
);
|
218
|
+
if (filterOption) {
|
219
|
+
searchSpecification = filterOption.filterFunction(
|
220
|
+
searchSpecification,
|
221
|
+
guaranteeNonNullable(this.queryBuilderState),
|
222
|
+
);
|
223
|
+
}
|
224
|
+
}
|
225
|
+
});
|
226
|
+
}
|
227
|
+
searchSpecification =
|
228
|
+
this.decorateSearchSpecification?.(searchSpecification) ??
|
229
|
+
searchSpecification;
|
230
|
+
this.queries = (yield this.graphManagerState.graphManager.searchQueries(
|
231
|
+
searchSpecification,
|
232
|
+
)) as LightQuery[];
|
233
|
+
this.searchQueriesState.pass();
|
234
|
+
} catch (error) {
|
235
|
+
assertErrorThrown(error);
|
236
|
+
this.applicationStore.notificationService.notifyError(error);
|
237
|
+
this.searchQueriesState.fail();
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
*renameQuery(queryId: string, name: string): GeneratorFn<void> {
|
242
|
+
this.renameQueryState.inProgress();
|
243
|
+
try {
|
244
|
+
const query = (yield this.graphManagerState.graphManager.renameQuery(
|
245
|
+
queryId,
|
246
|
+
name,
|
247
|
+
)) as Query;
|
248
|
+
this.onQueryRenamed?.(query);
|
249
|
+
this.applicationStore.notificationService.notify(
|
250
|
+
'Renamed query successfully',
|
251
|
+
);
|
252
|
+
this.renameQueryState.pass();
|
253
|
+
this.searchQueries(this.searchText); // trigger a search to refresh the query list
|
254
|
+
} catch (error) {
|
255
|
+
assertErrorThrown(error);
|
256
|
+
this.applicationStore.notificationService.notifyError(error);
|
257
|
+
this.renameQueryState.fail();
|
258
|
+
}
|
259
|
+
}
|
260
|
+
|
261
|
+
*deleteQuery(queryId: string): GeneratorFn<void> {
|
262
|
+
this.deleteQueryState.inProgress();
|
263
|
+
try {
|
264
|
+
const query = (yield this.graphManagerState.graphManager.deleteQuery(
|
265
|
+
queryId,
|
266
|
+
)) as Query;
|
267
|
+
this.onQueryDeleted?.(query);
|
268
|
+
this.applicationStore.notificationService.notify(
|
269
|
+
'Deleted query successfully',
|
270
|
+
);
|
271
|
+
this.deleteQueryState.pass();
|
272
|
+
this.searchQueries(this.searchText); // trigger a search to refresh the query list
|
273
|
+
} catch (error) {
|
274
|
+
assertErrorThrown(error);
|
275
|
+
this.applicationStore.notificationService.notifyError(error);
|
276
|
+
this.deleteQueryState.fail();
|
277
|
+
}
|
278
|
+
}
|
279
|
+
|
280
|
+
*getPreviewQueryContent(queryId: string): GeneratorFn<void> {
|
281
|
+
this.previewQueryState.inProgress();
|
282
|
+
try {
|
283
|
+
const queryInfo = (yield this.graphManagerState.graphManager.getQueryInfo(
|
284
|
+
queryId,
|
285
|
+
)) as QueryInfo;
|
286
|
+
this.queryPreviewContent = queryInfo;
|
287
|
+
this.queryPreviewContent.content =
|
288
|
+
(yield this.graphManagerState.graphManager.prettyLambdaContent(
|
289
|
+
queryInfo.content,
|
290
|
+
)) as string;
|
291
|
+
this.previewQueryState.pass();
|
292
|
+
} catch (error) {
|
293
|
+
assertErrorThrown(error);
|
294
|
+
this.applicationStore.notificationService.notifyError(error);
|
295
|
+
this.previewQueryState.fail();
|
296
|
+
}
|
297
|
+
}
|
298
|
+
}
|
@@ -16,10 +16,13 @@
|
|
16
16
|
|
17
17
|
import {
|
18
18
|
type PureModel,
|
19
|
-
|
19
|
+
type GraphManagerState,
|
20
20
|
type ValueSpecification,
|
21
21
|
type Type,
|
22
22
|
type Enum,
|
23
|
+
type ObserverContext,
|
24
|
+
type RawLambda,
|
25
|
+
VariableExpression,
|
23
26
|
CollectionInstanceValue,
|
24
27
|
Enumeration,
|
25
28
|
EnumValueExplicitReference,
|
@@ -32,7 +35,12 @@ import {
|
|
32
35
|
PRIMITIVE_TYPE,
|
33
36
|
INTERNAL__PropagatedValue,
|
34
37
|
SimpleFunctionExpression,
|
35
|
-
|
38
|
+
LambdaFunction,
|
39
|
+
FunctionType,
|
40
|
+
PackageableElementExplicitReference,
|
41
|
+
Multiplicity,
|
42
|
+
CORE_PURE_PATH,
|
43
|
+
buildRawLambdaFromLambdaFunction,
|
36
44
|
} from '@finos/legend-graph';
|
37
45
|
import { Randomizer, UnsupportedOperationError } from '@finos/legend-shared';
|
38
46
|
import { generateDefaultValueForPrimitiveType } from '../QueryBuilderValueSpecificationHelper.js';
|
@@ -177,6 +185,35 @@ export const buildDefaultInstanceValue = (
|
|
177
185
|
}
|
178
186
|
};
|
179
187
|
|
188
|
+
export const buildDefaultEmptyStringLambda = (
|
189
|
+
graph: PureModel,
|
190
|
+
observerContext: ObserverContext,
|
191
|
+
): LambdaFunction => {
|
192
|
+
const lambdaFunction = new LambdaFunction(
|
193
|
+
new FunctionType(
|
194
|
+
PackageableElementExplicitReference.create(
|
195
|
+
graph.getType(CORE_PURE_PATH.ANY),
|
196
|
+
),
|
197
|
+
Multiplicity.ONE,
|
198
|
+
),
|
199
|
+
);
|
200
|
+
lambdaFunction.expressionSequence[0] = buildDefaultInstanceValue(
|
201
|
+
graph,
|
202
|
+
PrimitiveType.STRING,
|
203
|
+
observerContext,
|
204
|
+
);
|
205
|
+
return lambdaFunction;
|
206
|
+
};
|
207
|
+
|
208
|
+
export const buildDefaultEmptyStringRawLambda = (
|
209
|
+
graphState: GraphManagerState,
|
210
|
+
observerContext: ObserverContext,
|
211
|
+
): RawLambda =>
|
212
|
+
buildRawLambdaFromLambdaFunction(
|
213
|
+
buildDefaultEmptyStringLambda(graphState.graph, observerContext),
|
214
|
+
graphState,
|
215
|
+
);
|
216
|
+
|
180
217
|
export const generateVariableExpressionMockValue = (
|
181
218
|
parameter: VariableExpression,
|
182
219
|
graph: PureModel,
|
package/tsconfig.json
CHANGED
@@ -71,6 +71,8 @@
|
|
71
71
|
"./src/stores/QueryBuilderValueSpecificationBuilder.ts",
|
72
72
|
"./src/stores/QueryBuilderValueSpecificationBuilderHelper.ts",
|
73
73
|
"./src/stores/QueryBuilderValueSpecificationHelper.ts",
|
74
|
+
"./src/stores/QueryBuilder_LegendApplicationPlugin_Extension.ts",
|
75
|
+
"./src/stores/QueryLoaderState.ts",
|
74
76
|
"./src/stores/ServiceInfo.ts",
|
75
77
|
"./src/stores/__test-utils__/QueryBuilderStateTestUtils.ts",
|
76
78
|
"./src/stores/entitlements/QueryBuilderCheckEntitlementsState.ts",
|
@@ -213,6 +215,7 @@
|
|
213
215
|
"./src/components/QueryBuilderSideBar.tsx",
|
214
216
|
"./src/components/QueryBuilderTextEditor.tsx",
|
215
217
|
"./src/components/QueryBuilderUnsupportedQueryEditor.tsx",
|
218
|
+
"./src/components/QueryLoader.tsx",
|
216
219
|
"./src/components/ServiceQuerySetupUtils.tsx",
|
217
220
|
"./src/components/__test-utils__/QueryBuilderComponentTestUtils.tsx",
|
218
221
|
"./src/components/execution-plan/ExecutionPlanViewer.tsx",
|