@finos/legend-extension-dsl-data-space-studio 0.1.340 → 0.1.342
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/DSL_DataProduct_ElementDriver.d.ts.map +1 -1
- package/lib/components/DSL_DataProduct_ElementDriver.js +1 -10
- package/lib/components/DSL_DataProduct_ElementDriver.js.map +1 -1
- package/lib/components/DataSpaceEditor.js +9 -4
- package/lib/components/DataSpaceEditor.js.map +1 -1
- package/lib/components/DataSpaceExecutableQueryAction.d.ts +20 -0
- package/lib/components/DataSpaceExecutableQueryAction.d.ts.map +1 -0
- package/lib/components/DataSpaceExecutableQueryAction.js +85 -0
- package/lib/components/DataSpaceExecutableQueryAction.js.map +1 -0
- package/lib/components/DataSpaceExecutionContextEditor.d.ts +1 -12
- package/lib/components/DataSpaceExecutionContextEditor.d.ts.map +1 -1
- package/lib/components/DataSpaceExecutionContextEditor.js +206 -134
- package/lib/components/DataSpaceExecutionContextEditor.js.map +1 -1
- package/lib/components/DataSpaceGeneralEditor/DataSpaceExecutablesSection.d.ts.map +1 -1
- package/lib/components/DataSpaceGeneralEditor/DataSpaceExecutablesSection.js +130 -26
- package/lib/components/DataSpaceGeneralEditor/DataSpaceExecutablesSection.js.map +1 -1
- package/lib/components/DataSpaceGeneralEditor/DataSpaceGeneralEditor.d.ts.map +1 -1
- package/lib/components/DataSpaceGeneralEditor/DataSpaceGeneralEditor.js +16 -75
- package/lib/components/DataSpaceGeneralEditor/DataSpaceGeneralEditor.js.map +1 -1
- package/lib/components/DataSpaceGeneralEditor/{DataSpaceDefaultExecutionContextSection.d.ts → DataSpaceHomeTab.d.ts} +3 -3
- package/lib/components/DataSpaceGeneralEditor/DataSpaceHomeTab.d.ts.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceHomeTab.js +100 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceHomeTab.js.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceSidebar.d.ts +23 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceSidebar.d.ts.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceSidebar.js +31 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceSidebar.js.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceValidation.d.ts +28 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceValidation.d.ts.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceValidation.js +45 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceValidation.js.map +1 -0
- package/lib/components/DataSpaceQueryAction.d.ts.map +1 -1
- package/lib/components/DataSpaceQueryAction.js +11 -8
- package/lib/components/DataSpaceQueryAction.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/DataSpaceEditorState.d.ts +9 -0
- package/lib/stores/DataSpaceEditorState.d.ts.map +1 -1
- package/lib/stores/DataSpaceEditorState.js +15 -0
- package/lib/stores/DataSpaceEditorState.js.map +1 -1
- package/lib/stores/DataSpaceExecutableTemplateState.d.ts +48 -0
- package/lib/stores/DataSpaceExecutableTemplateState.d.ts.map +1 -0
- package/lib/stores/DataSpaceExecutableTemplateState.js +105 -0
- package/lib/stores/DataSpaceExecutableTemplateState.js.map +1 -0
- package/lib/stores/DataSpaceExecutionContextState.d.ts +4 -9
- package/lib/stores/DataSpaceExecutionContextState.d.ts.map +1 -1
- package/lib/stores/DataSpaceExecutionContextState.js +13 -39
- package/lib/stores/DataSpaceExecutionContextState.js.map +1 -1
- package/lib/stores/studio/DSL_DataSpace_GraphModifierHelper.d.ts +12 -6
- package/lib/stores/studio/DSL_DataSpace_GraphModifierHelper.d.ts.map +1 -1
- package/lib/stores/studio/DSL_DataSpace_GraphModifierHelper.js +45 -3
- package/lib/stores/studio/DSL_DataSpace_GraphModifierHelper.js.map +1 -1
- package/package.json +9 -9
- package/src/components/DSL_DataProduct_ElementDriver.tsx +0 -14
- package/src/components/DataSpaceEditor.tsx +10 -10
- package/src/components/DataSpaceExecutableQueryAction.tsx +159 -0
- package/src/components/DataSpaceExecutionContextEditor.tsx +699 -558
- package/src/components/DataSpaceGeneralEditor/DataSpaceExecutablesSection.tsx +517 -60
- package/src/components/DataSpaceGeneralEditor/DataSpaceGeneralEditor.tsx +22 -198
- package/src/components/DataSpaceGeneralEditor/DataSpaceHomeTab.tsx +235 -0
- package/src/components/DataSpaceGeneralEditor/DataSpaceSidebar.tsx +60 -0
- package/src/components/DataSpaceGeneralEditor/DataSpaceValidation.tsx +83 -0
- package/src/components/DataSpaceQueryAction.tsx +19 -12
- package/src/stores/DataSpaceEditorState.ts +18 -0
- package/src/stores/DataSpaceExecutableTemplateState.ts +152 -0
- package/src/stores/DataSpaceExecutionContextState.ts +17 -70
- package/src/stores/studio/DSL_DataSpace_GraphModifierHelper.ts +79 -6
- package/tsconfig.json +6 -2
- package/lib/components/DataSpaceGeneralEditor/DataSpaceDefaultExecutionContextSection.d.ts.map +0 -1
- package/lib/components/DataSpaceGeneralEditor/DataSpaceDefaultExecutionContextSection.js +0 -138
- package/lib/components/DataSpaceGeneralEditor/DataSpaceDefaultExecutionContextSection.js.map +0 -1
- package/src/components/DataSpaceGeneralEditor/DataSpaceDefaultExecutionContextSection.tsx +0 -393
|
@@ -14,218 +14,42 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
LEGEND_STUDIO_DOCUMENTATION_KEY,
|
|
20
|
-
LegendStudioTelemetryHelper,
|
|
21
|
-
type DSL_DataSpace_LegendStudioApplicationPlugin_Extension,
|
|
22
|
-
} from '@finos/legend-application-studio';
|
|
23
|
-
import {
|
|
24
|
-
clsx,
|
|
25
|
-
PanelContentLists,
|
|
26
|
-
PanelForm,
|
|
27
|
-
PanelFormTextField,
|
|
28
|
-
PanelLoadingIndicator,
|
|
29
|
-
SparkleIcon,
|
|
30
|
-
} from '@finos/legend-art';
|
|
17
|
+
import { useEditorStore } from '@finos/legend-application-studio';
|
|
18
|
+
import { PanelContentLists } from '@finos/legend-art';
|
|
31
19
|
import { observer } from 'mobx-react-lite';
|
|
32
|
-
import { useState } from 'react';
|
|
33
20
|
import {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
} from '
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
dataSpace_setDescription,
|
|
41
|
-
dataSpace_setTitle,
|
|
42
|
-
} from '../../stores/studio/DSL_DataSpace_GraphModifierHelper.js';
|
|
43
|
-
import { DataSpaceDefaultExecutionContextSection } from './DataSpaceDefaultExecutionContextSection.js';
|
|
44
|
-
import { DataSpaceDiagramsSection } from './DataSpaceDiagramsSection.js';
|
|
45
|
-
import { DataSpaceElementsSection } from './DataSpaceElementsSection.js';
|
|
21
|
+
DATA_SPACE_TAB,
|
|
22
|
+
DataSpaceEditorState,
|
|
23
|
+
} from '../../stores/DataSpaceEditorState.js';
|
|
24
|
+
import { DataSpaceSidebar } from './DataSpaceSidebar.js';
|
|
25
|
+
import { DataSpaceHomeTab } from './DataSpaceHomeTab.js';
|
|
26
|
+
import { DataSpaceExecutionContextEditor } from '../DataSpaceExecutionContextEditor.js';
|
|
46
27
|
import { DataspaceExecutablesSection } from './DataSpaceExecutablesSection.js';
|
|
47
|
-
import { DataSpaceSupportInfoSection } from './DataSpaceSupportInfoSection.js';
|
|
48
28
|
|
|
49
29
|
export const DataSpaceGeneralEditor = observer(() => {
|
|
50
30
|
const editorStore = useEditorStore();
|
|
51
|
-
|
|
52
31
|
const dataSpaceState =
|
|
53
32
|
editorStore.tabManagerState.getCurrentEditorState(DataSpaceEditorState);
|
|
54
|
-
const dataSpace = dataSpaceState.dataSpace;
|
|
55
|
-
const isReadOnly = dataSpaceState.isReadOnly;
|
|
56
33
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// AI documentation suggestion
|
|
67
|
-
const legendAIUrl = editorStore.applicationStore.config.legendAIUrl;
|
|
68
|
-
const aiDocSuggester = legendAIUrl
|
|
69
|
-
? editorStore.pluginManager
|
|
70
|
-
.getApplicationPlugins()
|
|
71
|
-
.map((p) =>
|
|
72
|
-
(
|
|
73
|
-
p as DSL_DataSpace_LegendStudioApplicationPlugin_Extension
|
|
74
|
-
).getExtraDataSpaceDocumentationAISuggester?.bind(p),
|
|
75
|
-
)
|
|
76
|
-
.find(Boolean)
|
|
77
|
-
: undefined;
|
|
78
|
-
const [isSuggestingWithAI, setIsSuggestingWithAI] = useState(false);
|
|
79
|
-
const [aiDocSuggestion, setAIDocSuggestion] = useState<string | undefined>(
|
|
80
|
-
undefined,
|
|
81
|
-
);
|
|
82
|
-
const suggestDocumentationWithAI = async (): Promise<void> => {
|
|
83
|
-
if (!aiDocSuggester || !legendAIUrl) {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
LegendStudioTelemetryHelper.logEvent_DataSpaceLegendAISuggestLaunched(
|
|
87
|
-
editorStore.applicationStore.telemetryService,
|
|
88
|
-
dataSpace.path,
|
|
89
|
-
);
|
|
90
|
-
setIsSuggestingWithAI(true);
|
|
91
|
-
setAIDocSuggestion(undefined);
|
|
92
|
-
try {
|
|
93
|
-
const definitions =
|
|
94
|
-
await editorStore.graphManagerState.graphManager.graphToPureCode(
|
|
95
|
-
editorStore.graphManagerState.graph,
|
|
96
|
-
);
|
|
97
|
-
const suggestion = await aiDocSuggester(
|
|
98
|
-
{ definitions, data_space_name: dataSpace.path },
|
|
99
|
-
legendAIUrl,
|
|
100
|
-
);
|
|
101
|
-
setAIDocSuggestion(suggestion.description);
|
|
102
|
-
} catch (error) {
|
|
103
|
-
assertErrorThrown(error);
|
|
104
|
-
LegendStudioTelemetryHelper.logEvent_DataSpaceLegendAISuggestFailure(
|
|
105
|
-
editorStore.applicationStore.telemetryService,
|
|
106
|
-
dataSpace.path,
|
|
107
|
-
error.message,
|
|
108
|
-
);
|
|
109
|
-
if (
|
|
110
|
-
error instanceof NetworkClientError &&
|
|
111
|
-
(error.response.status === HttpStatus.UNAUTHORIZED ||
|
|
112
|
-
error.response.status === HttpStatus.FORBIDDEN)
|
|
113
|
-
) {
|
|
114
|
-
const docEntry =
|
|
115
|
-
editorStore.applicationStore.documentationService.getDocEntry(
|
|
116
|
-
LEGEND_STUDIO_DOCUMENTATION_KEY.LEGENDAI_HOW_TO_GET_ENTITLEMENTS,
|
|
117
|
-
);
|
|
118
|
-
if (docEntry?.url) {
|
|
119
|
-
error.message = `${error.message}. Please check how to get entitlements: ${docEntry.url}`;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
throw error;
|
|
123
|
-
} finally {
|
|
124
|
-
setIsSuggestingWithAI(false);
|
|
34
|
+
const renderTab = (): React.ReactNode => {
|
|
35
|
+
switch (dataSpaceState.selectedTab) {
|
|
36
|
+
case DATA_SPACE_TAB.EXECUTION_CONTEXTS:
|
|
37
|
+
return <DataSpaceExecutionContextEditor />;
|
|
38
|
+
case DATA_SPACE_TAB.EXECUTABLES:
|
|
39
|
+
return <DataspaceExecutablesSection />;
|
|
40
|
+
case DATA_SPACE_TAB.HOME:
|
|
41
|
+
default:
|
|
42
|
+
return <DataSpaceHomeTab />;
|
|
125
43
|
}
|
|
126
44
|
};
|
|
127
|
-
const applyAIDocSuggestion = (): void => {
|
|
128
|
-
if (!aiDocSuggestion) {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
LegendStudioTelemetryHelper.logEvent_DataSpaceLegendAISuggestApplied(
|
|
132
|
-
editorStore.applicationStore.telemetryService,
|
|
133
|
-
dataSpace.path,
|
|
134
|
-
);
|
|
135
|
-
dataSpace_setDescription(dataSpace, aiDocSuggestion);
|
|
136
|
-
setAIDocSuggestion(undefined);
|
|
137
|
-
};
|
|
138
|
-
const discardAIDocSuggestion = (): void => {
|
|
139
|
-
LegendStudioTelemetryHelper.logEvent_DataSpaceLegendAISuggestDiscarded(
|
|
140
|
-
editorStore.applicationStore.telemetryService,
|
|
141
|
-
dataSpace.path,
|
|
142
|
-
);
|
|
143
|
-
setAIDocSuggestion(undefined);
|
|
144
|
-
};
|
|
145
45
|
|
|
146
46
|
return (
|
|
147
47
|
<PanelContentLists className="dataSpace-editor__general">
|
|
148
|
-
<
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
update={handleTitleChange}
|
|
154
|
-
placeholder="Enter title"
|
|
155
|
-
/>
|
|
156
|
-
<div className="panel__content__form__section">
|
|
157
|
-
<div className="panel__content__form__section__header__label">
|
|
158
|
-
Description
|
|
159
|
-
{aiDocSuggestion && (
|
|
160
|
-
<span
|
|
161
|
-
className="dataSpace-editor__ai-suggestion-badge"
|
|
162
|
-
style={{ marginLeft: '0.8rem' }}
|
|
163
|
-
>
|
|
164
|
-
<SparkleIcon />
|
|
165
|
-
AI Suggestion
|
|
166
|
-
</span>
|
|
167
|
-
)}
|
|
168
|
-
{aiDocSuggester && !aiDocSuggestion && (
|
|
169
|
-
<button
|
|
170
|
-
className="dataSpace-editor__ai-suggest-btn"
|
|
171
|
-
style={{ marginLeft: '0.8rem' }}
|
|
172
|
-
onClick={(): void => {
|
|
173
|
-
suggestDocumentationWithAI().catch(
|
|
174
|
-
editorStore.applicationStore.alertUnhandledError,
|
|
175
|
-
);
|
|
176
|
-
}}
|
|
177
|
-
disabled={isSuggestingWithAI || isReadOnly}
|
|
178
|
-
title="Use AI to suggest a description for this data product"
|
|
179
|
-
>
|
|
180
|
-
<SparkleIcon />
|
|
181
|
-
<span>
|
|
182
|
-
{isSuggestingWithAI ? 'Suggesting...' : 'Suggest with AI'}
|
|
183
|
-
</span>
|
|
184
|
-
</button>
|
|
185
|
-
)}
|
|
186
|
-
</div>
|
|
187
|
-
<div className="panel__content__form__section__header__prompt">
|
|
188
|
-
Provide a description for this Data Product.
|
|
189
|
-
</div>
|
|
190
|
-
<PanelLoadingIndicator isLoading={isSuggestingWithAI} />
|
|
191
|
-
<textarea
|
|
192
|
-
className={clsx('panel__content__form__section__textarea', {
|
|
193
|
-
'textarea--ai-suggested': Boolean(aiDocSuggestion),
|
|
194
|
-
})}
|
|
195
|
-
spellCheck={false}
|
|
196
|
-
disabled={isReadOnly}
|
|
197
|
-
readOnly={Boolean(aiDocSuggestion)}
|
|
198
|
-
value={aiDocSuggestion ?? dataSpace.description ?? ''}
|
|
199
|
-
onChange={(event) => {
|
|
200
|
-
handleDescriptionChange(event.target.value);
|
|
201
|
-
}}
|
|
202
|
-
placeholder="Enter description"
|
|
203
|
-
/>
|
|
204
|
-
{aiDocSuggestion && (
|
|
205
|
-
<div className="dataSpace-editor__ai-suggestion__actions">
|
|
206
|
-
<button
|
|
207
|
-
className="btn btn--dark dataSpace-editor__ai-suggestion__apply-btn"
|
|
208
|
-
onClick={applyAIDocSuggestion}
|
|
209
|
-
title="Apply AI suggestion to description"
|
|
210
|
-
>
|
|
211
|
-
Apply Suggestion
|
|
212
|
-
</button>
|
|
213
|
-
<button
|
|
214
|
-
className="btn dataSpace-editor__ai-suggestion__dismiss-btn"
|
|
215
|
-
onClick={discardAIDocSuggestion}
|
|
216
|
-
title="Dismiss AI suggestion"
|
|
217
|
-
>
|
|
218
|
-
Dismiss
|
|
219
|
-
</button>
|
|
220
|
-
</div>
|
|
221
|
-
)}
|
|
222
|
-
</div>
|
|
223
|
-
<DataSpaceDefaultExecutionContextSection />
|
|
224
|
-
<DataSpaceDiagramsSection />
|
|
225
|
-
<DataSpaceElementsSection />
|
|
226
|
-
<DataspaceExecutablesSection />
|
|
227
|
-
<DataSpaceSupportInfoSection />
|
|
228
|
-
</PanelForm>
|
|
48
|
+
<DataSpaceSidebar
|
|
49
|
+
selectedTab={dataSpaceState.selectedTab}
|
|
50
|
+
setSelectedTab={(tab): void => dataSpaceState.setSelectedTab(tab)}
|
|
51
|
+
/>
|
|
52
|
+
<div className="dataSpace-editor__general__content">{renderTab()}</div>
|
|
229
53
|
</PanelContentLists>
|
|
230
54
|
);
|
|
231
55
|
});
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026-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
|
+
useEditorStore,
|
|
19
|
+
LEGEND_STUDIO_DOCUMENTATION_KEY,
|
|
20
|
+
LegendStudioTelemetryHelper,
|
|
21
|
+
type DSL_DataSpace_LegendStudioApplicationPlugin_Extension,
|
|
22
|
+
} from '@finos/legend-application-studio';
|
|
23
|
+
import {
|
|
24
|
+
clsx,
|
|
25
|
+
PanelForm,
|
|
26
|
+
PanelFormTextField,
|
|
27
|
+
PanelLoadingIndicator,
|
|
28
|
+
SparkleIcon,
|
|
29
|
+
} from '@finos/legend-art';
|
|
30
|
+
import { observer } from 'mobx-react-lite';
|
|
31
|
+
import { useState } from 'react';
|
|
32
|
+
import {
|
|
33
|
+
assertErrorThrown,
|
|
34
|
+
HttpStatus,
|
|
35
|
+
NetworkClientError,
|
|
36
|
+
} from '@finos/legend-shared';
|
|
37
|
+
import { DataSpaceEditorState } from '../../stores/DataSpaceEditorState.js';
|
|
38
|
+
import {
|
|
39
|
+
dataSpace_setDescription,
|
|
40
|
+
dataSpace_setTitle,
|
|
41
|
+
} from '../../stores/studio/DSL_DataSpace_GraphModifierHelper.js';
|
|
42
|
+
import { DataSpaceDiagramsSection } from './DataSpaceDiagramsSection.js';
|
|
43
|
+
import { DataSpaceElementsSection } from './DataSpaceElementsSection.js';
|
|
44
|
+
import { DataSpaceSupportInfoSection } from './DataSpaceSupportInfoSection.js';
|
|
45
|
+
import {
|
|
46
|
+
dataSpaceNeedsExecutionContextOrExecutable,
|
|
47
|
+
InlineIssue,
|
|
48
|
+
} from './DataSpaceValidation.js';
|
|
49
|
+
|
|
50
|
+
export const DataSpaceHomeTab = observer(() => {
|
|
51
|
+
const editorStore = useEditorStore();
|
|
52
|
+
|
|
53
|
+
const dataSpaceState =
|
|
54
|
+
editorStore.tabManagerState.getCurrentEditorState(DataSpaceEditorState);
|
|
55
|
+
const dataSpace = dataSpaceState.dataSpace;
|
|
56
|
+
const isReadOnly = dataSpaceState.isReadOnly;
|
|
57
|
+
|
|
58
|
+
const handleTitleChange = (value: string | undefined): void => {
|
|
59
|
+
dataSpace_setTitle(dataSpace, value);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const handleDescriptionChange = (value: string | undefined): void => {
|
|
63
|
+
dataSpace_setDescription(dataSpace, value);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const legendAIUrl = editorStore.applicationStore.config.legendAIUrl;
|
|
67
|
+
const aiDocSuggester = legendAIUrl
|
|
68
|
+
? editorStore.pluginManager
|
|
69
|
+
.getApplicationPlugins()
|
|
70
|
+
.map((p) =>
|
|
71
|
+
(
|
|
72
|
+
p as DSL_DataSpace_LegendStudioApplicationPlugin_Extension
|
|
73
|
+
).getExtraDataSpaceDocumentationAISuggester?.bind(p),
|
|
74
|
+
)
|
|
75
|
+
.find(Boolean)
|
|
76
|
+
: undefined;
|
|
77
|
+
const [isSuggestingWithAI, setIsSuggestingWithAI] = useState(false);
|
|
78
|
+
const [aiDocSuggestion, setAIDocSuggestion] = useState<string | undefined>(
|
|
79
|
+
undefined,
|
|
80
|
+
);
|
|
81
|
+
const suggestDocumentationWithAI = async (): Promise<void> => {
|
|
82
|
+
if (!aiDocSuggester || !legendAIUrl) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
LegendStudioTelemetryHelper.logEvent_DataSpaceLegendAISuggestLaunched(
|
|
86
|
+
editorStore.applicationStore.telemetryService,
|
|
87
|
+
dataSpace.path,
|
|
88
|
+
);
|
|
89
|
+
setIsSuggestingWithAI(true);
|
|
90
|
+
setAIDocSuggestion(undefined);
|
|
91
|
+
try {
|
|
92
|
+
const definitions =
|
|
93
|
+
await editorStore.graphManagerState.graphManager.graphToPureCode(
|
|
94
|
+
editorStore.graphManagerState.graph,
|
|
95
|
+
);
|
|
96
|
+
const suggestion = await aiDocSuggester(
|
|
97
|
+
{ definitions, data_space_name: dataSpace.path },
|
|
98
|
+
legendAIUrl,
|
|
99
|
+
);
|
|
100
|
+
setAIDocSuggestion(suggestion.description);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
assertErrorThrown(error);
|
|
103
|
+
LegendStudioTelemetryHelper.logEvent_DataSpaceLegendAISuggestFailure(
|
|
104
|
+
editorStore.applicationStore.telemetryService,
|
|
105
|
+
dataSpace.path,
|
|
106
|
+
error.message,
|
|
107
|
+
);
|
|
108
|
+
if (
|
|
109
|
+
error instanceof NetworkClientError &&
|
|
110
|
+
(error.response.status === HttpStatus.UNAUTHORIZED ||
|
|
111
|
+
error.response.status === HttpStatus.FORBIDDEN)
|
|
112
|
+
) {
|
|
113
|
+
const docEntry =
|
|
114
|
+
editorStore.applicationStore.documentationService.getDocEntry(
|
|
115
|
+
LEGEND_STUDIO_DOCUMENTATION_KEY.LEGENDAI_HOW_TO_GET_ENTITLEMENTS,
|
|
116
|
+
);
|
|
117
|
+
if (docEntry?.url) {
|
|
118
|
+
error.message = `${error.message}. Please check how to get entitlements: ${docEntry.url}`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
throw error;
|
|
122
|
+
} finally {
|
|
123
|
+
setIsSuggestingWithAI(false);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
const applyAIDocSuggestion = (): void => {
|
|
127
|
+
if (!aiDocSuggestion) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
LegendStudioTelemetryHelper.logEvent_DataSpaceLegendAISuggestApplied(
|
|
131
|
+
editorStore.applicationStore.telemetryService,
|
|
132
|
+
dataSpace.path,
|
|
133
|
+
);
|
|
134
|
+
dataSpace_setDescription(dataSpace, aiDocSuggestion);
|
|
135
|
+
setAIDocSuggestion(undefined);
|
|
136
|
+
};
|
|
137
|
+
const discardAIDocSuggestion = (): void => {
|
|
138
|
+
LegendStudioTelemetryHelper.logEvent_DataSpaceLegendAISuggestDiscarded(
|
|
139
|
+
editorStore.applicationStore.telemetryService,
|
|
140
|
+
dataSpace.path,
|
|
141
|
+
);
|
|
142
|
+
setAIDocSuggestion(undefined);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
return (
|
|
146
|
+
<PanelForm>
|
|
147
|
+
{dataSpaceNeedsExecutionContextOrExecutable(dataSpace) && (
|
|
148
|
+
<InlineIssue
|
|
149
|
+
issue={{
|
|
150
|
+
severity: 'error',
|
|
151
|
+
message:
|
|
152
|
+
'Add at least one execution context, or at least one executable.',
|
|
153
|
+
}}
|
|
154
|
+
/>
|
|
155
|
+
)}
|
|
156
|
+
<PanelFormTextField
|
|
157
|
+
name="Title"
|
|
158
|
+
value={dataSpace.title ?? ''}
|
|
159
|
+
prompt="Provide a title for this Data Product."
|
|
160
|
+
update={handleTitleChange}
|
|
161
|
+
placeholder="Enter title"
|
|
162
|
+
/>
|
|
163
|
+
<div className="panel__content__form__section">
|
|
164
|
+
<div className="panel__content__form__section__header__label">
|
|
165
|
+
Description
|
|
166
|
+
{aiDocSuggestion && (
|
|
167
|
+
<span
|
|
168
|
+
className="dataSpace-editor__ai-suggestion-badge"
|
|
169
|
+
style={{ marginLeft: '0.8rem' }}
|
|
170
|
+
>
|
|
171
|
+
<SparkleIcon />
|
|
172
|
+
AI Suggestion
|
|
173
|
+
</span>
|
|
174
|
+
)}
|
|
175
|
+
{aiDocSuggester && !aiDocSuggestion && (
|
|
176
|
+
<button
|
|
177
|
+
className="dataSpace-editor__ai-suggest-btn"
|
|
178
|
+
style={{ marginLeft: '0.8rem' }}
|
|
179
|
+
onClick={(): void => {
|
|
180
|
+
suggestDocumentationWithAI().catch(
|
|
181
|
+
editorStore.applicationStore.alertUnhandledError,
|
|
182
|
+
);
|
|
183
|
+
}}
|
|
184
|
+
disabled={isSuggestingWithAI || isReadOnly}
|
|
185
|
+
title="Use AI to suggest a description for this data product"
|
|
186
|
+
>
|
|
187
|
+
<SparkleIcon />
|
|
188
|
+
<span>
|
|
189
|
+
{isSuggestingWithAI ? 'Suggesting...' : 'Suggest with AI'}
|
|
190
|
+
</span>
|
|
191
|
+
</button>
|
|
192
|
+
)}
|
|
193
|
+
</div>
|
|
194
|
+
<div className="panel__content__form__section__header__prompt">
|
|
195
|
+
Provide a description for this Data Product.
|
|
196
|
+
</div>
|
|
197
|
+
<PanelLoadingIndicator isLoading={isSuggestingWithAI} />
|
|
198
|
+
<textarea
|
|
199
|
+
className={clsx('panel__content__form__section__textarea', {
|
|
200
|
+
'textarea--ai-suggested': Boolean(aiDocSuggestion),
|
|
201
|
+
})}
|
|
202
|
+
spellCheck={false}
|
|
203
|
+
disabled={isReadOnly}
|
|
204
|
+
readOnly={Boolean(aiDocSuggestion)}
|
|
205
|
+
value={aiDocSuggestion ?? dataSpace.description ?? ''}
|
|
206
|
+
onChange={(event) => {
|
|
207
|
+
handleDescriptionChange(event.target.value);
|
|
208
|
+
}}
|
|
209
|
+
placeholder="Enter description"
|
|
210
|
+
/>
|
|
211
|
+
{aiDocSuggestion && (
|
|
212
|
+
<div className="dataSpace-editor__ai-suggestion__actions">
|
|
213
|
+
<button
|
|
214
|
+
className="btn btn--dark dataSpace-editor__ai-suggestion__apply-btn"
|
|
215
|
+
onClick={applyAIDocSuggestion}
|
|
216
|
+
title="Apply AI suggestion to description"
|
|
217
|
+
>
|
|
218
|
+
Apply Suggestion
|
|
219
|
+
</button>
|
|
220
|
+
<button
|
|
221
|
+
className="btn dataSpace-editor__ai-suggestion__dismiss-btn"
|
|
222
|
+
onClick={discardAIDocSuggestion}
|
|
223
|
+
title="Dismiss AI suggestion"
|
|
224
|
+
>
|
|
225
|
+
Dismiss
|
|
226
|
+
</button>
|
|
227
|
+
</div>
|
|
228
|
+
)}
|
|
229
|
+
</div>
|
|
230
|
+
<DataSpaceDiagramsSection />
|
|
231
|
+
<DataSpaceElementsSection />
|
|
232
|
+
<DataSpaceSupportInfoSection />
|
|
233
|
+
</PanelForm>
|
|
234
|
+
);
|
|
235
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026-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 { observer } from 'mobx-react-lite';
|
|
18
|
+
import { clsx, HomeIcon, PlayIcon, SitemapIcon } from '@finos/legend-art';
|
|
19
|
+
import { DATA_SPACE_TAB } from '../../stores/DataSpaceEditorState.js';
|
|
20
|
+
|
|
21
|
+
const SIDEBAR_TABS = [
|
|
22
|
+
{ tab: DATA_SPACE_TAB.HOME, icon: <HomeIcon /> },
|
|
23
|
+
{ tab: DATA_SPACE_TAB.EXECUTION_CONTEXTS, icon: <SitemapIcon /> },
|
|
24
|
+
{ tab: DATA_SPACE_TAB.EXECUTABLES, icon: <PlayIcon /> },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
export const DataSpaceSidebar = observer(
|
|
28
|
+
(props: {
|
|
29
|
+
selectedTab: DATA_SPACE_TAB;
|
|
30
|
+
setSelectedTab: (tab: DATA_SPACE_TAB) => void;
|
|
31
|
+
}) => {
|
|
32
|
+
const { selectedTab, setSelectedTab } = props;
|
|
33
|
+
return (
|
|
34
|
+
<div
|
|
35
|
+
className="data-space__viewer__activity-bar dataSpace-editor__sidebar"
|
|
36
|
+
style={{ position: 'static', maxHeight: '100%' }}
|
|
37
|
+
>
|
|
38
|
+
<div className="data-space__viewer__activity-bar__items">
|
|
39
|
+
{SIDEBAR_TABS.map((item) => (
|
|
40
|
+
<button
|
|
41
|
+
key={item.tab}
|
|
42
|
+
className={clsx('data-space__viewer__activity-bar__item', {
|
|
43
|
+
'data-space__viewer__activity-bar__item--active':
|
|
44
|
+
selectedTab === item.tab,
|
|
45
|
+
})}
|
|
46
|
+
onClick={(): void => setSelectedTab(item.tab)}
|
|
47
|
+
tabIndex={-1}
|
|
48
|
+
title={item.tab}
|
|
49
|
+
>
|
|
50
|
+
{item.icon}
|
|
51
|
+
<span className="dataSpace-editor__sidebar__item__label">
|
|
52
|
+
{item.tab}
|
|
53
|
+
</span>
|
|
54
|
+
</button>
|
|
55
|
+
))}
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
},
|
|
60
|
+
);
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026-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 { clsx, WarningIcon } from '@finos/legend-art';
|
|
18
|
+
import type {
|
|
19
|
+
DataSpace,
|
|
20
|
+
DataSpaceExecutionContext,
|
|
21
|
+
} from '@finos/legend-extension-dsl-data-space/graph';
|
|
22
|
+
|
|
23
|
+
export type DataSpaceValidationIssue = {
|
|
24
|
+
severity: 'error' | 'warning';
|
|
25
|
+
message: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const InlineIssue: React.FC<{ issue: DataSpaceValidationIssue }> = (
|
|
29
|
+
props,
|
|
30
|
+
) => (
|
|
31
|
+
<div
|
|
32
|
+
className={clsx('dataSpace-editor__inline-warning', {
|
|
33
|
+
'dataSpace-editor__inline-warning--error':
|
|
34
|
+
props.issue.severity === 'error',
|
|
35
|
+
'dataSpace-editor__inline-warning--warning':
|
|
36
|
+
props.issue.severity === 'warning',
|
|
37
|
+
})}
|
|
38
|
+
>
|
|
39
|
+
<WarningIcon />
|
|
40
|
+
<span>{props.issue.message}</span>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
export const hasNoMappingSource = (
|
|
45
|
+
executionContext: DataSpaceExecutionContext,
|
|
46
|
+
): boolean => !executionContext.mapping && !executionContext.mappingProvider;
|
|
47
|
+
|
|
48
|
+
export const collectExecutionContextValidationIssues = (
|
|
49
|
+
executionContext: DataSpaceExecutionContext,
|
|
50
|
+
): DataSpaceValidationIssue[] => {
|
|
51
|
+
const issues: DataSpaceValidationIssue[] = [];
|
|
52
|
+
const hasMapping = Boolean(executionContext.mapping);
|
|
53
|
+
const hasMappingProvider = Boolean(executionContext.mappingProvider);
|
|
54
|
+
if (hasMapping && hasMappingProvider) {
|
|
55
|
+
issues.push({
|
|
56
|
+
severity: 'error',
|
|
57
|
+
message: `Only one of mapping and mapping provider can be set.`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (
|
|
61
|
+
executionContext.mappingProvider &&
|
|
62
|
+
!executionContext.mappingProvider.keys.length
|
|
63
|
+
) {
|
|
64
|
+
issues.push({
|
|
65
|
+
severity: 'error',
|
|
66
|
+
message: `Select an access point group for the mapping provider.`,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return issues;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export const hasExecutionContextValidationError = (
|
|
73
|
+
executionContext: DataSpaceExecutionContext,
|
|
74
|
+
): boolean =>
|
|
75
|
+
hasNoMappingSource(executionContext) ||
|
|
76
|
+
collectExecutionContextValidationIssues(executionContext).some(
|
|
77
|
+
(issue) => issue.severity === 'error',
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
export const dataSpaceNeedsExecutionContextOrExecutable = (
|
|
81
|
+
dataSpace: DataSpace,
|
|
82
|
+
): boolean =>
|
|
83
|
+
!dataSpace.executionContexts?.length && !dataSpace.executables?.length;
|