@finos/legend-application-studio 28.18.136 → 28.18.138
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__/LegendStudioEvent.d.ts +2 -1
- package/lib/__lib__/LegendStudioEvent.d.ts.map +1 -1
- package/lib/__lib__/LegendStudioEvent.js +2 -0
- package/lib/__lib__/LegendStudioEvent.js.map +1 -1
- package/lib/components/LegendStudioWebApplication.d.ts.map +1 -1
- package/lib/components/LegendStudioWebApplication.js +13 -29
- package/lib/components/LegendStudioWebApplication.js.map +1 -1
- package/lib/components/editor/editor-group/dataProduct/DataPoductEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/dataProduct/DataPoductEditor.js +43 -8
- package/lib/components/editor/editor-group/dataProduct/DataPoductEditor.js.map +1 -1
- package/lib/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.js +34 -15
- package/lib/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.js.map +1 -1
- package/lib/components/editor/side-bar/CreateNewElementModal.d.ts.map +1 -1
- package/lib/components/editor/side-bar/CreateNewElementModal.js +6 -5
- package/lib/components/editor/side-bar/CreateNewElementModal.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/editor/NewElementState.js +1 -1
- package/lib/stores/editor/NewElementState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.d.ts +4 -3
- package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.js +41 -10
- package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.js.map +1 -1
- package/package.json +6 -6
- package/src/__lib__/LegendStudioEvent.ts +3 -0
- package/src/components/LegendStudioWebApplication.tsx +31 -38
- package/src/components/editor/editor-group/dataProduct/DataPoductEditor.tsx +143 -20
- package/src/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.tsx +101 -34
- package/src/components/editor/side-bar/CreateNewElementModal.tsx +5 -22
- package/src/stores/editor/NewElementState.ts +1 -1
- package/src/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.ts +72 -12
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@finos/legend-application-studio",
|
3
|
-
"version": "28.18.
|
3
|
+
"version": "28.18.138",
|
4
4
|
"description": "Legend Studio application core",
|
5
5
|
"keywords": [
|
6
6
|
"legend",
|
@@ -47,11 +47,11 @@
|
|
47
47
|
"dependencies": {
|
48
48
|
"@finos/legend-application": "16.0.48",
|
49
49
|
"@finos/legend-art": "7.1.102",
|
50
|
-
"@finos/legend-code-editor": "2.0.
|
51
|
-
"@finos/legend-data-cube": "0.2.
|
52
|
-
"@finos/legend-graph": "32.1.
|
53
|
-
"@finos/legend-lego": "2.0.
|
54
|
-
"@finos/legend-query-builder": "4.16.
|
50
|
+
"@finos/legend-code-editor": "2.0.80",
|
51
|
+
"@finos/legend-data-cube": "0.2.12",
|
52
|
+
"@finos/legend-graph": "32.1.38",
|
53
|
+
"@finos/legend-lego": "2.0.85",
|
54
|
+
"@finos/legend-query-builder": "4.16.46",
|
55
55
|
"@finos/legend-server-depot": "6.0.92",
|
56
56
|
"@finos/legend-server-sdlc": "5.3.58",
|
57
57
|
"@finos/legend-server-showcase": "0.2.54",
|
@@ -77,4 +77,7 @@ export enum LEGEND_STUDIO_APP_EVENT {
|
|
77
77
|
TEXT_MODE_ACTION_KEYBOARD_SHORTCUT_GO_TO_DEFINITION__LAUNCH = 'editor.text-mode.action.keyboard.shortcut.go-to-element.launch',
|
78
78
|
TEXT_MODE_ACTION_KEYBOARD_SHORTCUT_GO_TO_DEFINITION__ERROR = 'editor.text-mode.action.keyboard.shortcut.go-to-element.error',
|
79
79
|
TEXT_MODE_ACTION_KEYBOARD_SHORTCUT_GO_TO_DEFINITION__SUCCESS = 'editor.text-mode.action.keyboard.shortcut.go-to-element.success',
|
80
|
+
|
81
|
+
// Ingestion
|
82
|
+
INGESTION_DEPLOY_SUCCESS_URN = 'editor.ingestion.deployment.success.urn',
|
80
83
|
}
|
@@ -20,7 +20,13 @@ import { Editor } from './editor/Editor.js';
|
|
20
20
|
import { ProjectReviewer } from './project-reviewer/ProjectReviewer.js';
|
21
21
|
import { ProjectViewer } from './project-view/ProjectViewer.js';
|
22
22
|
import { observer } from 'mobx-react-lite';
|
23
|
-
import {
|
23
|
+
import {
|
24
|
+
clsx,
|
25
|
+
CubesLoadingIndicator,
|
26
|
+
CubesLoadingIndicatorIcon,
|
27
|
+
GhostIcon,
|
28
|
+
MarkdownTextViewer,
|
29
|
+
} from '@finos/legend-art';
|
24
30
|
import {
|
25
31
|
LEGEND_STUDIO_ROUTE_PATTERN,
|
26
32
|
LEGEND_STUDIO_SDLC_BYPASSED_ROUTE_PATTERN,
|
@@ -44,11 +50,10 @@ import { PureCompatibilityTestManager } from './pct/PureCompatibilityTest.js';
|
|
44
50
|
import { ShowcaseViewer } from './showcase/ShowcaseViewer.js';
|
45
51
|
import {
|
46
52
|
AuthProvider,
|
47
|
-
|
53
|
+
withAuthenticationRequired,
|
48
54
|
type AuthProviderProps,
|
49
55
|
} from 'react-oidc-context';
|
50
56
|
import type { User } from 'oidc-client-ts';
|
51
|
-
import { assertErrorThrown } from '@finos/legend-shared';
|
52
57
|
|
53
58
|
const NotFoundPage = observer(() => {
|
54
59
|
const applicationStore = useApplicationStore();
|
@@ -293,33 +298,6 @@ export const LegendStudioWebApplicationRouter = observer(() => {
|
|
293
298
|
const LegendStudioWebProvider: React.FC<{
|
294
299
|
baseUrl: string;
|
295
300
|
}> = ({ baseUrl }) => {
|
296
|
-
const applicationStore = useLegendStudioApplicationStore();
|
297
|
-
|
298
|
-
const enableOauthFlow = applicationStore.config.options.enableOauthFlow;
|
299
|
-
const auth = useAuth();
|
300
|
-
|
301
|
-
useEffect(() => {
|
302
|
-
const tryLogin = async () => {
|
303
|
-
if (enableOauthFlow) {
|
304
|
-
try {
|
305
|
-
const user = auth.user;
|
306
|
-
if ((!user || user.expired) && !auth.isLoading) {
|
307
|
-
await auth.signinRedirect({
|
308
|
-
state: window.location.pathname + window.location.search,
|
309
|
-
});
|
310
|
-
}
|
311
|
-
} catch (error) {
|
312
|
-
assertErrorThrown(error);
|
313
|
-
applicationStore.logUnhandledError(error);
|
314
|
-
}
|
315
|
-
}
|
316
|
-
};
|
317
|
-
|
318
|
-
tryLogin().catch((error) => {
|
319
|
-
assertErrorThrown(error);
|
320
|
-
});
|
321
|
-
}, [enableOauthFlow, applicationStore, auth]);
|
322
|
-
|
323
301
|
return (
|
324
302
|
<BrowserEnvironmentProvider baseUrl={baseUrl}>
|
325
303
|
<LegendStudioFrameworkProvider>
|
@@ -329,6 +307,20 @@ const LegendStudioWebProvider: React.FC<{
|
|
329
307
|
);
|
330
308
|
};
|
331
309
|
|
310
|
+
const AuthenticatedLegendStudioWebProvider = withAuthenticationRequired(
|
311
|
+
LegendStudioWebProvider,
|
312
|
+
{
|
313
|
+
OnRedirecting: () => (
|
314
|
+
<CubesLoadingIndicator isLoading={true}>
|
315
|
+
<CubesLoadingIndicatorIcon />
|
316
|
+
</CubesLoadingIndicator>
|
317
|
+
),
|
318
|
+
signinRedirectArgs: {
|
319
|
+
state: `${window.location.pathname}${window.location.search}`,
|
320
|
+
},
|
321
|
+
},
|
322
|
+
);
|
323
|
+
|
332
324
|
export const LegendStudioWebApplication = observer(
|
333
325
|
(props: { baseUrl: string }) => {
|
334
326
|
const { baseUrl } = props;
|
@@ -337,6 +329,7 @@ export const LegendStudioWebApplication = observer(
|
|
337
329
|
const oidcConfig =
|
338
330
|
applicationStore.config.options.ingestDeploymentConfig?.deployment
|
339
331
|
.oidcConfig;
|
332
|
+
const enableOauthFlow = applicationStore.config.options.enableOauthFlow;
|
340
333
|
if (oidcConfig) {
|
341
334
|
const onSigninCallback = (_user: User | undefined) => {
|
342
335
|
window.location.href = (_user?.state as string | undefined) ?? '/';
|
@@ -346,10 +339,16 @@ export const LegendStudioWebApplication = observer(
|
|
346
339
|
...oidcConfig.authProviderProps,
|
347
340
|
redirect_uri: `${window.location.origin}${oidcConfig.redirectPath}`,
|
348
341
|
silent_redirect_uri: `${window.location.origin}${oidcConfig.silentRedirectPath}`,
|
349
|
-
automaticSilentRenew: true,
|
350
342
|
onSigninCallback,
|
351
343
|
};
|
352
344
|
|
345
|
+
if (enableOauthFlow) {
|
346
|
+
return (
|
347
|
+
<AuthProvider {...mergedOIDCConfig}>
|
348
|
+
<AuthenticatedLegendStudioWebProvider baseUrl={baseUrl} />
|
349
|
+
</AuthProvider>
|
350
|
+
);
|
351
|
+
}
|
353
352
|
return (
|
354
353
|
<AuthProvider {...mergedOIDCConfig}>
|
355
354
|
<LegendStudioWebProvider baseUrl={baseUrl} />
|
@@ -357,12 +356,6 @@ export const LegendStudioWebApplication = observer(
|
|
357
356
|
);
|
358
357
|
}
|
359
358
|
|
360
|
-
return
|
361
|
-
<BrowserEnvironmentProvider baseUrl={baseUrl}>
|
362
|
-
<LegendStudioFrameworkProvider>
|
363
|
-
<LegendStudioWebApplicationRouter />
|
364
|
-
</LegendStudioFrameworkProvider>
|
365
|
-
</BrowserEnvironmentProvider>
|
366
|
-
);
|
359
|
+
return <LegendStudioWebProvider baseUrl={baseUrl} />;
|
367
360
|
},
|
368
361
|
);
|
@@ -42,14 +42,17 @@ import {
|
|
42
42
|
ModalBody,
|
43
43
|
ModalFooter,
|
44
44
|
ModalFooterButton,
|
45
|
+
PencilEditIcon,
|
46
|
+
PanelFormTextField,
|
45
47
|
} from '@finos/legend-art';
|
46
|
-
import { useRef, useState, useEffect } from 'react';
|
48
|
+
import React, { useRef, useState, useEffect } from 'react';
|
47
49
|
import { filterByType } from '@finos/legend-shared';
|
48
50
|
import { InlineLambdaEditor } from '@finos/legend-query-builder';
|
49
|
-
import { flowResult } from 'mobx';
|
51
|
+
import { action, flowResult } from 'mobx';
|
50
52
|
import { useAuth } from 'react-oidc-context';
|
51
53
|
import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor';
|
52
54
|
import { CodeEditor } from '@finos/legend-lego/code-editor';
|
55
|
+
import type { LakehouseAccessPoint } from '@finos/legend-graph';
|
53
56
|
|
54
57
|
const NewAccessPointAccessPOint = observer(
|
55
58
|
(props: { dataProductEditorState: DataProductEditorState }) => {
|
@@ -163,6 +166,32 @@ const NewAccessPointAccessPOint = observer(
|
|
163
166
|
},
|
164
167
|
);
|
165
168
|
|
169
|
+
interface DescriptionTextAreaProps {
|
170
|
+
accessPoint: LakehouseAccessPoint;
|
171
|
+
handleMouseOver: (event: React.MouseEvent<HTMLDivElement>) => void;
|
172
|
+
handleMouseOut: (event: React.MouseEvent<HTMLDivElement>) => void;
|
173
|
+
}
|
174
|
+
|
175
|
+
const DescriptionTextArea: React.FC<DescriptionTextAreaProps> = ({
|
176
|
+
accessPoint,
|
177
|
+
handleMouseOver,
|
178
|
+
handleMouseOut,
|
179
|
+
}) => {
|
180
|
+
return (
|
181
|
+
<div onMouseOver={handleMouseOver} onMouseOut={handleMouseOut}>
|
182
|
+
{accessPoint.description}
|
183
|
+
</div>
|
184
|
+
);
|
185
|
+
};
|
186
|
+
|
187
|
+
const hoverIcon = () => {
|
188
|
+
return (
|
189
|
+
<div>
|
190
|
+
<PencilEditIcon />
|
191
|
+
</div>
|
192
|
+
);
|
193
|
+
};
|
194
|
+
|
166
195
|
export const LakehouseDataProductAcccessPointEditor = observer(
|
167
196
|
(props: {
|
168
197
|
accessPointState: LakehouseAccessPointState;
|
@@ -175,6 +204,28 @@ export const LakehouseDataProductAcccessPointEditor = observer(
|
|
175
204
|
const propertyHasParserError = productEditorState.accessPointStates
|
176
205
|
.filter(filterByType(LakehouseAccessPointState))
|
177
206
|
.find((pm) => pm.lambdaState.parserError);
|
207
|
+
const [editingDescription, setEditingDescription] = useState(false);
|
208
|
+
const [isHovering, setIsHovering] = useState(false);
|
209
|
+
|
210
|
+
const handleEdit = () => setEditingDescription(true);
|
211
|
+
const handleBlur = () => {
|
212
|
+
setEditingDescription(false);
|
213
|
+
setIsHovering(false);
|
214
|
+
};
|
215
|
+
|
216
|
+
const handleMouseOver: React.MouseEventHandler<HTMLDivElement> = () => {
|
217
|
+
setIsHovering(true);
|
218
|
+
};
|
219
|
+
const handleMouseOut: React.MouseEventHandler<HTMLDivElement> = () => {
|
220
|
+
setIsHovering(false);
|
221
|
+
};
|
222
|
+
|
223
|
+
const updateAccessPointDescription: React.ChangeEventHandler<
|
224
|
+
HTMLTextAreaElement
|
225
|
+
> = (event) => {
|
226
|
+
action((accessPoint.description = event.target.value));
|
227
|
+
};
|
228
|
+
|
178
229
|
return (
|
179
230
|
<div
|
180
231
|
className={clsx('access-point-editor', {
|
@@ -187,6 +238,34 @@ export const LakehouseDataProductAcccessPointEditor = observer(
|
|
187
238
|
{accessPoint.id}
|
188
239
|
</div>
|
189
240
|
</div>
|
241
|
+
{editingDescription ? (
|
242
|
+
<textarea
|
243
|
+
className="panel__content__form__section__input"
|
244
|
+
spellCheck={false}
|
245
|
+
value={accessPoint.description ?? ''}
|
246
|
+
onChange={updateAccessPointDescription}
|
247
|
+
placeholder="Access Point description"
|
248
|
+
onBlur={handleBlur}
|
249
|
+
style={{
|
250
|
+
overflow: 'hidden',
|
251
|
+
resize: 'none',
|
252
|
+
padding: '0.25rem',
|
253
|
+
}}
|
254
|
+
/>
|
255
|
+
) : (
|
256
|
+
<div
|
257
|
+
onClick={handleEdit}
|
258
|
+
title="Click to edit description"
|
259
|
+
className="access-point-editor__description-container"
|
260
|
+
>
|
261
|
+
<DescriptionTextArea
|
262
|
+
accessPoint={accessPoint}
|
263
|
+
handleMouseOver={handleMouseOver}
|
264
|
+
handleMouseOut={handleMouseOut}
|
265
|
+
/>
|
266
|
+
{isHovering && hoverIcon()}
|
267
|
+
</div>
|
268
|
+
)}
|
190
269
|
<div className="access-point-editor__info">
|
191
270
|
<div
|
192
271
|
className={clsx('access-point-editor__type')}
|
@@ -287,7 +366,7 @@ const DataProductDeploymentResponseModal = observer(
|
|
287
366
|
className="editor-modal"
|
288
367
|
>
|
289
368
|
<ModalHeader>
|
290
|
-
<ModalTitle title="
|
369
|
+
<ModalTitle title="Data Product Deployment Response" />
|
291
370
|
</ModalHeader>
|
292
371
|
<ModalBody>
|
293
372
|
<PanelContent>
|
@@ -352,6 +431,19 @@ export const DataProductEditor = observer(() => {
|
|
352
431
|
}
|
353
432
|
};
|
354
433
|
|
434
|
+
const updateDataProductTitle = action((val: string | undefined): void => {
|
435
|
+
if (val === undefined) {
|
436
|
+
return;
|
437
|
+
}
|
438
|
+
product.name = val;
|
439
|
+
});
|
440
|
+
|
441
|
+
const updateDataProductDescription = action(
|
442
|
+
(val: string | undefined): void => {
|
443
|
+
product.description = val;
|
444
|
+
},
|
445
|
+
);
|
446
|
+
|
355
447
|
useEffect(() => {
|
356
448
|
flowResult(dataProductEditorState.convertAccessPointsFuncObjects()).catch(
|
357
449
|
dataProductEditorState.editorStore.applicationStore.alertUnhandledError,
|
@@ -381,7 +473,6 @@ export const DataProductEditor = observer(() => {
|
|
381
473
|
</div>
|
382
474
|
)}
|
383
475
|
<div className="panel__header__title__label">data product</div>
|
384
|
-
<div className="panel__header__title__content">{product.name}</div>
|
385
476
|
</div>
|
386
477
|
<PanelHeaderActions>
|
387
478
|
<div className="btn__dropdown-combo btn__dropdown-combo--primary">
|
@@ -398,10 +489,26 @@ export const DataProductEditor = observer(() => {
|
|
398
489
|
</div>
|
399
490
|
</PanelHeaderActions>
|
400
491
|
</div>
|
492
|
+
<div className="panel" style={{ padding: '1rem' }}>
|
493
|
+
<PanelFormTextField
|
494
|
+
name="Title"
|
495
|
+
value={product.name}
|
496
|
+
prompt="Provide a title for this Lakehouse Data Product."
|
497
|
+
update={updateDataProductTitle}
|
498
|
+
placeholder="Enter title"
|
499
|
+
/>
|
500
|
+
<PanelFormTextField
|
501
|
+
name="Description"
|
502
|
+
value={product.description}
|
503
|
+
prompt="Provide a description for this Lakehouse Data Product."
|
504
|
+
update={updateDataProductDescription}
|
505
|
+
placeholder="Enter description"
|
506
|
+
/>
|
507
|
+
</div>
|
401
508
|
<div className="panel">
|
402
509
|
<PanelHeader>
|
403
510
|
<div className="panel__header__title">
|
404
|
-
<div className="
|
511
|
+
<div className="panel__header__title__label">access points</div>
|
405
512
|
</div>
|
406
513
|
<PanelHeaderActions>
|
407
514
|
<PanelHeaderActionItem
|
@@ -414,22 +521,38 @@ export const DataProductEditor = observer(() => {
|
|
414
521
|
</PanelHeaderActionItem>
|
415
522
|
</PanelHeaderActions>
|
416
523
|
</PanelHeader>
|
417
|
-
<
|
418
|
-
|
419
|
-
.
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
524
|
+
<div style={{ overflow: 'auto' }}>
|
525
|
+
<PanelContent>
|
526
|
+
{dataProductEditorState.accessPointGroupStates.map(
|
527
|
+
(groupState) => (
|
528
|
+
<div
|
529
|
+
key={groupState.value.id}
|
530
|
+
className="access-point-editor__group-container"
|
531
|
+
>
|
532
|
+
<div className="access-point-editor__group-container__title">
|
533
|
+
<div className="panel__header__title__content">
|
534
|
+
{groupState.value.id}
|
535
|
+
</div>
|
536
|
+
</div>
|
537
|
+
{groupState.accessPointStates
|
538
|
+
.filter(filterByType(LakehouseAccessPointState))
|
539
|
+
.map((apState) => (
|
540
|
+
<LakehouseDataProductAcccessPointEditor
|
541
|
+
key={apState.accessPoint.id}
|
542
|
+
isReadOnly={isReadOnly}
|
543
|
+
accessPointState={apState}
|
544
|
+
/>
|
545
|
+
))}
|
546
|
+
</div>
|
547
|
+
),
|
548
|
+
)}
|
549
|
+
{!accessPointStates.length && (
|
550
|
+
<DataProductEditorSplashScreen
|
551
|
+
dataProductEditorState={dataProductEditorState}
|
425
552
|
/>
|
426
|
-
)
|
427
|
-
|
428
|
-
|
429
|
-
dataProductEditorState={dataProductEditorState}
|
430
|
-
/>
|
431
|
-
)}
|
432
|
-
</PanelContent>
|
553
|
+
)}
|
554
|
+
</PanelContent>
|
555
|
+
</div>
|
433
556
|
{dataProductEditorState.accessPointModal && (
|
434
557
|
<NewAccessPointAccessPOint
|
435
558
|
dataProductEditorState={dataProductEditorState}
|
@@ -17,6 +17,8 @@
|
|
17
17
|
import { observer } from 'mobx-react-lite';
|
18
18
|
import { useEditorStore } from '../../EditorStoreProvider.js';
|
19
19
|
import {
|
20
|
+
CheckCircleIcon,
|
21
|
+
CopyIcon,
|
20
22
|
Dialog,
|
21
23
|
Modal,
|
22
24
|
ModalBody,
|
@@ -34,50 +36,91 @@ import {
|
|
34
36
|
IngestDefinitionEditorState,
|
35
37
|
} from '../../../../stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.js';
|
36
38
|
import { CodeEditor } from '@finos/legend-lego/code-editor';
|
37
|
-
import { useEffect } from 'react';
|
39
|
+
import React, { useEffect } from 'react';
|
38
40
|
import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor';
|
39
41
|
import { flowResult } from 'mobx';
|
40
42
|
import { useAuth } from 'react-oidc-context';
|
43
|
+
import {
|
44
|
+
type IngestDefinitionDeploymentResponse,
|
45
|
+
IngestDefinitionValidationResponse,
|
46
|
+
} from '../../../../stores/ingestion/IngestionDeploymentResponse.js';
|
41
47
|
|
42
|
-
const
|
43
|
-
(props: {
|
44
|
-
|
48
|
+
const IngestValidationError = observer(
|
49
|
+
(props: {
|
50
|
+
state: IngestDefinitionEditorState;
|
51
|
+
validateResponse: IngestDefinitionValidationResponse;
|
52
|
+
}) => {
|
53
|
+
const { state, validateResponse } = props;
|
45
54
|
const applicationStore = state.editorStore.applicationStore;
|
55
|
+
const closeModal = (): void =>
|
56
|
+
state.setValidateAndDeployResponse(undefined);
|
46
57
|
return (
|
47
58
|
<Dialog
|
48
|
-
open={
|
49
|
-
classes={{
|
59
|
+
open={true}
|
60
|
+
classes={{
|
61
|
+
root: 'editor-modal__root-container',
|
62
|
+
container: 'editor-modal__container',
|
63
|
+
paper: 'editor-modal__content',
|
64
|
+
}}
|
65
|
+
onClose={closeModal}
|
50
66
|
>
|
51
67
|
<Modal
|
52
68
|
darkMode={
|
53
69
|
!applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled
|
54
70
|
}
|
55
|
-
className="
|
71
|
+
className="editor-modal"
|
56
72
|
>
|
57
73
|
<ModalHeader>
|
58
|
-
<ModalTitle title=
|
74
|
+
<ModalTitle title={'Validation Error'} />
|
59
75
|
</ModalHeader>
|
60
76
|
<ModalBody>
|
61
|
-
<
|
77
|
+
<PanelContent>
|
78
|
+
<CodeEditor
|
79
|
+
inputValue={JSON.stringify(validateResponse, null, 2)}
|
80
|
+
isReadOnly={true}
|
81
|
+
language={CODE_EDITOR_LANGUAGE.JSON}
|
82
|
+
/>
|
83
|
+
</PanelContent>
|
62
84
|
</ModalBody>
|
85
|
+
<ModalFooter>
|
86
|
+
<ModalFooterButton
|
87
|
+
onClick={closeModal}
|
88
|
+
text="Close"
|
89
|
+
type="secondary"
|
90
|
+
/>
|
91
|
+
</ModalFooter>
|
63
92
|
</Modal>
|
64
93
|
</Dialog>
|
65
94
|
);
|
66
95
|
},
|
67
96
|
);
|
68
97
|
|
69
|
-
|
70
|
-
|
71
|
-
|
98
|
+
// TODO: show full report i.e write envs etc
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
100
|
+
const IngestDeploymentResponseModal = observer(
|
101
|
+
(props: {
|
102
|
+
state: IngestDefinitionEditorState;
|
103
|
+
deploymentResponse: IngestDefinitionDeploymentResponse;
|
104
|
+
}) => {
|
105
|
+
const { state, deploymentResponse } = props;
|
72
106
|
const applicationStore = state.editorStore.applicationStore;
|
73
|
-
const
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
107
|
+
const closeModal = (): void =>
|
108
|
+
state.setValidateAndDeployResponse(undefined);
|
109
|
+
const copyURN = (text: string): void => {
|
110
|
+
state.editorStore.applicationStore.clipboardService
|
111
|
+
.copyTextToClipboard(text)
|
112
|
+
.then(() =>
|
113
|
+
state.editorStore.applicationStore.notificationService.notifySuccess(
|
114
|
+
'Ingest URN copied to clipboard',
|
115
|
+
undefined,
|
116
|
+
2500,
|
117
|
+
),
|
118
|
+
)
|
119
|
+
.catch(state.editorStore.applicationStore.alertUnhandledError);
|
120
|
+
};
|
78
121
|
return (
|
79
122
|
<Dialog
|
80
|
-
open={
|
123
|
+
open={true}
|
81
124
|
classes={{
|
82
125
|
root: 'editor-modal__root-container',
|
83
126
|
container: 'editor-modal__container',
|
@@ -92,19 +135,34 @@ const IngestValidationError = observer(
|
|
92
135
|
className="editor-modal"
|
93
136
|
>
|
94
137
|
<ModalHeader>
|
95
|
-
<ModalTitle
|
138
|
+
<ModalTitle
|
139
|
+
icon={<CheckCircleIcon />}
|
140
|
+
title="Deployment URN"
|
141
|
+
></ModalTitle>
|
96
142
|
</ModalHeader>
|
97
143
|
<ModalBody>
|
98
144
|
<PanelContent>
|
99
|
-
<
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
145
|
+
<div>
|
146
|
+
<div>Ingestion URN</div>
|
147
|
+
<div>{deploymentResponse.ingestDefinitionUrn}</div>
|
148
|
+
|
149
|
+
<div className="data-space__viewer__quickstart__tds__query-text__actions">
|
150
|
+
<button
|
151
|
+
className="data-space__viewer__quickstart__tds__query-text__action"
|
152
|
+
tabIndex={-1}
|
153
|
+
title="Copy"
|
154
|
+
onClick={() => {
|
155
|
+
copyURN(deploymentResponse.ingestDefinitionUrn);
|
156
|
+
}}
|
157
|
+
>
|
158
|
+
<CopyIcon />
|
159
|
+
</button>
|
160
|
+
<button
|
161
|
+
className="data-space__viewer__quickstart__tds__query-text__action"
|
162
|
+
tabIndex={-1}
|
163
|
+
></button>
|
164
|
+
</div>
|
165
|
+
</div>
|
108
166
|
</PanelContent>
|
109
167
|
</ModalBody>
|
110
168
|
<ModalFooter>
|
@@ -153,6 +211,20 @@ export const IngestDefinitionEditor = observer(() => {
|
|
153
211
|
}
|
154
212
|
};
|
155
213
|
|
214
|
+
const renderDeploymentResponse = (): React.ReactNode => {
|
215
|
+
const response = ingestDefinitionEditorState.deploymentResponse;
|
216
|
+
if (response instanceof IngestDefinitionValidationResponse) {
|
217
|
+
return (
|
218
|
+
<IngestValidationError
|
219
|
+
state={ingestDefinitionEditorState}
|
220
|
+
validateResponse={response}
|
221
|
+
/>
|
222
|
+
);
|
223
|
+
}
|
224
|
+
|
225
|
+
return null;
|
226
|
+
};
|
227
|
+
|
156
228
|
const isValid = ingestDefinitionEditorState.validForDeployment;
|
157
229
|
useEffect(() => {
|
158
230
|
ingestDefinitionEditorState.generateElementGrammar();
|
@@ -202,12 +274,7 @@ export const IngestDefinitionEditor = observer(() => {
|
|
202
274
|
language={CODE_EDITOR_LANGUAGE.PURE}
|
203
275
|
/>
|
204
276
|
</PanelContent>
|
205
|
-
{
|
206
|
-
<IngestDepoymentModal state={ingestDefinitionEditorState} />
|
207
|
-
)}
|
208
|
-
{ingestDefinitionEditorState.validationError && (
|
209
|
-
<IngestValidationError state={ingestDefinitionEditorState} />
|
210
|
-
)}
|
277
|
+
{renderDeploymentResponse()}
|
211
278
|
</PanelContent>
|
212
279
|
</div>
|
213
280
|
);
|
@@ -27,7 +27,6 @@ import {
|
|
27
27
|
NewServiceDriver,
|
28
28
|
CONNECTION_TYPE,
|
29
29
|
type RuntimeOption,
|
30
|
-
NewLakehouseDataProductDriver,
|
31
30
|
} from '../../../stores/editor/NewElementState.js';
|
32
31
|
import { Dialog, compareLabelFn, CustomSelectorInput } from '@finos/legend-art';
|
33
32
|
import type { EditorStore } from '../../../stores/editor/EditorStore.js';
|
@@ -441,27 +440,11 @@ const NewServiceDriverEditor = observer(() => {
|
|
441
440
|
});
|
442
441
|
|
443
442
|
const NewLakehouseDataProductEditor = observer(() => {
|
444
|
-
const editorStore = useEditorStore();
|
445
|
-
const newProductDriver = editorStore.newElementState.getNewElementDriver(
|
446
|
-
|
447
|
-
);
|
448
|
-
|
449
|
-
event,
|
450
|
-
) => newProductDriver.setTitle(event.target.value);
|
451
|
-
return (
|
452
|
-
<>
|
453
|
-
<div className="panel__content__form__section__header__label">Title</div>
|
454
|
-
<div className="explorer__new-element-modal__driver">
|
455
|
-
<input
|
456
|
-
className="input--dark explorer__new-element-modal__name-input"
|
457
|
-
spellCheck={false}
|
458
|
-
value={newProductDriver.title}
|
459
|
-
onChange={handleTitleChangee}
|
460
|
-
placeholder={`Data Product Title`}
|
461
|
-
/>
|
462
|
-
</div>
|
463
|
-
</>
|
464
|
-
);
|
443
|
+
// const editorStore = useEditorStore();
|
444
|
+
// const newProductDriver = editorStore.newElementState.getNewElementDriver(
|
445
|
+
// NewLakehouseDataProductDriver,
|
446
|
+
// );
|
447
|
+
return null;
|
465
448
|
});
|
466
449
|
|
467
450
|
const NewFileGenerationDriverEditor = observer(() => {
|