@finos/legend-application-query 13.8.48 → 13.8.50
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/Core_LegendQueryApplicationPlugin.d.ts.map +1 -1
- package/lib/components/Core_LegendQueryApplicationPlugin.js +52 -18
- package/lib/components/Core_LegendQueryApplicationPlugin.js.map +1 -1
- package/lib/components/QueryEditor.d.ts.map +1 -1
- package/lib/components/QueryEditor.js +14 -2
- package/lib/components/QueryEditor.js.map +1 -1
- package/lib/components/data-space/DataSpaceInfo.d.ts.map +1 -1
- package/lib/components/data-space/DataSpaceInfo.js +13 -9
- package/lib/components/data-space/DataSpaceInfo.js.map +1 -1
- package/lib/components/data-space/DataSpaceQuerySetup.js +3 -3
- package/lib/components/data-space/DataSpaceQuerySetup.js.map +1 -1
- package/lib/components/data-space/LegendQueryDataSpaceQueryBuilder.d.ts.map +1 -1
- package/lib/components/data-space/LegendQueryDataSpaceQueryBuilder.js +23 -13
- package/lib/components/data-space/LegendQueryDataSpaceQueryBuilder.js.map +1 -1
- package/lib/index.css +1 -1
- package/lib/light-mode.css +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/QueryEditorStore.d.ts +14 -11
- package/lib/stores/QueryEditorStore.d.ts.map +1 -1
- package/lib/stores/QueryEditorStore.js +68 -35
- package/lib/stores/QueryEditorStore.js.map +1 -1
- package/lib/stores/__test-utils__/DataSpaceQueryBuilderStateTestUtils.d.ts +33 -0
- package/lib/stores/__test-utils__/DataSpaceQueryBuilderStateTestUtils.d.ts.map +1 -0
- package/lib/stores/__test-utils__/DataSpaceQueryBuilderStateTestUtils.js +74 -0
- package/lib/stores/__test-utils__/DataSpaceQueryBuilderStateTestUtils.js.map +1 -0
- package/lib/stores/data-product/query-builder/LegendQueryDataProductQueryBuilderState.d.ts.map +1 -1
- package/lib/stores/data-product/query-builder/LegendQueryDataProductQueryBuilderState.js +3 -3
- package/lib/stores/data-product/query-builder/LegendQueryDataProductQueryBuilderState.js.map +1 -1
- package/lib/stores/data-space/DataProductQueryCreatorStore.d.ts.map +1 -1
- package/lib/stores/data-space/DataProductQueryCreatorStore.js +13 -5
- package/lib/stores/data-space/DataProductQueryCreatorStore.js.map +1 -1
- package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.d.ts +1 -1
- package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.d.ts.map +1 -1
- package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.js +11 -4
- package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.js.map +1 -1
- package/lib/stores/data-space/query-builder/LegendQueryDataSpaceQueryBuilderState.d.ts +5 -4
- package/lib/stores/data-space/query-builder/LegendQueryDataSpaceQueryBuilderState.d.ts.map +1 -1
- package/lib/stores/data-space/query-builder/LegendQueryDataSpaceQueryBuilderState.js +37 -8
- package/lib/stores/data-space/query-builder/LegendQueryDataSpaceQueryBuilderState.js.map +1 -1
- package/lib/stores/ingest/IngestQueryCreatorStore.d.ts.map +1 -1
- package/lib/stores/ingest/IngestQueryCreatorStore.js +2 -2
- package/lib/stores/ingest/IngestQueryCreatorStore.js.map +1 -1
- package/package.json +8 -8
- package/src/components/Core_LegendQueryApplicationPlugin.tsx +72 -33
- package/src/components/QueryEditor.tsx +22 -4
- package/src/components/data-space/DataSpaceInfo.tsx +28 -11
- package/src/components/data-space/DataSpaceQuerySetup.tsx +4 -4
- package/src/components/data-space/LegendQueryDataSpaceQueryBuilder.tsx +94 -38
- package/src/stores/QueryEditorStore.ts +118 -59
- package/src/stores/__test-utils__/DataSpaceQueryBuilderStateTestUtils.ts +138 -0
- package/src/stores/data-product/query-builder/LegendQueryDataProductQueryBuilderState.ts +9 -2
- package/src/stores/data-space/DataProductQueryCreatorStore.ts +29 -6
- package/src/stores/data-space/DataSpaceTemplateQueryCreatorStore.ts +23 -4
- package/src/stores/data-space/query-builder/LegendQueryDataSpaceQueryBuilderState.ts +51 -13
- package/src/stores/ingest/IngestQueryCreatorStore.ts +5 -1
- package/tsconfig.json +1 -0
|
@@ -31,7 +31,6 @@ import { type QueryEditorStore } from '../../stores/QueryEditorStore.js';
|
|
|
31
31
|
import {
|
|
32
32
|
type DataSpace,
|
|
33
33
|
type DataSpaceExecutionContext,
|
|
34
|
-
DataSpaceQueryBuilderState,
|
|
35
34
|
DataSpaceSupportEmail,
|
|
36
35
|
} from '@finos/legend-extension-dsl-data-space/graph';
|
|
37
36
|
import {
|
|
@@ -39,11 +38,13 @@ import {
|
|
|
39
38
|
EXTERNAL_APPLICATION_NAVIGATION__generateTaxonomyDataspaceViewUrl,
|
|
40
39
|
} from '../../__lib__/LegendQueryNavigation.js';
|
|
41
40
|
import { flowResult } from 'mobx';
|
|
42
|
-
import { assertErrorThrown } from '@finos/legend-shared';
|
|
41
|
+
import { assertErrorThrown, guaranteeType } from '@finos/legend-shared';
|
|
43
42
|
import {
|
|
44
43
|
ConnectionPointer,
|
|
44
|
+
INTERNAL_ELEMENT_PATH,
|
|
45
45
|
RelationalDatabaseConnection,
|
|
46
46
|
} from '@finos/legend-graph';
|
|
47
|
+
import { LegendQueryDataSpaceQueryBuilderState } from '../../stores/data-space/query-builder/LegendQueryDataSpaceQueryBuilderState.js';
|
|
47
48
|
|
|
48
49
|
export const QueryEditorDataspaceInfoModal = observer(
|
|
49
50
|
(props: {
|
|
@@ -55,8 +56,16 @@ export const QueryEditorDataspaceInfoModal = observer(
|
|
|
55
56
|
}) => {
|
|
56
57
|
const { editorStore, dataspace, executionContext, open, closeModal } =
|
|
57
58
|
props;
|
|
59
|
+
const queryBuilderState = guaranteeType(
|
|
60
|
+
editorStore.queryBuilderState,
|
|
61
|
+
LegendQueryDataSpaceQueryBuilderState,
|
|
62
|
+
`Data product info modal expects a ${LegendQueryDataSpaceQueryBuilderState.name}`,
|
|
63
|
+
);
|
|
58
64
|
const projectInfo = editorStore.getProjectInfo();
|
|
59
65
|
const visitElement = async (path: string | undefined): Promise<void> => {
|
|
66
|
+
if (path?.startsWith(`${INTERNAL_ELEMENT_PATH}::`)) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
60
69
|
try {
|
|
61
70
|
if (projectInfo) {
|
|
62
71
|
const project = StoreProjectData.serialization.fromJson(
|
|
@@ -94,15 +103,14 @@ export const QueryEditorDataspaceInfoModal = observer(
|
|
|
94
103
|
}
|
|
95
104
|
};
|
|
96
105
|
|
|
97
|
-
const dataSpaceAnalysisResult =
|
|
98
|
-
editorStore.queryBuilderState instanceof DataSpaceQueryBuilderState
|
|
99
|
-
? editorStore.queryBuilderState.dataSpaceAnalysisResult
|
|
100
|
-
: undefined;
|
|
106
|
+
const dataSpaceAnalysisResult = queryBuilderState.dataSpaceAnalysisResult;
|
|
101
107
|
const dataSpaceMedata = dataSpaceAnalysisResult?.executionContextsIndex.get(
|
|
102
108
|
executionContext.name,
|
|
103
109
|
)?.runtimeMetadata;
|
|
104
110
|
const defaultRuntimeValue = executionContext.defaultRuntime?.value;
|
|
105
111
|
const executionContextMappingValue = executionContext.mapping?.value;
|
|
112
|
+
const mappingProviderElement =
|
|
113
|
+
executionContext.mappingProvider?.element.value;
|
|
106
114
|
const connection = defaultRuntimeValue?.runtimeValue.connections.length
|
|
107
115
|
? defaultRuntimeValue.runtimeValue.connections[0]?.storeConnections?.[0]
|
|
108
116
|
?.connection instanceof ConnectionPointer
|
|
@@ -162,7 +170,7 @@ export const QueryEditorDataspaceInfoModal = observer(
|
|
|
162
170
|
className="dataspace-info-modal"
|
|
163
171
|
>
|
|
164
172
|
<div className="dataspace-info-modal__header">
|
|
165
|
-
<ModalTitle title="About Data
|
|
173
|
+
<ModalTitle title="About Data Space" />
|
|
166
174
|
<button
|
|
167
175
|
className="btn--dark dataspace-info-modal__header__open-btn"
|
|
168
176
|
title="Close"
|
|
@@ -174,7 +182,7 @@ export const QueryEditorDataspaceInfoModal = observer(
|
|
|
174
182
|
}
|
|
175
183
|
onClick={openInTaxonomy}
|
|
176
184
|
>
|
|
177
|
-
Open Data
|
|
185
|
+
Open Data Space
|
|
178
186
|
</button>
|
|
179
187
|
</div>
|
|
180
188
|
|
|
@@ -209,9 +217,18 @@ export const QueryEditorDataspaceInfoModal = observer(
|
|
|
209
217
|
</div>
|
|
210
218
|
<div className="dataspace-info-modal__field">
|
|
211
219
|
<div className="dataspace-info-modal__field__label">
|
|
212
|
-
Mapping
|
|
220
|
+
{mappingProviderElement ? 'Data Product' : 'Mapping'}
|
|
213
221
|
</div>
|
|
214
|
-
{
|
|
222
|
+
{mappingProviderElement ? (
|
|
223
|
+
<div
|
|
224
|
+
className="dataspace-info-modal__field__value dataspace-info-modal__field__value--linkable"
|
|
225
|
+
onClick={() =>
|
|
226
|
+
flowResult(visitElement(mappingProviderElement.path))
|
|
227
|
+
}
|
|
228
|
+
>
|
|
229
|
+
{mappingProviderElement.name}
|
|
230
|
+
</div>
|
|
231
|
+
) : executionContextMappingValue ? (
|
|
215
232
|
<div
|
|
216
233
|
className="dataspace-info-modal__field__value dataspace-info-modal__field__value--linkable"
|
|
217
234
|
onClick={() =>
|
|
@@ -299,7 +316,7 @@ export const QueryEditorDataspaceInfoModal = observer(
|
|
|
299
316
|
className="dataspace-info-modal__field__value dataspace-info-modal__field__value--linkable"
|
|
300
317
|
onClick={() => flowResult(visitElement(dataspace.path))}
|
|
301
318
|
>
|
|
302
|
-
Show Data
|
|
319
|
+
Show Data Space Configuration
|
|
303
320
|
</div>
|
|
304
321
|
</div>
|
|
305
322
|
{dataspace.supportInfo instanceof DataSpaceSupportEmail && (
|
|
@@ -114,10 +114,10 @@ const DataProductQuerySetupSetupPanelContent = observer(
|
|
|
114
114
|
<div className="query-builder__setup__config-group__item">
|
|
115
115
|
<label
|
|
116
116
|
className="btn--sm query-builder__setup__config-group__data-product"
|
|
117
|
-
title="data
|
|
117
|
+
title="data space"
|
|
118
118
|
htmlFor="query-builder__setup__data-space-selector"
|
|
119
119
|
>
|
|
120
|
-
Data
|
|
120
|
+
Data Space
|
|
121
121
|
</label>
|
|
122
122
|
<CustomSelectorInput
|
|
123
123
|
inputId="query-builder__setup__data-space-selector"
|
|
@@ -130,7 +130,7 @@ const DataProductQuerySetupSetupPanelContent = observer(
|
|
|
130
130
|
}
|
|
131
131
|
onChange={onDataSpaceOptionChange}
|
|
132
132
|
value={selectedDataSpaceOption}
|
|
133
|
-
placeholder="Search for data
|
|
133
|
+
placeholder="Search for data space..."
|
|
134
134
|
escapeClearsValue={true}
|
|
135
135
|
darkMode={
|
|
136
136
|
!applicationStore.layoutService
|
|
@@ -142,7 +142,7 @@ const DataProductQuerySetupSetupPanelContent = observer(
|
|
|
142
142
|
tabIndex={-1}
|
|
143
143
|
className="query-builder__setup__data-space-searcher__btn btn--dark"
|
|
144
144
|
onClick={openDataSpaceAdvancedSearch}
|
|
145
|
-
title="Open advanced search for data
|
|
145
|
+
title="Open advanced search for data space..."
|
|
146
146
|
>
|
|
147
147
|
<SearchIcon />
|
|
148
148
|
</button>
|
|
@@ -18,6 +18,7 @@ import { useApplicationStore } from '@finos/legend-application';
|
|
|
18
18
|
import {
|
|
19
19
|
AnchorLinkIcon,
|
|
20
20
|
CheckIcon,
|
|
21
|
+
CogIcon,
|
|
21
22
|
compareLabelFn,
|
|
22
23
|
ControlledDropdownMenu,
|
|
23
24
|
createFilter,
|
|
@@ -39,6 +40,7 @@ import {
|
|
|
39
40
|
import {
|
|
40
41
|
buildExecutionContextOption,
|
|
41
42
|
DataSpaceAdvancedSearchModal,
|
|
43
|
+
formatExecutionContextOptionLabel,
|
|
42
44
|
type ExecutionContextOption,
|
|
43
45
|
} from '@finos/legend-extension-dsl-data-space/application-query';
|
|
44
46
|
import { resolveExecutionContextMapping } from '@finos/legend-extension-dsl-data-space/graph';
|
|
@@ -58,7 +60,8 @@ import { guaranteeNonNullable, guaranteeType } from '@finos/legend-shared';
|
|
|
58
60
|
import { DepotEntityWithOrigin } from '@finos/legend-storage';
|
|
59
61
|
import { flowResult } from 'mobx';
|
|
60
62
|
import { observer } from 'mobx-react-lite';
|
|
61
|
-
import { useEffect } from 'react';
|
|
63
|
+
import { useEffect, useState } from 'react';
|
|
64
|
+
import { LakehouseRuntimeConfigModal } from '../shared/LakehouseRuntimeConfigModal.js';
|
|
62
65
|
import type { DataProductWithLegacyOption } from '../../stores/data-space/DataProductSelectorState.js';
|
|
63
66
|
import { formatDataProductOrSpaceOptionLabel } from '../shared/LegendQueryDataProductOptionLabel.js';
|
|
64
67
|
import type { LegendQueryDataSpaceQueryBuilderState } from '../../stores/data-space/query-builder/LegendQueryDataSpaceQueryBuilderState.js';
|
|
@@ -132,7 +135,7 @@ const LegendQueryDataSpaceQueryBuilderSetupPanelContent = observer(
|
|
|
132
135
|
// execution context
|
|
133
136
|
const executionContextOptions = guaranteeNonNullable(
|
|
134
137
|
queryBuilderState.dataSpace.executionContexts,
|
|
135
|
-
`Data
|
|
138
|
+
`Data space '${queryBuilderState.dataSpace.path}' does not have any execution contexts`,
|
|
136
139
|
)
|
|
137
140
|
.map(buildExecutionContextOption)
|
|
138
141
|
.sort(compareLabelFn);
|
|
@@ -147,17 +150,14 @@ const LegendQueryDataSpaceQueryBuilderSetupPanelContent = observer(
|
|
|
147
150
|
if (option.value === queryBuilderState.executionContext) {
|
|
148
151
|
return;
|
|
149
152
|
}
|
|
150
|
-
const currentMappingPath =
|
|
151
|
-
queryBuilderState.executionContext
|
|
152
|
-
|
|
153
|
-
).value.path;
|
|
154
|
-
const nextMappingPath = guaranteeNonNullable(
|
|
155
|
-
option.value.mapping,
|
|
156
|
-
`Execution context '${option.value.name}' does not have a mapping`,
|
|
157
|
-
).value.path;
|
|
153
|
+
const currentMappingPath = resolveExecutionContextMapping(
|
|
154
|
+
queryBuilderState.executionContext,
|
|
155
|
+
)?.path;
|
|
158
156
|
queryBuilderState.setExecutionContext(option.value);
|
|
159
157
|
await queryBuilderState.propagateExecutionContextChange(
|
|
160
|
-
currentMappingPath
|
|
158
|
+
currentMappingPath !== undefined &&
|
|
159
|
+
currentMappingPath ===
|
|
160
|
+
resolveExecutionContextMapping(option.value)?.path,
|
|
161
161
|
);
|
|
162
162
|
queryBuilderState.onExecutionContextChange?.(option.value);
|
|
163
163
|
};
|
|
@@ -200,16 +200,21 @@ const LegendQueryDataSpaceQueryBuilderSetupPanelContent = observer(
|
|
|
200
200
|
});
|
|
201
201
|
|
|
202
202
|
// class
|
|
203
|
+
const executionContextMapping = guaranteeNonNullable(
|
|
204
|
+
resolveExecutionContextMapping(queryBuilderState.executionContext),
|
|
205
|
+
`Execution context '${queryBuilderState.executionContext.name}' does not have a resolvable mapping`,
|
|
206
|
+
);
|
|
203
207
|
const classes = resolveUsableDataSpaceClasses(
|
|
204
208
|
queryBuilderState.dataSpace,
|
|
205
|
-
|
|
206
|
-
queryBuilderState.executionContext.mapping,
|
|
207
|
-
`Execution context '${queryBuilderState.executionContext.name}' does not have a mapping`,
|
|
208
|
-
).value,
|
|
209
|
+
executionContextMapping,
|
|
209
210
|
queryBuilderState.graphManagerState,
|
|
210
211
|
queryBuilderState,
|
|
211
212
|
);
|
|
212
213
|
|
|
214
|
+
const injectedLakehouseRuntime = queryBuilderState.injectedLakehouseRuntime;
|
|
215
|
+
const [isLakehouseConfigModalOpen, setIsLakehouseConfigModalOpen] =
|
|
216
|
+
useState(false);
|
|
217
|
+
|
|
213
218
|
useEffect(() => {
|
|
214
219
|
flowResult(queryBuilderState.loadEntities()).catch(
|
|
215
220
|
applicationStore.alertUnhandledError,
|
|
@@ -227,7 +232,7 @@ const LegendQueryDataSpaceQueryBuilderSetupPanelContent = observer(
|
|
|
227
232
|
<PanelHeader title="properties">
|
|
228
233
|
<PanelHeaderActions>
|
|
229
234
|
<PanelHeaderActionItem
|
|
230
|
-
title="copy data
|
|
235
|
+
title="copy data space query set up link to clipboard"
|
|
231
236
|
onClick={copyDataSpaceLinkToClipboard}
|
|
232
237
|
disabled={!queryBuilderState.isDataSpaceLinkable}
|
|
233
238
|
>
|
|
@@ -254,6 +259,18 @@ const LegendQueryDataSpaceQueryBuilderSetupPanelContent = observer(
|
|
|
254
259
|
Show Runtime Selector
|
|
255
260
|
</MenuContentItemLabel>
|
|
256
261
|
</MenuContentItem>
|
|
262
|
+
{injectedLakehouseRuntime && (
|
|
263
|
+
<MenuContentItem
|
|
264
|
+
onClick={(): void => setIsLakehouseConfigModalOpen(true)}
|
|
265
|
+
>
|
|
266
|
+
<MenuContentItemIcon>
|
|
267
|
+
<CogIcon />
|
|
268
|
+
</MenuContentItemIcon>
|
|
269
|
+
<MenuContentItemLabel>
|
|
270
|
+
Lakehouse Runtime Configuration
|
|
271
|
+
</MenuContentItemLabel>
|
|
272
|
+
</MenuContentItem>
|
|
273
|
+
)}
|
|
257
274
|
</MenuContent>
|
|
258
275
|
}
|
|
259
276
|
menuProps={{
|
|
@@ -269,10 +286,10 @@ const LegendQueryDataSpaceQueryBuilderSetupPanelContent = observer(
|
|
|
269
286
|
<div className="query-builder__setup__config-group__item">
|
|
270
287
|
<label
|
|
271
288
|
className="btn--sm query-builder__setup__config-group__data-product"
|
|
272
|
-
title="data
|
|
289
|
+
title="data space"
|
|
273
290
|
htmlFor="query-builder__setup__data-space-selector"
|
|
274
291
|
>
|
|
275
|
-
Data
|
|
292
|
+
Data Space
|
|
276
293
|
</label>
|
|
277
294
|
<CustomSelectorInput
|
|
278
295
|
inputId="query-builder__setup__data-space-selector"
|
|
@@ -281,7 +298,7 @@ const LegendQueryDataSpaceQueryBuilderSetupPanelContent = observer(
|
|
|
281
298
|
isLoading={queryBuilderState.loadEntitiesState.isInProgress}
|
|
282
299
|
onChange={onOptionChange}
|
|
283
300
|
value={selectedOption}
|
|
284
|
-
placeholder="Search for data
|
|
301
|
+
placeholder="Search for data space..."
|
|
285
302
|
escapeClearsValue={true}
|
|
286
303
|
darkMode={
|
|
287
304
|
!applicationStore.layoutService
|
|
@@ -295,7 +312,7 @@ const LegendQueryDataSpaceQueryBuilderSetupPanelContent = observer(
|
|
|
295
312
|
tabIndex={-1}
|
|
296
313
|
className="query-builder__setup__data-space-searcher__btn btn--dark"
|
|
297
314
|
onClick={openDataSpaceAdvancedSearch}
|
|
298
|
-
title="Open advanced search for data
|
|
315
|
+
title="Open advanced search for data space..."
|
|
299
316
|
>
|
|
300
317
|
<SearchIcon />
|
|
301
318
|
</button>
|
|
@@ -333,6 +350,7 @@ const LegendQueryDataSpaceQueryBuilderSetupPanelContent = observer(
|
|
|
333
350
|
!applicationStore.layoutService
|
|
334
351
|
.TEMPORARY__isLightColorThemeEnabled
|
|
335
352
|
}
|
|
353
|
+
formatOptionLabel={formatExecutionContextOptionLabel}
|
|
336
354
|
/>
|
|
337
355
|
</div>
|
|
338
356
|
)}
|
|
@@ -345,25 +363,52 @@ const LegendQueryDataSpaceQueryBuilderSetupPanelContent = observer(
|
|
|
345
363
|
>
|
|
346
364
|
Runtime
|
|
347
365
|
</label>
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
366
|
+
{injectedLakehouseRuntime ? (
|
|
367
|
+
<div
|
|
368
|
+
className="query-builder__setup__config-group__item__selector"
|
|
369
|
+
title="Lakehouse runtime — configure via the settings menu"
|
|
370
|
+
>
|
|
371
|
+
<CustomSelectorInput
|
|
372
|
+
inputId="query-builder__setup__runtime-selector"
|
|
373
|
+
className="panel__content__form__section__dropdown"
|
|
374
|
+
options={
|
|
375
|
+
selectedRuntimeOption ? [selectedRuntimeOption] : []
|
|
376
|
+
}
|
|
377
|
+
value={selectedRuntimeOption}
|
|
378
|
+
onChange={() => {}}
|
|
379
|
+
disabled={true}
|
|
380
|
+
darkMode={
|
|
381
|
+
!applicationStore.layoutService
|
|
382
|
+
.TEMPORARY__isLightColorThemeEnabled
|
|
383
|
+
}
|
|
384
|
+
formatOptionLabel={getRuntimeOptionFormatter({
|
|
385
|
+
darkMode:
|
|
386
|
+
!applicationStore.layoutService
|
|
387
|
+
.TEMPORARY__isLightColorThemeEnabled,
|
|
388
|
+
})}
|
|
389
|
+
/>
|
|
390
|
+
</div>
|
|
391
|
+
) : (
|
|
392
|
+
<CustomSelectorInput
|
|
393
|
+
inputId="query-builder__setup__runtime-selector"
|
|
394
|
+
className="panel__content__form__section__dropdown query-builder__setup__config-group__item__selector"
|
|
395
|
+
placeholder="Choose a runtime..."
|
|
396
|
+
noMatchMessage="No compatible runtime found for specified execution context"
|
|
397
|
+
options={runtimeOptions}
|
|
398
|
+
onChange={changeRuntime}
|
|
399
|
+
value={selectedRuntimeOption}
|
|
400
|
+
darkMode={
|
|
363
401
|
!applicationStore.layoutService
|
|
364
|
-
.TEMPORARY__isLightColorThemeEnabled
|
|
365
|
-
|
|
366
|
-
|
|
402
|
+
.TEMPORARY__isLightColorThemeEnabled
|
|
403
|
+
}
|
|
404
|
+
filterOption={runtimeFilterOption}
|
|
405
|
+
formatOptionLabel={getRuntimeOptionFormatter({
|
|
406
|
+
darkMode:
|
|
407
|
+
!applicationStore.layoutService
|
|
408
|
+
.TEMPORARY__isLightColorThemeEnabled,
|
|
409
|
+
})}
|
|
410
|
+
/>
|
|
411
|
+
)}
|
|
367
412
|
</div>
|
|
368
413
|
)}
|
|
369
414
|
<div className="query-builder__setup__config-group__item">
|
|
@@ -375,6 +420,17 @@ const LegendQueryDataSpaceQueryBuilderSetupPanelContent = observer(
|
|
|
375
420
|
/>
|
|
376
421
|
</div>
|
|
377
422
|
</div>
|
|
423
|
+
{injectedLakehouseRuntime && (
|
|
424
|
+
<LakehouseRuntimeConfigModal
|
|
425
|
+
lakehouseRuntime={injectedLakehouseRuntime}
|
|
426
|
+
open={isLakehouseConfigModalOpen}
|
|
427
|
+
onClose={() => setIsLakehouseConfigModalOpen(false)}
|
|
428
|
+
darkMode={
|
|
429
|
+
!applicationStore.layoutService
|
|
430
|
+
.TEMPORARY__isLightColorThemeEnabled
|
|
431
|
+
}
|
|
432
|
+
/>
|
|
433
|
+
)}
|
|
378
434
|
</div>
|
|
379
435
|
);
|
|
380
436
|
},
|
|
@@ -50,6 +50,7 @@ import {
|
|
|
50
50
|
type ValueSpecification,
|
|
51
51
|
type GraphInitializationReport,
|
|
52
52
|
PackageableRuntime,
|
|
53
|
+
createPath,
|
|
53
54
|
type QueryInfo,
|
|
54
55
|
GraphManagerState,
|
|
55
56
|
Query,
|
|
@@ -69,6 +70,7 @@ import {
|
|
|
69
70
|
cloneQueryTaggedValue,
|
|
70
71
|
QueryProjectCoordinates,
|
|
71
72
|
CORE_PURE_PATH,
|
|
73
|
+
INTERNAL_ELEMENT_PATH,
|
|
72
74
|
isValidFullPath,
|
|
73
75
|
QUERY_PROFILE_PATH,
|
|
74
76
|
QueryDataSpaceExecutionContextInfo,
|
|
@@ -147,6 +149,7 @@ import {
|
|
|
147
149
|
DSL_DataSpace_getGraphManagerExtension,
|
|
148
150
|
getOwnDataSpace,
|
|
149
151
|
QUERY_PROFILE_TAG_DATA_SPACE,
|
|
152
|
+
resolveExecutionContextMapping,
|
|
150
153
|
retrieveAnalyticsResultCache,
|
|
151
154
|
retrieveDataspaceArtifactsCache,
|
|
152
155
|
} from '@finos/legend-extension-dsl-data-space/graph';
|
|
@@ -810,7 +813,7 @@ export abstract class QueryEditorStore {
|
|
|
810
813
|
supportBuildMinimalGraph
|
|
811
814
|
) {
|
|
812
815
|
try {
|
|
813
|
-
this.initState.setMessage('Fetching data
|
|
816
|
+
this.initState.setMessage('Fetching data space analysis result...');
|
|
814
817
|
const project = StoreProjectData.serialization.fromJson(
|
|
815
818
|
await this.depotServerClient.getProject(groupId, artifactId),
|
|
816
819
|
);
|
|
@@ -1142,24 +1145,9 @@ export abstract class QueryEditorStore {
|
|
|
1142
1145
|
);
|
|
1143
1146
|
}
|
|
1144
1147
|
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
*
|
|
1149
|
-
* Resolution order:
|
|
1150
|
-
* 1. Check local storage (`LakehouseUserInfo`) for a previously persisted value.
|
|
1151
|
-
* 2. If not found, fetch from the lakehouse contract server via
|
|
1152
|
-
* `getUserEntitlementEnvs()` and persist the result to local storage.
|
|
1153
|
-
*/
|
|
1154
|
-
async createLakehousePackageableRuntime(
|
|
1155
|
-
dataProductPath: string,
|
|
1156
|
-
gav: {
|
|
1157
|
-
groupId: string;
|
|
1158
|
-
artifactId: string;
|
|
1159
|
-
versionId: string;
|
|
1160
|
-
},
|
|
1161
|
-
): Promise<PackageableRuntime> {
|
|
1162
|
-
// 1. Check local storage for persisted lakehouse user info
|
|
1148
|
+
async resolveLakehouseEnvAndWarehouse(
|
|
1149
|
+
isSnapshot: boolean,
|
|
1150
|
+
): Promise<{ env: string; warehouse: string }> {
|
|
1163
1151
|
const persistedInfo = LegendQueryUserDataHelper.getLakehouseUserInfo(
|
|
1164
1152
|
this.applicationStore.userDataService,
|
|
1165
1153
|
);
|
|
@@ -1167,7 +1155,6 @@ export abstract class QueryEditorStore {
|
|
|
1167
1155
|
let userEnvironment: string | undefined = persistedInfo?.env;
|
|
1168
1156
|
const userWarehouse: string =
|
|
1169
1157
|
persistedInfo?.snowflakeWarehouse ?? 'LAKEHOUSE_CONSUMER_DEFAULT_WH';
|
|
1170
|
-
// 2. If no persisted environment, fetch from the server
|
|
1171
1158
|
if (userEnvironment === undefined && this.lakehouseState) {
|
|
1172
1159
|
try {
|
|
1173
1160
|
const entitlementEnvs =
|
|
@@ -1178,7 +1165,6 @@ export abstract class QueryEditorStore {
|
|
|
1178
1165
|
userEnvironment = entitlementEnvs.users
|
|
1179
1166
|
.map((e) => e.lakehouseEnvironment)
|
|
1180
1167
|
.at(0);
|
|
1181
|
-
// Persist to local storage for future use
|
|
1182
1168
|
LegendQueryUserDataHelper.persistLakehouseUserInfo(
|
|
1183
1169
|
this.applicationStore.userDataService,
|
|
1184
1170
|
{
|
|
@@ -1197,30 +1183,82 @@ export abstract class QueryEditorStore {
|
|
|
1197
1183
|
|
|
1198
1184
|
if (userEnvironment === undefined) {
|
|
1199
1185
|
throw new Error(
|
|
1200
|
-
`
|
|
1201
|
-
`Please ensure your lakehouse entitlements are configured.`,
|
|
1186
|
+
`Unable to resolve lakehouse user environment. Please ensure your lakehouse entitlements are configured.`,
|
|
1202
1187
|
);
|
|
1203
1188
|
}
|
|
1204
|
-
if (
|
|
1205
|
-
isSnapshotVersion(gav.versionId) ||
|
|
1206
|
-
gav.versionId === SNAPSHOT_VERSION_ALIAS
|
|
1207
|
-
) {
|
|
1189
|
+
if (isSnapshot) {
|
|
1208
1190
|
userEnvironment = decorateEnvWithRealm(
|
|
1209
1191
|
userEnvironment,
|
|
1210
1192
|
LakehouseEnvironmentType.PRODUCTION_PARALLEL,
|
|
1211
1193
|
);
|
|
1212
1194
|
}
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1195
|
+
return { env: userEnvironment, warehouse: userWarehouse };
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
async createLakehousePackageableRuntime(
|
|
1199
|
+
dataProductPath: string,
|
|
1200
|
+
gav: {
|
|
1201
|
+
groupId: string;
|
|
1202
|
+
artifactId: string;
|
|
1203
|
+
versionId: string;
|
|
1204
|
+
},
|
|
1205
|
+
): Promise<PackageableRuntime> {
|
|
1206
|
+
const isSnapshot =
|
|
1207
|
+
isSnapshotVersion(gav.versionId) ||
|
|
1208
|
+
gav.versionId === SNAPSHOT_VERSION_ALIAS;
|
|
1209
|
+
const { env, warehouse } =
|
|
1210
|
+
await this.resolveLakehouseEnvAndWarehouse(isSnapshot);
|
|
1217
1211
|
const packageableRuntime = new PackageableRuntime(
|
|
1218
1212
|
`${dataProductPath}_LakehouseRuntime`,
|
|
1219
1213
|
);
|
|
1220
|
-
packageableRuntime.runtimeValue =
|
|
1214
|
+
packageableRuntime.runtimeValue = new LakehouseRuntime(env, warehouse);
|
|
1221
1215
|
return packageableRuntime;
|
|
1222
1216
|
}
|
|
1223
1217
|
|
|
1218
|
+
async createOrGetDataSpaceLakehouseFallbackRuntime(
|
|
1219
|
+
isSnapshot: boolean,
|
|
1220
|
+
): Promise<PackageableRuntime> {
|
|
1221
|
+
const runtimePath = createPath(INTERNAL_ELEMENT_PATH, 'LakehouseRuntime');
|
|
1222
|
+
const existing =
|
|
1223
|
+
this.graphManagerState.graph.getNullableRuntime(runtimePath);
|
|
1224
|
+
if (existing) {
|
|
1225
|
+
return existing;
|
|
1226
|
+
}
|
|
1227
|
+
const { env, warehouse } =
|
|
1228
|
+
await this.resolveLakehouseEnvAndWarehouse(isSnapshot);
|
|
1229
|
+
const created = new PackageableRuntime('LakehouseRuntime');
|
|
1230
|
+
created.runtimeValue = new LakehouseRuntime(env, warehouse);
|
|
1231
|
+
this.graphManagerState.graph.addElement(created, INTERNAL_ELEMENT_PATH);
|
|
1232
|
+
return created;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
async attachDataSpaceFallbackRuntimes(
|
|
1236
|
+
dataSpace: DataSpace,
|
|
1237
|
+
dataSpaceAnalysisResult: DataSpaceAnalysisResult | undefined,
|
|
1238
|
+
isSnapshot: boolean,
|
|
1239
|
+
): Promise<void> {
|
|
1240
|
+
const contexts = dataSpace.executionContexts ?? [];
|
|
1241
|
+
let sharedRuntime: PackageableRuntime | undefined;
|
|
1242
|
+
for (const context of contexts) {
|
|
1243
|
+
const analyticsContext =
|
|
1244
|
+
dataSpaceAnalysisResult?.executionContextsIndex.get(context.name);
|
|
1245
|
+
|
|
1246
|
+
if (
|
|
1247
|
+
context.mappingProvider === undefined ||
|
|
1248
|
+
context.defaultRuntime !== undefined ||
|
|
1249
|
+
(analyticsContext?.compatibleRuntimes.length ?? 0) !== 0
|
|
1250
|
+
) {
|
|
1251
|
+
continue;
|
|
1252
|
+
}
|
|
1253
|
+
if (!sharedRuntime) {
|
|
1254
|
+
sharedRuntime =
|
|
1255
|
+
await this.createOrGetDataSpaceLakehouseFallbackRuntime(isSnapshot);
|
|
1256
|
+
}
|
|
1257
|
+
context.defaultRuntime =
|
|
1258
|
+
PackageableElementExplicitReference.create(sharedRuntime);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1224
1262
|
/**
|
|
1225
1263
|
* Centralized method to build a data product query builder state.
|
|
1226
1264
|
* Used by both the creator flow (new query from data product route/picker)
|
|
@@ -1280,7 +1318,10 @@ export abstract class QueryEditorStore {
|
|
|
1280
1318
|
versionId,
|
|
1281
1319
|
},
|
|
1282
1320
|
);
|
|
1283
|
-
this.graphManagerState.graph.addElement(
|
|
1321
|
+
this.graphManagerState.graph.addElement(
|
|
1322
|
+
packageableRuntime,
|
|
1323
|
+
INTERNAL_ELEMENT_PATH,
|
|
1324
|
+
);
|
|
1284
1325
|
}
|
|
1285
1326
|
// 6. Create query builder state
|
|
1286
1327
|
const projectInfo = { groupId, artifactId, versionId };
|
|
@@ -1835,7 +1876,7 @@ export class ExistingQueryUpdateState {
|
|
|
1835
1876
|
* navigating to a chosen revision. A revision is keyed by its `version`
|
|
1836
1877
|
* identifier, which is passed as the `revisionId` route param.
|
|
1837
1878
|
*/
|
|
1838
|
-
const resolveExecutionContext = (
|
|
1879
|
+
export const resolveExecutionContext = (
|
|
1839
1880
|
dataSpace: DataSpace,
|
|
1840
1881
|
ex: string | undefined,
|
|
1841
1882
|
queryMapping: Mapping | undefined,
|
|
@@ -1847,20 +1888,22 @@ const resolveExecutionContext = (
|
|
|
1847
1888
|
}
|
|
1848
1889
|
const defaultExecutionContext = dataSpace.defaultExecutionContext;
|
|
1849
1890
|
if (!defaultExecutionContext) {
|
|
1850
|
-
return
|
|
1891
|
+
return executionContexts[0];
|
|
1851
1892
|
}
|
|
1852
1893
|
if (queryMapping && queryRuntime) {
|
|
1853
|
-
const defaultExecutionContextMapping =
|
|
1894
|
+
const defaultExecutionContextMapping = resolveExecutionContextMapping(
|
|
1895
|
+
defaultExecutionContext,
|
|
1896
|
+
);
|
|
1854
1897
|
const defaultExecutionContextRuntime =
|
|
1855
1898
|
defaultExecutionContext.defaultRuntime;
|
|
1856
1899
|
if (
|
|
1857
1900
|
defaultExecutionContextMapping &&
|
|
1858
1901
|
defaultExecutionContextRuntime &&
|
|
1859
|
-
defaultExecutionContextMapping
|
|
1902
|
+
defaultExecutionContextMapping !== queryMapping &&
|
|
1860
1903
|
defaultExecutionContextRuntime.value.path !== queryRuntime.path
|
|
1861
1904
|
) {
|
|
1862
1905
|
const matchingExecContexts = executionContexts.filter(
|
|
1863
|
-
(ec) => ec
|
|
1906
|
+
(ec) => resolveExecutionContextMapping(ec) === queryMapping,
|
|
1864
1907
|
);
|
|
1865
1908
|
if (matchingExecContexts.length > 1) {
|
|
1866
1909
|
const matchRuntime = matchingExecContexts.find(
|
|
@@ -2100,6 +2143,12 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
|
|
|
2100
2143
|
exec.dataSpacePath,
|
|
2101
2144
|
this.graphManagerState.graph,
|
|
2102
2145
|
);
|
|
2146
|
+
await this.attachDataSpaceFallbackRuntimes(
|
|
2147
|
+
dataSpace,
|
|
2148
|
+
dataSpaceAnalysisResult,
|
|
2149
|
+
isSnapshotVersion(queryInfo.versionId) ||
|
|
2150
|
+
queryInfo.versionId === SNAPSHOT_VERSION_ALIAS,
|
|
2151
|
+
);
|
|
2103
2152
|
const mapping = queryInfo.mapping
|
|
2104
2153
|
? this.graphManagerState.graph.getMapping(queryInfo.mapping)
|
|
2105
2154
|
: undefined;
|
|
@@ -2228,36 +2277,43 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
|
|
|
2228
2277
|
this.applicationStore.config.options.queryBuilderConfig,
|
|
2229
2278
|
sourceInfo,
|
|
2230
2279
|
);
|
|
2231
|
-
const matchingExecutionContextMapping =
|
|
2232
|
-
matchingExecutionContext
|
|
2233
|
-
`Execution context '${matchingExecutionContext.name}' does not have a mapping`,
|
|
2234
|
-
);
|
|
2235
|
-
const matchingExecutionContextRuntime = guaranteeNonNullable(
|
|
2236
|
-
matchingExecutionContext.defaultRuntime,
|
|
2237
|
-
`Execution context '${matchingExecutionContext.name}' does not have a default runtime`,
|
|
2280
|
+
const matchingExecutionContextMapping = resolveExecutionContextMapping(
|
|
2281
|
+
matchingExecutionContext,
|
|
2238
2282
|
);
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2283
|
+
if (
|
|
2284
|
+
matchingExecutionContext.mappingProvider &&
|
|
2285
|
+
!matchingExecutionContextMapping
|
|
2286
|
+
) {
|
|
2287
|
+
throw new Error(
|
|
2288
|
+
`Execution context '${matchingExecutionContext.name}' in data space '${dataSpace.path}' sources its mapping from a data product access point group that does not exist.`,
|
|
2242
2289
|
);
|
|
2290
|
+
}
|
|
2291
|
+
const mappingModelCoverageAnalysisResult =
|
|
2292
|
+
matchingExecutionContextMapping
|
|
2293
|
+
? dataSpaceAnalysisResult?.mappingToMappingCoverageResult?.get(
|
|
2294
|
+
matchingExecutionContextMapping.path,
|
|
2295
|
+
)
|
|
2296
|
+
: undefined;
|
|
2243
2297
|
if (mappingModelCoverageAnalysisResult) {
|
|
2244
2298
|
dataSpaceQueryBuilderState.explorerState.mappingModelCoverageAnalysisResult =
|
|
2245
2299
|
mappingModelCoverageAnalysisResult;
|
|
2246
2300
|
}
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2301
|
+
if (matchingExecutionContextMapping) {
|
|
2302
|
+
dataSpaceQueryBuilderState.executionContextState.setMapping(
|
|
2303
|
+
matchingExecutionContextMapping,
|
|
2304
|
+
);
|
|
2305
|
+
}
|
|
2306
|
+
const matchingExecutionContextRuntime =
|
|
2307
|
+
matchingExecutionContext.defaultRuntime
|
|
2308
|
+
? new RuntimePointer(matchingExecutionContext.defaultRuntime)
|
|
2309
|
+
: undefined;
|
|
2250
2310
|
dataSpaceQueryBuilderState.executionContextState.setRuntimeValue(
|
|
2251
|
-
|
|
2252
|
-
PackageableElementExplicitReference.create(
|
|
2253
|
-
matchingExecutionContextRuntime.value,
|
|
2254
|
-
),
|
|
2255
|
-
),
|
|
2311
|
+
matchingExecutionContextRuntime,
|
|
2256
2312
|
);
|
|
2257
2313
|
return dataSpaceQueryBuilderState;
|
|
2258
2314
|
} else {
|
|
2259
|
-
throw new
|
|
2260
|
-
`
|
|
2315
|
+
throw new Error(
|
|
2316
|
+
`Execution context '${exec.executionKey}' does not exist in data space '${dataSpace.path}'.`,
|
|
2261
2317
|
);
|
|
2262
2318
|
}
|
|
2263
2319
|
} else if (exec instanceof QueryExplicitExecutionContextInfo) {
|
|
@@ -2347,7 +2403,10 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
|
|
|
2347
2403
|
exec.ingestDefinitionPath,
|
|
2348
2404
|
projectInfo,
|
|
2349
2405
|
);
|
|
2350
|
-
this.graphManagerState.graph.addElement(
|
|
2406
|
+
this.graphManagerState.graph.addElement(
|
|
2407
|
+
adhocRuntime,
|
|
2408
|
+
INTERNAL_ELEMENT_PATH,
|
|
2409
|
+
);
|
|
2351
2410
|
|
|
2352
2411
|
// Tracked separately from the closure on `ingestQueryBuilderState` so
|
|
2353
2412
|
// the swap callback can capture it directly without forming a self-
|