@finos/legend-application-studio 28.21.27 → 28.21.29
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__/LegendStudioDocumentation.d.ts +1 -0
- package/lib/__lib__/LegendStudioDocumentation.d.ts.map +1 -1
- package/lib/__lib__/LegendStudioDocumentation.js +2 -0
- package/lib/__lib__/LegendStudioDocumentation.js.map +1 -1
- package/lib/__lib__/LegendStudioEvent.d.ts +6 -0
- package/lib/__lib__/LegendStudioEvent.d.ts.map +1 -1
- package/lib/__lib__/LegendStudioEvent.js +7 -0
- package/lib/__lib__/LegendStudioEvent.js.map +1 -1
- package/lib/__lib__/LegendStudioTelemetryHelper.d.ts +6 -0
- package/lib/__lib__/LegendStudioTelemetryHelper.d.ts.map +1 -1
- package/lib/__lib__/LegendStudioTelemetryHelper.js +19 -0
- package/lib/__lib__/LegendStudioTelemetryHelper.js.map +1 -1
- package/lib/components/editor/editor-group/dataProduct/DataProductEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js +15 -1
- package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js.map +1 -1
- package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.js +100 -6
- package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.js.map +1 -1
- package/lib/components/editor/editor-group/service-editor/ServiceEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/service-editor/ServiceEditor.js +16 -3
- package/lib/components/editor/editor-group/service-editor/ServiceEditor.js.map +1 -1
- package/lib/components/editor/editor-group/testable/LakehouseTestableEditor.d.ts +4 -0
- package/lib/components/editor/editor-group/testable/LakehouseTestableEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/testable/LakehouseTestableEditor.js +10 -6
- package/lib/components/editor/editor-group/testable/LakehouseTestableEditor.js.map +1 -1
- package/lib/index.css +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/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.d.ts +6 -1
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.js +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.js.map +1 -1
- package/lib/stores/extensions/DSL_DataSpace_LegendStudioApplicationPlugin_Extension.d.ts +41 -0
- package/lib/stores/extensions/DSL_DataSpace_LegendStudioApplicationPlugin_Extension.d.ts.map +1 -0
- package/lib/stores/extensions/DSL_DataSpace_LegendStudioApplicationPlugin_Extension.js +17 -0
- package/lib/stores/extensions/DSL_DataSpace_LegendStudioApplicationPlugin_Extension.js.map +1 -0
- package/package.json +16 -16
- package/src/__lib__/LegendStudioDocumentation.ts +3 -0
- package/src/__lib__/LegendStudioEvent.ts +8 -0
- package/src/__lib__/LegendStudioTelemetryHelper.ts +64 -0
- package/src/components/editor/editor-group/dataProduct/DataProductEditor.tsx +24 -0
- package/src/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.tsx +373 -4
- package/src/components/editor/editor-group/service-editor/ServiceEditor.tsx +29 -3
- package/src/components/editor/editor-group/testable/LakehouseTestableEditor.tsx +26 -5
- package/src/index.ts +3 -0
- package/src/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.ts +1 -1
- package/src/stores/extensions/DSL_DataSpace_LegendStudioApplicationPlugin_Extension.ts +54 -0
- package/tsconfig.json +1 -0
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=DSL_DataSpace_LegendStudioApplicationPlugin_Extension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DSL_DataSpace_LegendStudioApplicationPlugin_Extension.js","sourceRoot":"","sources":["../../../src/stores/extensions/DSL_DataSpace_LegendStudioApplicationPlugin_Extension.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finos/legend-application-studio",
|
|
3
|
-
"version": "28.21.
|
|
3
|
+
"version": "28.21.29",
|
|
4
4
|
"description": "Legend Studio application core",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"legend",
|
|
@@ -47,21 +47,21 @@
|
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@dagrejs/dagre": "1.1.4",
|
|
50
|
-
"@finos/legend-application": "16.0.
|
|
51
|
-
"@finos/legend-art": "7.1.
|
|
52
|
-
"@finos/legend-code-editor": "2.0.
|
|
53
|
-
"@finos/legend-data-cube": "0.3.
|
|
54
|
-
"@finos/legend-extension-dsl-data-product": "0.0.
|
|
55
|
-
"@finos/legend-extension-dsl-diagram": "8.1.
|
|
56
|
-
"@finos/legend-graph": "32.6.
|
|
57
|
-
"@finos/legend-lego": "2.0.
|
|
58
|
-
"@finos/legend-query-builder": "4.18.
|
|
59
|
-
"@finos/legend-server-depot": "6.1.
|
|
60
|
-
"@finos/legend-server-lakehouse": "0.3.
|
|
61
|
-
"@finos/legend-server-sdlc": "5.4.
|
|
62
|
-
"@finos/legend-server-showcase": "0.2.
|
|
63
|
-
"@finos/legend-shared": "11.0.
|
|
64
|
-
"@finos/legend-storage": "3.0.
|
|
50
|
+
"@finos/legend-application": "16.0.118",
|
|
51
|
+
"@finos/legend-art": "7.1.158",
|
|
52
|
+
"@finos/legend-code-editor": "2.0.193",
|
|
53
|
+
"@finos/legend-data-cube": "0.3.110",
|
|
54
|
+
"@finos/legend-extension-dsl-data-product": "0.0.103",
|
|
55
|
+
"@finos/legend-extension-dsl-diagram": "8.1.257",
|
|
56
|
+
"@finos/legend-graph": "32.6.24",
|
|
57
|
+
"@finos/legend-lego": "2.0.213",
|
|
58
|
+
"@finos/legend-query-builder": "4.18.32",
|
|
59
|
+
"@finos/legend-server-depot": "6.1.17",
|
|
60
|
+
"@finos/legend-server-lakehouse": "0.3.73",
|
|
61
|
+
"@finos/legend-server-sdlc": "5.4.7",
|
|
62
|
+
"@finos/legend-server-showcase": "0.2.68",
|
|
63
|
+
"@finos/legend-shared": "11.0.27",
|
|
64
|
+
"@finos/legend-storage": "3.0.149",
|
|
65
65
|
"@testing-library/dom": "10.4.0",
|
|
66
66
|
"@testing-library/react": "16.2.0",
|
|
67
67
|
"@types/react": "19.0.10",
|
|
@@ -86,6 +86,9 @@ export enum LEGEND_STUDIO_DOCUMENTATION_KEY {
|
|
|
86
86
|
// sdlc
|
|
87
87
|
QUESTION_WHAT_ARE_PROJECT_ROLES = 'question.what-are-project-roles',
|
|
88
88
|
|
|
89
|
+
// legend AI
|
|
90
|
+
LEGENDAI_HOW_TO_GET_ENTITLEMENTS = 'legend-ai.how-to-get-entitlements',
|
|
91
|
+
|
|
89
92
|
// contexts
|
|
90
93
|
CONTEXT_CLASS_EDITOR = 'context.class-editor',
|
|
91
94
|
CONTEXT_SERVICE_TEST_EDITOR = 'context.service-editor.test',
|
|
@@ -90,11 +90,19 @@ export enum LEGEND_STUDIO_APP_EVENT {
|
|
|
90
90
|
DATA_PRODUCT_LEGENDAI_SUGGEST__LAUNCH = 'editor.data-product.legendai-suggest.launch',
|
|
91
91
|
DATA_PRODUCT_LEGENDAI_SUGGEST__APPLY = 'editor.data-product.legendai-suggest.apply',
|
|
92
92
|
DATA_PRODUCT_LEGENDAI_SUGGEST__DISCARD = 'editor.data-product.legendai-suggest.discard',
|
|
93
|
+
DATA_PRODUCT_LEGENDAI_SUGGEST__FAILURE = 'editor.data-product.legendai-suggest.failure',
|
|
94
|
+
|
|
95
|
+
// dataspace
|
|
96
|
+
DATASPACE_LEGENDAI_SUGGEST__LAUNCH = 'editor.dataspace.legendai-suggest.launch',
|
|
97
|
+
DATASPACE_LEGENDAI_SUGGEST__APPLY = 'editor.dataspace.legendai-suggest.apply',
|
|
98
|
+
DATASPACE_LEGENDAI_SUGGEST__DISCARD = 'editor.dataspace.legendai-suggest.discard',
|
|
99
|
+
DATASPACE_LEGENDAI_SUGGEST__FAILURE = 'editor.dataspace.legendai-suggest.failure',
|
|
93
100
|
|
|
94
101
|
// service
|
|
95
102
|
SERVICE_LEGENDAI_SUGGEST__LAUNCH = 'editor.service-editor.legendai-suggest.launch',
|
|
96
103
|
SERVICE_LEGENDAI_SUGGEST__APPLY = 'editor.service-editor.legendai-suggest.apply',
|
|
97
104
|
SERVICE_LEGENDAI_SUGGEST__DISCARD = 'editor.service-editor.legendai-suggest.discard',
|
|
105
|
+
SERVICE_LEGENDAI_SUGGEST__FAILURE = 'editor.service-editor.legendai-suggest.failure',
|
|
98
106
|
|
|
99
107
|
// push to dev
|
|
100
108
|
METADATA_PUSH_TO_METADATA = 'editor.metadata.push-to-metadata',
|
|
@@ -214,6 +214,59 @@ export class LegendStudioTelemetryHelper {
|
|
|
214
214
|
);
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
static logEvent_ServiceLegendAISuggestFailure(
|
|
218
|
+
telemetryService: TelemetryService,
|
|
219
|
+
servicePath: string,
|
|
220
|
+
errorMessage: string,
|
|
221
|
+
): void {
|
|
222
|
+
telemetryService.logEvent(
|
|
223
|
+
LEGEND_STUDIO_APP_EVENT.SERVICE_LEGENDAI_SUGGEST__FAILURE,
|
|
224
|
+
{ servicePath, errorMessage },
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// DataSpace Legend AI
|
|
229
|
+
static logEvent_DataSpaceLegendAISuggestLaunched(
|
|
230
|
+
telemetryService: TelemetryService,
|
|
231
|
+
dataSpacePath: string,
|
|
232
|
+
): void {
|
|
233
|
+
telemetryService.logEvent(
|
|
234
|
+
LEGEND_STUDIO_APP_EVENT.DATASPACE_LEGENDAI_SUGGEST__LAUNCH,
|
|
235
|
+
{ dataSpacePath },
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
static logEvent_DataSpaceLegendAISuggestApplied(
|
|
240
|
+
telemetryService: TelemetryService,
|
|
241
|
+
dataSpacePath: string,
|
|
242
|
+
): void {
|
|
243
|
+
telemetryService.logEvent(
|
|
244
|
+
LEGEND_STUDIO_APP_EVENT.DATASPACE_LEGENDAI_SUGGEST__APPLY,
|
|
245
|
+
{ dataSpacePath },
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
static logEvent_DataSpaceLegendAISuggestDiscarded(
|
|
250
|
+
telemetryService: TelemetryService,
|
|
251
|
+
dataSpacePath: string,
|
|
252
|
+
): void {
|
|
253
|
+
telemetryService.logEvent(
|
|
254
|
+
LEGEND_STUDIO_APP_EVENT.DATASPACE_LEGENDAI_SUGGEST__DISCARD,
|
|
255
|
+
{ dataSpacePath },
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
static logEvent_DataSpaceLegendAISuggestFailure(
|
|
260
|
+
telemetryService: TelemetryService,
|
|
261
|
+
dataSpacePath: string,
|
|
262
|
+
errorMessage: string,
|
|
263
|
+
): void {
|
|
264
|
+
telemetryService.logEvent(
|
|
265
|
+
LEGEND_STUDIO_APP_EVENT.DATASPACE_LEGENDAI_SUGGEST__FAILURE,
|
|
266
|
+
{ dataSpacePath, errorMessage },
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
217
270
|
static logEvent_DataProductLegendAISuggestLaunched(
|
|
218
271
|
telemetryService: TelemetryService,
|
|
219
272
|
dataProductPath: string,
|
|
@@ -244,6 +297,17 @@ export class LegendStudioTelemetryHelper {
|
|
|
244
297
|
);
|
|
245
298
|
}
|
|
246
299
|
|
|
300
|
+
static logEvent_DataProductLegendAISuggestFailure(
|
|
301
|
+
telemetryService: TelemetryService,
|
|
302
|
+
dataProductPath: string,
|
|
303
|
+
errorMessage: string,
|
|
304
|
+
): void {
|
|
305
|
+
telemetryService.logEvent(
|
|
306
|
+
LEGEND_STUDIO_APP_EVENT.DATA_PRODUCT_LEGENDAI_SUGGEST__FAILURE,
|
|
307
|
+
{ dataProductPath, errorMessage },
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
|
|
247
311
|
// Lakehouse
|
|
248
312
|
static logEvent_LakehouseDeployIngest(
|
|
249
313
|
service: TelemetryService,
|
|
@@ -95,7 +95,9 @@ import {
|
|
|
95
95
|
assertErrorThrown,
|
|
96
96
|
guaranteeNonNullable,
|
|
97
97
|
guaranteeType,
|
|
98
|
+
HttpStatus,
|
|
98
99
|
isNonNullable,
|
|
100
|
+
NetworkClientError,
|
|
99
101
|
UserSearchService,
|
|
100
102
|
} from '@finos/legend-shared';
|
|
101
103
|
import {
|
|
@@ -209,6 +211,7 @@ import type {
|
|
|
209
211
|
DSL_DataProduct_LegendStudioApplicationPlugin_Extension,
|
|
210
212
|
} from '../../../../stores/extensions/DSL_DataProduct_LegendStudioApplicationPlugin_Extension.js';
|
|
211
213
|
import { LegendStudioTelemetryHelper } from '../../../../__lib__/LegendStudioTelemetryHelper.js';
|
|
214
|
+
import { LEGEND_STUDIO_DOCUMENTATION_KEY } from '../../../../__lib__/LegendStudioDocumentation.js';
|
|
212
215
|
|
|
213
216
|
export enum AP_GROUP_MODAL_ERRORS {
|
|
214
217
|
GROUP_NAME_EMPTY = 'Group Name is empty',
|
|
@@ -1872,6 +1875,27 @@ const AccessPointGroupEditor = observer(
|
|
|
1872
1875
|
runInAction(() => {
|
|
1873
1876
|
setAISuggestion(suggestion);
|
|
1874
1877
|
});
|
|
1878
|
+
} catch (error) {
|
|
1879
|
+
assertErrorThrown(error);
|
|
1880
|
+
LegendStudioTelemetryHelper.logEvent_DataProductLegendAISuggestFailure(
|
|
1881
|
+
editorStore.applicationStore.telemetryService,
|
|
1882
|
+
productEditorState.product.path,
|
|
1883
|
+
error.message,
|
|
1884
|
+
);
|
|
1885
|
+
if (
|
|
1886
|
+
error instanceof NetworkClientError &&
|
|
1887
|
+
(error.response.status === HttpStatus.UNAUTHORIZED ||
|
|
1888
|
+
error.response.status === HttpStatus.FORBIDDEN)
|
|
1889
|
+
) {
|
|
1890
|
+
const docEntry =
|
|
1891
|
+
editorStore.applicationStore.documentationService.getDocEntry(
|
|
1892
|
+
LEGEND_STUDIO_DOCUMENTATION_KEY.LEGENDAI_HOW_TO_GET_ENTITLEMENTS,
|
|
1893
|
+
);
|
|
1894
|
+
if (docEntry?.url) {
|
|
1895
|
+
error.message = `${error.message}. Please check how to get entitlements: ${docEntry.url}`;
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
throw error;
|
|
1875
1899
|
} finally {
|
|
1876
1900
|
runInAction(() => {
|
|
1877
1901
|
setIsSuggestingWithAI(false);
|
package/src/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.tsx
CHANGED
|
@@ -17,11 +17,13 @@
|
|
|
17
17
|
import { observer } from 'mobx-react-lite';
|
|
18
18
|
import { flowResult } from 'mobx';
|
|
19
19
|
import {
|
|
20
|
+
BlankPanelContent,
|
|
20
21
|
BlankPanelPlaceholder,
|
|
21
22
|
clsx,
|
|
22
23
|
ContextMenu,
|
|
23
24
|
CustomSelectorInput,
|
|
24
25
|
Dialog,
|
|
26
|
+
FilledWindowMaximizeIcon,
|
|
25
27
|
MenuContent,
|
|
26
28
|
MenuContentItem,
|
|
27
29
|
Modal,
|
|
@@ -37,20 +39,42 @@ import {
|
|
|
37
39
|
PanelHeaderActions,
|
|
38
40
|
PanelLoadingIndicator,
|
|
39
41
|
PlusIcon,
|
|
42
|
+
RefreshIcon,
|
|
43
|
+
TimesIcon,
|
|
40
44
|
} from '@finos/legend-art';
|
|
41
|
-
import
|
|
45
|
+
import {
|
|
46
|
+
PrimitiveInstanceValue,
|
|
47
|
+
PrimitiveType,
|
|
48
|
+
type DataProductTestSuite,
|
|
49
|
+
type ValueSpecification,
|
|
50
|
+
} from '@finos/legend-graph';
|
|
42
51
|
import type { DataProductEditorState } from '../../../../../stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js';
|
|
43
52
|
import {
|
|
53
|
+
DataProductValueSpecificationTestParameterState,
|
|
54
|
+
type DataProductTestParameterState,
|
|
55
|
+
DataProductTestState,
|
|
56
|
+
getAccessPointLambda,
|
|
44
57
|
type DataProductTestableState,
|
|
45
58
|
type DataProductTestSuiteState,
|
|
46
59
|
} from '../../../../../stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.js';
|
|
47
|
-
import { forwardRef, useRef, useState } from 'react';
|
|
48
|
-
import {
|
|
60
|
+
import { forwardRef, useEffect, useRef, useState } from 'react';
|
|
61
|
+
import {
|
|
62
|
+
getContentTypeWithParamFromQuery,
|
|
63
|
+
type TestParamContentType,
|
|
64
|
+
validateTestableId,
|
|
65
|
+
} from '../../../../../stores/editor/utils/TestableUtils.js';
|
|
49
66
|
import { useEditorStore } from '../../../EditorStoreProvider.js';
|
|
50
67
|
import { guaranteeNonNullable } from '@finos/legend-shared';
|
|
51
|
-
import {
|
|
68
|
+
import {
|
|
69
|
+
ExternalFormatParameterEditorModal,
|
|
70
|
+
RenameModal,
|
|
71
|
+
} from '../../testable/TestableSharedComponents.js';
|
|
52
72
|
import { testSuite_setId } from '../../../../../stores/graph-modifier/Testable_GraphModifierHelper.js';
|
|
53
73
|
import { LakehouseTestSuiteEditor } from '../../testable/LakehouseTestableEditor.js';
|
|
74
|
+
import {
|
|
75
|
+
BasicValueSpecificationEditor,
|
|
76
|
+
instanceValue_setValue,
|
|
77
|
+
} from '@finos/legend-query-builder';
|
|
54
78
|
|
|
55
79
|
// ─── Create Suite Modal ───────────────────────────────────────────────────────
|
|
56
80
|
|
|
@@ -291,6 +315,343 @@ const CreateTestModal = observer(
|
|
|
291
315
|
},
|
|
292
316
|
);
|
|
293
317
|
|
|
318
|
+
const DataProductTestParameterEditor = observer(
|
|
319
|
+
(props: {
|
|
320
|
+
testState: DataProductTestState;
|
|
321
|
+
paramState: DataProductTestParameterState;
|
|
322
|
+
isReadOnly: boolean;
|
|
323
|
+
contentTypeParamPair: TestParamContentType | undefined;
|
|
324
|
+
}) => {
|
|
325
|
+
const { testState, paramState, isReadOnly, contentTypeParamPair } = props;
|
|
326
|
+
const [showPopUp, setShowPopup] = useState(false);
|
|
327
|
+
const valueSpecParamState =
|
|
328
|
+
paramState instanceof DataProductValueSpecificationTestParameterState
|
|
329
|
+
? paramState
|
|
330
|
+
: undefined;
|
|
331
|
+
const valueSpec = valueSpecParamState?.valueSpec;
|
|
332
|
+
|
|
333
|
+
const paramIsRequired = Boolean(
|
|
334
|
+
testState.queryVariableExpressions.find(
|
|
335
|
+
(v) =>
|
|
336
|
+
v.name === paramState.parameterValue.name &&
|
|
337
|
+
v.multiplicity.lowerBound > 0,
|
|
338
|
+
),
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
const showCodeEditor =
|
|
342
|
+
Boolean(contentTypeParamPair) &&
|
|
343
|
+
valueSpecParamState?.varExpression.genericType?.value.rawType ===
|
|
344
|
+
PrimitiveType.STRING &&
|
|
345
|
+
valueSpec instanceof PrimitiveInstanceValue;
|
|
346
|
+
|
|
347
|
+
const type = contentTypeParamPair
|
|
348
|
+
? contentTypeParamPair.contentType
|
|
349
|
+
: (valueSpecParamState?.varExpression.genericType?.value.rawType.name ??
|
|
350
|
+
'unknown');
|
|
351
|
+
|
|
352
|
+
const openInPopUp = (): void => setShowPopup(!showPopUp);
|
|
353
|
+
const closePopUp = (): void => setShowPopup(false);
|
|
354
|
+
|
|
355
|
+
const updateParamValue = (val: string): void => {
|
|
356
|
+
if (
|
|
357
|
+
!(valueSpec instanceof PrimitiveInstanceValue) ||
|
|
358
|
+
!valueSpecParamState
|
|
359
|
+
) {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
const nextValue =
|
|
363
|
+
valueSpecParamState.varExpression.genericType?.value.rawType ===
|
|
364
|
+
PrimitiveType.BYTE
|
|
365
|
+
? btoa(val)
|
|
366
|
+
: val;
|
|
367
|
+
instanceValue_setValue(
|
|
368
|
+
valueSpec,
|
|
369
|
+
nextValue,
|
|
370
|
+
0,
|
|
371
|
+
testState.editorStore.changeDetectionState.observerContext,
|
|
372
|
+
);
|
|
373
|
+
valueSpecParamState.updateValueSpecification(valueSpec);
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
return (
|
|
377
|
+
<div
|
|
378
|
+
key={paramState.parameterValue.name}
|
|
379
|
+
className="panel__content__form__section"
|
|
380
|
+
>
|
|
381
|
+
<div className="panel__content__form__section__header__label">
|
|
382
|
+
{paramState.parameterValue.name}
|
|
383
|
+
<button
|
|
384
|
+
className={clsx('type-tree__node__type__label', {})}
|
|
385
|
+
tabIndex={-1}
|
|
386
|
+
title={type}
|
|
387
|
+
>
|
|
388
|
+
{type}
|
|
389
|
+
</button>
|
|
390
|
+
</div>
|
|
391
|
+
|
|
392
|
+
{!valueSpecParamState && (
|
|
393
|
+
<BlankPanelContent>Unsupported parameter value</BlankPanelContent>
|
|
394
|
+
)}
|
|
395
|
+
|
|
396
|
+
{valueSpecParamState &&
|
|
397
|
+
showCodeEditor &&
|
|
398
|
+
valueSpec instanceof PrimitiveInstanceValue && (
|
|
399
|
+
<div className="data-product-test-editor__parameter__code-editor">
|
|
400
|
+
<textarea
|
|
401
|
+
className="panel__content__form__section__textarea value-spec-editor__input"
|
|
402
|
+
spellCheck={false}
|
|
403
|
+
value={
|
|
404
|
+
valueSpecParamState.varExpression.genericType?.value
|
|
405
|
+
.rawType === PrimitiveType.BYTE
|
|
406
|
+
? atob(valueSpec.values[0] as string)
|
|
407
|
+
: (valueSpec.values[0] as string)
|
|
408
|
+
}
|
|
409
|
+
placeholder={
|
|
410
|
+
(valueSpec.values[0] as string) === '' ? '(empty)' : undefined
|
|
411
|
+
}
|
|
412
|
+
onChange={(event) => updateParamValue(event.target.value)}
|
|
413
|
+
/>
|
|
414
|
+
{showPopUp && (
|
|
415
|
+
<ExternalFormatParameterEditorModal
|
|
416
|
+
valueSpec={valueSpecParamState.valueSpec}
|
|
417
|
+
varExpression={valueSpecParamState.varExpression}
|
|
418
|
+
onClose={closePopUp}
|
|
419
|
+
isReadOnly={isReadOnly}
|
|
420
|
+
updateParamValue={updateParamValue}
|
|
421
|
+
contentTypeParamPair={guaranteeNonNullable(
|
|
422
|
+
contentTypeParamPair,
|
|
423
|
+
)}
|
|
424
|
+
/>
|
|
425
|
+
)}
|
|
426
|
+
<div className="data-product-test-editor__parameter__value__actions">
|
|
427
|
+
<button
|
|
428
|
+
className="data-product-test-editor__parameter__code-editor__expand-btn"
|
|
429
|
+
onClick={openInPopUp}
|
|
430
|
+
tabIndex={-1}
|
|
431
|
+
title="Open in a popup..."
|
|
432
|
+
>
|
|
433
|
+
<FilledWindowMaximizeIcon />
|
|
434
|
+
</button>
|
|
435
|
+
<button
|
|
436
|
+
className="btn--icon btn--dark btn--sm data-product-test-editor__parameter__code-editor__expand-btn"
|
|
437
|
+
disabled={isReadOnly || paramIsRequired}
|
|
438
|
+
onClick={(): void =>
|
|
439
|
+
testState.removeParamValueState(paramState)
|
|
440
|
+
}
|
|
441
|
+
tabIndex={-1}
|
|
442
|
+
title={
|
|
443
|
+
paramIsRequired ? 'Parameter Required' : 'Remove Parameter'
|
|
444
|
+
}
|
|
445
|
+
>
|
|
446
|
+
<TimesIcon />
|
|
447
|
+
</button>
|
|
448
|
+
</div>
|
|
449
|
+
</div>
|
|
450
|
+
)}
|
|
451
|
+
|
|
452
|
+
{valueSpecParamState && !showCodeEditor && (
|
|
453
|
+
<div className="data-product-test-editor__parameter__value">
|
|
454
|
+
<BasicValueSpecificationEditor
|
|
455
|
+
valueSpecification={valueSpecParamState.valueSpec}
|
|
456
|
+
setValueSpecification={(val: ValueSpecification): void => {
|
|
457
|
+
valueSpecParamState.updateValueSpecification(val);
|
|
458
|
+
}}
|
|
459
|
+
graph={testState.editorStore.graphManagerState.graph}
|
|
460
|
+
observerContext={
|
|
461
|
+
testState.editorStore.changeDetectionState.observerContext
|
|
462
|
+
}
|
|
463
|
+
typeCheckOption={{
|
|
464
|
+
expectedType:
|
|
465
|
+
valueSpecParamState.varExpression.genericType?.value
|
|
466
|
+
.rawType ?? PrimitiveType.STRING,
|
|
467
|
+
}}
|
|
468
|
+
className="query-builder__parameters__value__editor"
|
|
469
|
+
resetValue={(): void => {
|
|
470
|
+
valueSpecParamState.resetValueSpec();
|
|
471
|
+
}}
|
|
472
|
+
/>
|
|
473
|
+
<div className="data-product-test-editor__parameter__value__actions">
|
|
474
|
+
<button
|
|
475
|
+
className="btn--icon btn--dark btn--sm"
|
|
476
|
+
disabled={isReadOnly || paramIsRequired}
|
|
477
|
+
onClick={(): void =>
|
|
478
|
+
testState.removeParamValueState(paramState)
|
|
479
|
+
}
|
|
480
|
+
tabIndex={-1}
|
|
481
|
+
title={
|
|
482
|
+
paramIsRequired ? 'Parameter Required' : 'Remove Parameter'
|
|
483
|
+
}
|
|
484
|
+
>
|
|
485
|
+
<TimesIcon />
|
|
486
|
+
</button>
|
|
487
|
+
</div>
|
|
488
|
+
</div>
|
|
489
|
+
)}
|
|
490
|
+
</div>
|
|
491
|
+
);
|
|
492
|
+
},
|
|
493
|
+
);
|
|
494
|
+
|
|
495
|
+
const NewDataProductParameterModal = observer(
|
|
496
|
+
(props: { testState: DataProductTestState; isReadOnly: boolean }) => {
|
|
497
|
+
const { testState, isReadOnly } = props;
|
|
498
|
+
const applicationStore = testState.editorStore.applicationStore;
|
|
499
|
+
const currentOption = {
|
|
500
|
+
value: testState.newParameterValueName,
|
|
501
|
+
label: testState.newParameterValueName,
|
|
502
|
+
};
|
|
503
|
+
const options = testState.newParamOptions;
|
|
504
|
+
const closeModal = (): void => testState.setShowNewParameterModal(false);
|
|
505
|
+
const onChange = (val: { label: string; value: string } | null): void => {
|
|
506
|
+
if (val === null) {
|
|
507
|
+
testState.setNewParameterValueName('');
|
|
508
|
+
} else if (val.value !== testState.newParameterValueName) {
|
|
509
|
+
testState.setNewParameterValueName(val.value);
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
return (
|
|
514
|
+
<Dialog
|
|
515
|
+
open={testState.showNewParameterModal}
|
|
516
|
+
onClose={closeModal}
|
|
517
|
+
classes={{ container: 'search-modal__container' }}
|
|
518
|
+
slotProps={{
|
|
519
|
+
paper: {
|
|
520
|
+
classes: { root: 'search-modal__inner-container' },
|
|
521
|
+
},
|
|
522
|
+
}}
|
|
523
|
+
>
|
|
524
|
+
<form
|
|
525
|
+
onSubmit={(event) => {
|
|
526
|
+
event.preventDefault();
|
|
527
|
+
testState.addParameterValue();
|
|
528
|
+
}}
|
|
529
|
+
className="modal modal--dark search-modal"
|
|
530
|
+
>
|
|
531
|
+
<div className="modal__title">New Test Parameter Value</div>
|
|
532
|
+
<CustomSelectorInput
|
|
533
|
+
className="panel__content__form__section__dropdown"
|
|
534
|
+
options={options}
|
|
535
|
+
onChange={onChange}
|
|
536
|
+
value={currentOption}
|
|
537
|
+
escapeClearsValue={true}
|
|
538
|
+
darkMode={
|
|
539
|
+
!applicationStore.layoutService
|
|
540
|
+
.TEMPORARY__isLightColorThemeEnabled
|
|
541
|
+
}
|
|
542
|
+
disabled={isReadOnly}
|
|
543
|
+
/>
|
|
544
|
+
<div className="search-modal__actions">
|
|
545
|
+
<button className="btn btn--dark" disabled={isReadOnly}>
|
|
546
|
+
Add
|
|
547
|
+
</button>
|
|
548
|
+
</div>
|
|
549
|
+
</form>
|
|
550
|
+
</Dialog>
|
|
551
|
+
);
|
|
552
|
+
},
|
|
553
|
+
);
|
|
554
|
+
|
|
555
|
+
const DataProductTestEditorExtension = observer(
|
|
556
|
+
(props: { testState: DataProductTestState; isReadOnly: boolean }) => {
|
|
557
|
+
const { testState, isReadOnly } = props;
|
|
558
|
+
|
|
559
|
+
useEffect(() => {
|
|
560
|
+
testState.syncWithQuery();
|
|
561
|
+
}, [testState]);
|
|
562
|
+
|
|
563
|
+
const hasQueryParameters = Boolean(
|
|
564
|
+
testState.queryVariableExpressions.length,
|
|
565
|
+
);
|
|
566
|
+
if (!hasQueryParameters) {
|
|
567
|
+
return null;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
const accessPoint = testState.suiteState.testableState.ownAccessPoints.find(
|
|
571
|
+
(ap) => ap.id === testState.test.accessPointId,
|
|
572
|
+
);
|
|
573
|
+
const query = accessPoint ? getAccessPointLambda(accessPoint) : undefined;
|
|
574
|
+
const contentTypeParamPairs = getContentTypeWithParamFromQuery(
|
|
575
|
+
query,
|
|
576
|
+
testState.editorStore,
|
|
577
|
+
);
|
|
578
|
+
|
|
579
|
+
const addParameter = (): void => {
|
|
580
|
+
testState.openNewParamModal();
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
const generateParameterValues = (): void => {
|
|
584
|
+
testState.generateTestParameterValues();
|
|
585
|
+
};
|
|
586
|
+
|
|
587
|
+
return (
|
|
588
|
+
<div className="data-product-test-editor__parameters-panel-container">
|
|
589
|
+
<div className="panel data-product-test-editor__parameters-panel">
|
|
590
|
+
<div className="data-product-test-editor__parameters-header">
|
|
591
|
+
<div className="data-product-test-editor__parameters-header__title">
|
|
592
|
+
<div className="data-product-test-editor__parameters-header__title__label">
|
|
593
|
+
Parameters
|
|
594
|
+
</div>
|
|
595
|
+
</div>
|
|
596
|
+
<div className="data-product-test-editor__parameters-header__actions">
|
|
597
|
+
<button
|
|
598
|
+
className="panel__header__action data-product-test-editor__generate-btn"
|
|
599
|
+
onClick={generateParameterValues}
|
|
600
|
+
disabled={!testState.newParamOptions.length}
|
|
601
|
+
title="Generate test parameter values"
|
|
602
|
+
tabIndex={-1}
|
|
603
|
+
>
|
|
604
|
+
<div className="data-product-test-editor__generate-btn__label">
|
|
605
|
+
<RefreshIcon className="data-product-test-editor__generate-btn__label__icon" />
|
|
606
|
+
<div className="data-product-test-editor__generate-btn__label__title">
|
|
607
|
+
Generate
|
|
608
|
+
</div>
|
|
609
|
+
</div>
|
|
610
|
+
</button>
|
|
611
|
+
<button
|
|
612
|
+
className="panel__header__action"
|
|
613
|
+
tabIndex={-1}
|
|
614
|
+
disabled={!testState.newParamOptions.length}
|
|
615
|
+
onClick={addParameter}
|
|
616
|
+
title="Add Parameter Value"
|
|
617
|
+
>
|
|
618
|
+
<PlusIcon />
|
|
619
|
+
</button>
|
|
620
|
+
</div>
|
|
621
|
+
</div>
|
|
622
|
+
|
|
623
|
+
<div className="data-product-test-editor__parameters">
|
|
624
|
+
{testState.parameterValueStates.map((paramState) => (
|
|
625
|
+
<DataProductTestParameterEditor
|
|
626
|
+
key={paramState.uuid}
|
|
627
|
+
isReadOnly={isReadOnly}
|
|
628
|
+
paramState={paramState}
|
|
629
|
+
testState={testState}
|
|
630
|
+
contentTypeParamPair={contentTypeParamPairs.find(
|
|
631
|
+
(pair) => pair.param === paramState.parameterValue.name,
|
|
632
|
+
)}
|
|
633
|
+
/>
|
|
634
|
+
))}
|
|
635
|
+
{testState.parameterValueStates.length === 0 && (
|
|
636
|
+
<BlankPanelPlaceholder
|
|
637
|
+
text="No parameter values"
|
|
638
|
+
tooltipText="Generate or add a parameter value"
|
|
639
|
+
/>
|
|
640
|
+
)}
|
|
641
|
+
</div>
|
|
642
|
+
</div>
|
|
643
|
+
|
|
644
|
+
{testState.showNewParameterModal && (
|
|
645
|
+
<NewDataProductParameterModal
|
|
646
|
+
testState={testState}
|
|
647
|
+
isReadOnly={isReadOnly}
|
|
648
|
+
/>
|
|
649
|
+
)}
|
|
650
|
+
</div>
|
|
651
|
+
);
|
|
652
|
+
},
|
|
653
|
+
);
|
|
654
|
+
|
|
294
655
|
// ─── Suite Tab Context Menu ───────────────────────────────────────────────────
|
|
295
656
|
|
|
296
657
|
const SuiteHeaderTabContextMenu = observer(
|
|
@@ -407,6 +768,14 @@ export const DataProductTestableEditor = observer(
|
|
|
407
768
|
suiteState={selectedSuiteState}
|
|
408
769
|
testableState={testableState}
|
|
409
770
|
isReadOnly={isReadOnly}
|
|
771
|
+
renderTestStateExtension={(testState) =>
|
|
772
|
+
testState instanceof DataProductTestState ? (
|
|
773
|
+
<DataProductTestEditorExtension
|
|
774
|
+
testState={testState}
|
|
775
|
+
isReadOnly={isReadOnly}
|
|
776
|
+
/>
|
|
777
|
+
) : null
|
|
778
|
+
}
|
|
410
779
|
/>
|
|
411
780
|
)}
|
|
412
781
|
{!dp.tests.length && (
|