@finos/legend-extension-dsl-data-space-studio 0.1.152 → 0.1.154
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 +27 -0
- package/lib/components/DSL_DataProduct_ElementDriver.d.ts.map +1 -0
- package/lib/components/DSL_DataProduct_ElementDriver.js +60 -0
- package/lib/components/DSL_DataProduct_ElementDriver.js.map +1 -0
- package/lib/components/DSL_DataSpace_LegendStudioApplicationPlugin.d.ts +3 -1
- package/lib/components/DSL_DataSpace_LegendStudioApplicationPlugin.d.ts.map +1 -1
- package/lib/components/DSL_DataSpace_LegendStudioApplicationPlugin.js +30 -15
- package/lib/components/DSL_DataSpace_LegendStudioApplicationPlugin.js.map +1 -1
- package/lib/components/DSL_NewDataProductEditor.d.ts +19 -0
- package/lib/components/DSL_NewDataProductEditor.d.ts.map +1 -0
- package/lib/components/DSL_NewDataProductEditor.js +32 -0
- package/lib/components/DSL_NewDataProductEditor.js.map +1 -0
- package/lib/components/DataSpaceEditor.d.ts +1 -1
- package/lib/components/DataSpaceEditor.d.ts.map +1 -1
- package/lib/components/DataSpaceEditor.js +18 -9
- package/lib/components/DataSpaceEditor.js.map +1 -1
- package/lib/components/DataSpaceExecutionContextEditor.d.ts +37 -0
- package/lib/components/DataSpaceExecutionContextEditor.d.ts.map +1 -0
- package/lib/components/DataSpaceExecutionContextEditor.js +170 -0
- package/lib/components/DataSpaceExecutionContextEditor.js.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceDefaultExecutionContextSection.d.ts +19 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceDefaultExecutionContextSection.d.ts.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceDefaultExecutionContextSection.js +138 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceDefaultExecutionContextSection.js.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceDiagramsSection.d.ts +19 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceDiagramsSection.d.ts.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceDiagramsSection.js +63 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceDiagramsSection.js.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceElementsSection.d.ts +19 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceElementsSection.d.ts.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceElementsSection.js +58 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceElementsSection.js.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceExecutablesSection.d.ts +19 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceExecutablesSection.d.ts.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceExecutablesSection.js +56 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceExecutablesSection.js.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceGeneralEditor.d.ts +19 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceGeneralEditor.d.ts.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceGeneralEditor.js +40 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceGeneralEditor.js.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceSupportInfoSection.d.ts +19 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceSupportInfoSection.d.ts.map +1 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceSupportInfoSection.js +120 -0
- package/lib/components/DataSpaceGeneralEditor/DataSpaceSupportInfoSection.js.map +1 -0
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +3 -2
- package/lib/stores/DataSpaceEditorState.d.ts +18 -2
- package/lib/stores/DataSpaceEditorState.d.ts.map +1 -1
- package/lib/stores/DataSpaceEditorState.js +55 -3
- package/lib/stores/DataSpaceEditorState.js.map +1 -1
- package/lib/stores/DataSpaceExecutionContextState.d.ts +37 -0
- package/lib/stores/DataSpaceExecutionContextState.d.ts.map +1 -0
- package/lib/stores/DataSpaceExecutionContextState.js +87 -0
- package/lib/stores/DataSpaceExecutionContextState.js.map +1 -0
- package/lib/stores/studio/DSL_DataSpace_GraphModifierHelper.d.ts +34 -3
- package/lib/stores/studio/DSL_DataSpace_GraphModifierHelper.d.ts.map +1 -1
- package/lib/stores/studio/DSL_DataSpace_GraphModifierHelper.js +128 -2
- package/lib/stores/studio/DSL_DataSpace_GraphModifierHelper.js.map +1 -1
- package/package.json +10 -9
- package/src/components/DSL_DataProduct_ElementDriver.tsx +82 -0
- package/src/components/DSL_DataSpace_LegendStudioApplicationPlugin.tsx +35 -19
- package/src/components/DSL_NewDataProductEditor.tsx +57 -0
- package/src/components/DataSpaceEditor.tsx +54 -33
- package/src/components/DataSpaceExecutionContextEditor.tsx +692 -0
- package/src/components/DataSpaceGeneralEditor/DataSpaceDefaultExecutionContextSection.tsx +393 -0
- package/src/components/DataSpaceGeneralEditor/DataSpaceDiagramsSection.tsx +144 -0
- package/src/components/DataSpaceGeneralEditor/DataSpaceElementsSection.tsx +128 -0
- package/src/components/DataSpaceGeneralEditor/DataSpaceExecutablesSection.tsx +108 -0
- package/src/components/DataSpaceGeneralEditor/DataSpaceGeneralEditor.tsx +76 -0
- package/src/components/DataSpaceGeneralEditor/DataSpaceSupportInfoSection.tsx +276 -0
- package/src/stores/DataSpaceEditorState.ts +92 -4
- package/src/stores/DataSpaceExecutionContextState.ts +135 -0
- package/src/stores/studio/DSL_DataSpace_GraphModifierHelper.ts +278 -3
- package/tsconfig.json +11 -1
@@ -0,0 +1,692 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (c) 2020-present, Goldman Sachs
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
|
17
|
+
import {
|
18
|
+
type ElementDragSource,
|
19
|
+
type UMLEditorElementDropTarget,
|
20
|
+
CORE_DND_TYPE,
|
21
|
+
useEditorStore,
|
22
|
+
} from '@finos/legend-application-studio';
|
23
|
+
import { observer } from 'mobx-react-lite';
|
24
|
+
import { useDrop } from 'react-dnd';
|
25
|
+
import { DataSpaceEditorState } from '../stores/DataSpaceEditorState.js';
|
26
|
+
import {
|
27
|
+
BlankPanelPlaceholder,
|
28
|
+
clsx,
|
29
|
+
ContextMenu,
|
30
|
+
CustomSelectorInput,
|
31
|
+
Dialog,
|
32
|
+
ErrorIcon,
|
33
|
+
ExclamationTriangleIcon,
|
34
|
+
InputWithInlineValidation,
|
35
|
+
LongArrowRightIcon,
|
36
|
+
MenuContent,
|
37
|
+
MenuContentItem,
|
38
|
+
ModalTitle,
|
39
|
+
PanelContent,
|
40
|
+
PanelDropZone,
|
41
|
+
PanelHeader,
|
42
|
+
PanelHeaderActionItem,
|
43
|
+
PanelHeaderActions,
|
44
|
+
PlusIcon,
|
45
|
+
PURE_MappingIcon,
|
46
|
+
PURE_RuntimeIcon,
|
47
|
+
ResizablePanel,
|
48
|
+
ResizablePanelGroup,
|
49
|
+
ResizablePanelSplitter,
|
50
|
+
ResizablePanelSplitterLine,
|
51
|
+
} from '@finos/legend-art';
|
52
|
+
import {
|
53
|
+
Mapping,
|
54
|
+
PackageableElementExplicitReference,
|
55
|
+
PackageableRuntime,
|
56
|
+
validate_PureExecutionMapping,
|
57
|
+
} from '@finos/legend-graph';
|
58
|
+
import {
|
59
|
+
dataSpace_setExecutionContextDefaultRuntime,
|
60
|
+
dataSpace_setExecutionContextMapping,
|
61
|
+
dataSpace_setExecutionContextTitle,
|
62
|
+
dataSpace_setExecutionContextDescription,
|
63
|
+
} from '../stores/studio/DSL_DataSpace_GraphModifierHelper.js';
|
64
|
+
import { guaranteeNonNullable } from '@finos/legend-shared';
|
65
|
+
import { forwardRef, useCallback, useState } from 'react';
|
66
|
+
import type { DataSpaceExecutionContextState } from '../stores/DataSpaceExecutionContextState.js';
|
67
|
+
import type { DataSpaceExecutionContext } from '@finos/legend-extension-dsl-data-space/graph';
|
68
|
+
import {
|
69
|
+
buildElementOption,
|
70
|
+
type PackageableElementOption,
|
71
|
+
} from '@finos/legend-lego/graph-editor';
|
72
|
+
import type { PropsValue } from 'react-select';
|
73
|
+
|
74
|
+
const DataSpaceExecutionContextConfigurationEditor = observer(
|
75
|
+
(props: {
|
76
|
+
executionContextState: DataSpaceExecutionContextState;
|
77
|
+
executionContext: DataSpaceExecutionContext;
|
78
|
+
}) => {
|
79
|
+
const { executionContextState, executionContext } = props;
|
80
|
+
const isReadOnly = executionContextState.dataSpaceEditorState.isReadOnly;
|
81
|
+
const editorStore = executionContextState.editorStore;
|
82
|
+
const applicationStore = editorStore.applicationStore;
|
83
|
+
|
84
|
+
// Mapping
|
85
|
+
// TODO: this is not generic error handling, as there could be other problems
|
86
|
+
// with mapping, we need to genericize this
|
87
|
+
const isMappingEmpty = validate_PureExecutionMapping(
|
88
|
+
executionContext.mapping.value,
|
89
|
+
);
|
90
|
+
const mapping = executionContext.mapping.value;
|
91
|
+
const mappingOptions =
|
92
|
+
editorStore.graphManagerState.usableMappings.map(buildElementOption);
|
93
|
+
const noMappingLabel = (
|
94
|
+
<div
|
95
|
+
className="service-execution-editor__configuration__mapping-option--empty"
|
96
|
+
title={isMappingEmpty?.messages.join('\n') ?? ''}
|
97
|
+
>
|
98
|
+
<div className="service-execution-editor__configuration__mapping-option--empty__label">
|
99
|
+
(none)
|
100
|
+
</div>
|
101
|
+
<ErrorIcon />
|
102
|
+
</div>
|
103
|
+
);
|
104
|
+
const selectedMappingOption = {
|
105
|
+
value: mapping,
|
106
|
+
label: isMappingEmpty ? noMappingLabel : mapping.path,
|
107
|
+
} as PackageableElementOption<Mapping>;
|
108
|
+
const onMappingSelectionChange = (
|
109
|
+
val: PackageableElementOption<Mapping>,
|
110
|
+
): void => {
|
111
|
+
if (val.value !== mapping) {
|
112
|
+
dataSpace_setExecutionContextMapping(
|
113
|
+
executionContext,
|
114
|
+
PackageableElementExplicitReference.create(val.value),
|
115
|
+
);
|
116
|
+
executionContextState.autoSelectRuntimeOnMappingChange(val.value);
|
117
|
+
}
|
118
|
+
};
|
119
|
+
const visitMapping = (): void =>
|
120
|
+
editorStore.graphEditorMode.openElement(mapping);
|
121
|
+
|
122
|
+
// Runtime
|
123
|
+
const defaultRuntime = executionContext.defaultRuntime;
|
124
|
+
// NOTE: for now, only include runtime associated with the mapping
|
125
|
+
// TODO?: Should we bring the runtime compatibility check from query to here?
|
126
|
+
const runtimes = editorStore.graphManagerState.graph.runtimes.filter((rt) =>
|
127
|
+
rt.runtimeValue.mappings.map((m) => m.value).includes(mapping),
|
128
|
+
);
|
129
|
+
const runtimeOptions = runtimes.map((rt) => ({
|
130
|
+
label: rt.path,
|
131
|
+
value: PackageableElementExplicitReference.create(rt),
|
132
|
+
}));
|
133
|
+
const runtimePointerWarning = !runtimes.includes(defaultRuntime.value) // if the runtime does not belong to the chosen mapping
|
134
|
+
? `runtime is not associated with specified mapping '${mapping.path}'`
|
135
|
+
: undefined;
|
136
|
+
const selectedRuntimeOption = {
|
137
|
+
value: defaultRuntime,
|
138
|
+
label: (
|
139
|
+
<div
|
140
|
+
className="service-execution-editor__configuration__runtime-option__pointer"
|
141
|
+
title={undefined}
|
142
|
+
>
|
143
|
+
<div
|
144
|
+
className={clsx(
|
145
|
+
'service-execution-editor__configuration__runtime-option__pointer__label',
|
146
|
+
{
|
147
|
+
'service-execution-editor__configuration__runtime-option__pointer__label--with-warning':
|
148
|
+
Boolean(runtimePointerWarning),
|
149
|
+
},
|
150
|
+
)}
|
151
|
+
>
|
152
|
+
{defaultRuntime.value.path}
|
153
|
+
</div>
|
154
|
+
{runtimePointerWarning && (
|
155
|
+
<div
|
156
|
+
className="service-execution-editor__configuration__runtime-option__pointer__warning"
|
157
|
+
title={runtimePointerWarning}
|
158
|
+
>
|
159
|
+
<ExclamationTriangleIcon />
|
160
|
+
</div>
|
161
|
+
)}
|
162
|
+
</div>
|
163
|
+
),
|
164
|
+
} as unknown as PropsValue<{
|
165
|
+
label: string;
|
166
|
+
value: PackageableElementExplicitReference<PackageableRuntime>;
|
167
|
+
}>;
|
168
|
+
const onRuntimeSelectionChange = (val: {
|
169
|
+
label: string | React.ReactNode;
|
170
|
+
value:
|
171
|
+
| PackageableElementExplicitReference<PackageableRuntime>
|
172
|
+
| undefined;
|
173
|
+
}): void => {
|
174
|
+
if (
|
175
|
+
val.value?.value !== defaultRuntime.value &&
|
176
|
+
val.value !== undefined
|
177
|
+
) {
|
178
|
+
dataSpace_setExecutionContextDefaultRuntime(
|
179
|
+
executionContext,
|
180
|
+
val.value,
|
181
|
+
);
|
182
|
+
}
|
183
|
+
};
|
184
|
+
const visitRuntime = (): void => {
|
185
|
+
editorStore.graphEditorMode.openElement(defaultRuntime.value);
|
186
|
+
};
|
187
|
+
|
188
|
+
// DnD
|
189
|
+
const handleMappingOrRuntimeDrop = useCallback(
|
190
|
+
(item: UMLEditorElementDropTarget): void => {
|
191
|
+
const element = item.data.packageableElement;
|
192
|
+
if (!isReadOnly) {
|
193
|
+
if (element instanceof Mapping) {
|
194
|
+
dataSpace_setExecutionContextMapping(
|
195
|
+
executionContext,
|
196
|
+
PackageableElementExplicitReference.create(element),
|
197
|
+
);
|
198
|
+
executionContextState.autoSelectRuntimeOnMappingChange(element);
|
199
|
+
} else if (
|
200
|
+
element instanceof PackageableRuntime &&
|
201
|
+
element.runtimeValue.mappings.map((m) => m.value).includes(mapping)
|
202
|
+
) {
|
203
|
+
dataSpace_setExecutionContextDefaultRuntime(
|
204
|
+
executionContext,
|
205
|
+
PackageableElementExplicitReference.create(element),
|
206
|
+
);
|
207
|
+
}
|
208
|
+
}
|
209
|
+
},
|
210
|
+
[isReadOnly, mapping, executionContextState, executionContext],
|
211
|
+
);
|
212
|
+
const [{ isMappingOrRuntimeDragOver }, dropConnector] = useDrop<
|
213
|
+
ElementDragSource,
|
214
|
+
void,
|
215
|
+
{ isMappingOrRuntimeDragOver: boolean }
|
216
|
+
>(
|
217
|
+
() => ({
|
218
|
+
accept: [
|
219
|
+
CORE_DND_TYPE.PROJECT_EXPLORER_MAPPING,
|
220
|
+
CORE_DND_TYPE.PROJECT_EXPLORER_RUNTIME,
|
221
|
+
],
|
222
|
+
drop: (item) => handleMappingOrRuntimeDrop(item),
|
223
|
+
collect: (monitor) => ({
|
224
|
+
isMappingOrRuntimeDragOver: monitor.isOver({ shallow: true }),
|
225
|
+
}),
|
226
|
+
}),
|
227
|
+
[handleMappingOrRuntimeDrop],
|
228
|
+
);
|
229
|
+
|
230
|
+
return (
|
231
|
+
<PanelContent>
|
232
|
+
<PanelDropZone
|
233
|
+
dropTargetConnector={dropConnector}
|
234
|
+
isDragOver={isMappingOrRuntimeDragOver && !isReadOnly}
|
235
|
+
>
|
236
|
+
<div className="service-execution-editor__configuration__items">
|
237
|
+
<div className="service-execution-editor__configuration__item">
|
238
|
+
<div className="btn--sm service-execution-editor__configuration__item__label">
|
239
|
+
<PURE_MappingIcon />
|
240
|
+
</div>
|
241
|
+
<CustomSelectorInput
|
242
|
+
className="panel__content__form__section__dropdown service-execution-editor__configuration__item__dropdown"
|
243
|
+
disabled={isReadOnly}
|
244
|
+
options={mappingOptions}
|
245
|
+
onChange={onMappingSelectionChange}
|
246
|
+
value={selectedMappingOption}
|
247
|
+
darkMode={
|
248
|
+
!applicationStore.layoutService
|
249
|
+
.TEMPORARY__isLightColorThemeEnabled
|
250
|
+
}
|
251
|
+
hasError={Boolean(isMappingEmpty)}
|
252
|
+
/>
|
253
|
+
<button
|
254
|
+
className="btn--dark btn--sm service-execution-editor__configuration__item__btn"
|
255
|
+
onClick={visitMapping}
|
256
|
+
tabIndex={-1}
|
257
|
+
title="See mapping"
|
258
|
+
disabled={Boolean(isMappingEmpty)}
|
259
|
+
>
|
260
|
+
<LongArrowRightIcon />
|
261
|
+
</button>
|
262
|
+
</div>
|
263
|
+
<div className="service-execution-editor__configuration__item">
|
264
|
+
<div className="btn--sm service-execution-editor__configuration__item__label">
|
265
|
+
<PURE_RuntimeIcon />
|
266
|
+
</div>
|
267
|
+
<CustomSelectorInput
|
268
|
+
className="panel__content__form__section__dropdown service-execution-editor__configuration__item__dropdown"
|
269
|
+
disabled={isReadOnly}
|
270
|
+
options={runtimeOptions}
|
271
|
+
onChange={onRuntimeSelectionChange}
|
272
|
+
value={selectedRuntimeOption}
|
273
|
+
darkMode={
|
274
|
+
!applicationStore.layoutService
|
275
|
+
.TEMPORARY__isLightColorThemeEnabled
|
276
|
+
}
|
277
|
+
/>
|
278
|
+
<button
|
279
|
+
className="btn--sm btn--dark service-execution-editor__configuration__item__btn"
|
280
|
+
onClick={visitRuntime}
|
281
|
+
tabIndex={-1}
|
282
|
+
title="See runtime"
|
283
|
+
>
|
284
|
+
<LongArrowRightIcon />
|
285
|
+
</button>
|
286
|
+
</div>
|
287
|
+
|
288
|
+
{/* Title input */}
|
289
|
+
<div className="execution-context-editor__form-section">
|
290
|
+
<div className="execution-context-editor__form-section__label">
|
291
|
+
Title
|
292
|
+
</div>
|
293
|
+
<div className="execution-context-editor__form-section__content">
|
294
|
+
<input
|
295
|
+
className="execution-context-editor__form-section__content__input panel__content__form__section__input"
|
296
|
+
spellCheck={false}
|
297
|
+
disabled={isReadOnly}
|
298
|
+
value={executionContext.title ?? ''}
|
299
|
+
onChange={(event): void =>
|
300
|
+
dataSpace_setExecutionContextTitle(
|
301
|
+
executionContext,
|
302
|
+
event.target.value,
|
303
|
+
)
|
304
|
+
}
|
305
|
+
/>
|
306
|
+
</div>
|
307
|
+
</div>
|
308
|
+
|
309
|
+
{/* Description input */}
|
310
|
+
<div className="execution-context-editor__form-section">
|
311
|
+
<div className="execution-context-editor__form-section__label">
|
312
|
+
Description
|
313
|
+
</div>
|
314
|
+
<div className="execution-context-editor__form-section__content">
|
315
|
+
<textarea
|
316
|
+
className="execution-context-editor__form-section__content__textarea panel__content__form__section__input"
|
317
|
+
spellCheck={false}
|
318
|
+
disabled={isReadOnly}
|
319
|
+
value={executionContext.description ?? ''}
|
320
|
+
onChange={(event): void =>
|
321
|
+
dataSpace_setExecutionContextDescription(
|
322
|
+
executionContext,
|
323
|
+
event.target.value,
|
324
|
+
)
|
325
|
+
}
|
326
|
+
rows={4}
|
327
|
+
/>
|
328
|
+
</div>
|
329
|
+
</div>
|
330
|
+
|
331
|
+
{/* Test Data input removed as it's not used */}
|
332
|
+
</div>
|
333
|
+
</PanelDropZone>
|
334
|
+
</PanelContent>
|
335
|
+
);
|
336
|
+
},
|
337
|
+
);
|
338
|
+
|
339
|
+
export const NewExecutionContextModal = observer(
|
340
|
+
(props: {
|
341
|
+
executionState: DataSpaceExecutionContextState;
|
342
|
+
isReadOnly: boolean;
|
343
|
+
}) => {
|
344
|
+
const { executionState, isReadOnly } = props;
|
345
|
+
const [name, setName] = useState('');
|
346
|
+
const validationMessage =
|
347
|
+
name === ''
|
348
|
+
? `Execution context name can't be empty`
|
349
|
+
: executionState.executionContexts.find((e) => e.name === name)
|
350
|
+
? 'Execution context name already exists'
|
351
|
+
: undefined;
|
352
|
+
|
353
|
+
const closeModal = (): void =>
|
354
|
+
executionState.setNewExecutionContextModal(false);
|
355
|
+
const onChange: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
356
|
+
setName(event.target.value);
|
357
|
+
};
|
358
|
+
return (
|
359
|
+
<Dialog
|
360
|
+
open={executionState.newExecutionContextModal}
|
361
|
+
onClose={closeModal}
|
362
|
+
classes={{ container: 'search-modal__container' }}
|
363
|
+
PaperProps={{ classes: { root: 'search-modal__inner-container' } }}
|
364
|
+
>
|
365
|
+
<form
|
366
|
+
onSubmit={(event) => {
|
367
|
+
event.preventDefault();
|
368
|
+
executionState.addExecutionContext(name);
|
369
|
+
setName('');
|
370
|
+
closeModal();
|
371
|
+
}}
|
372
|
+
className="modal modal--dark search-modal"
|
373
|
+
>
|
374
|
+
<ModalTitle title="New Execution Context" />
|
375
|
+
<div className="service-execution-editor__change__modal">
|
376
|
+
<InputWithInlineValidation
|
377
|
+
className="service-execution-editor__input input-group__input"
|
378
|
+
spellCheck={false}
|
379
|
+
value={name}
|
380
|
+
onChange={onChange}
|
381
|
+
placeholder="Key execution name"
|
382
|
+
error={validationMessage}
|
383
|
+
/>
|
384
|
+
</div>
|
385
|
+
<div className="search-modal__actions">
|
386
|
+
<button
|
387
|
+
className="btn btn--dark"
|
388
|
+
disabled={isReadOnly || Boolean(validationMessage)}
|
389
|
+
>
|
390
|
+
Add
|
391
|
+
</button>
|
392
|
+
</div>
|
393
|
+
</form>
|
394
|
+
</Dialog>
|
395
|
+
);
|
396
|
+
},
|
397
|
+
);
|
398
|
+
|
399
|
+
export const RenameModal = observer(
|
400
|
+
(props: {
|
401
|
+
val: string;
|
402
|
+
isReadOnly: boolean;
|
403
|
+
setValue: (val: string) => void;
|
404
|
+
showModal: boolean;
|
405
|
+
closeModal: () => void;
|
406
|
+
executionContext: DataSpaceExecutionContext;
|
407
|
+
}) => {
|
408
|
+
const {
|
409
|
+
val,
|
410
|
+
isReadOnly,
|
411
|
+
showModal,
|
412
|
+
closeModal,
|
413
|
+
setValue,
|
414
|
+
executionContext,
|
415
|
+
} = props;
|
416
|
+
const [inputValue, setInputValue] = useState(val);
|
417
|
+
const changeValue: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
418
|
+
setInputValue(event.target.value);
|
419
|
+
};
|
420
|
+
return (
|
421
|
+
<Dialog
|
422
|
+
open={showModal}
|
423
|
+
onClose={closeModal}
|
424
|
+
classes={{ container: 'search-modal__container' }}
|
425
|
+
PaperProps={{ classes: { root: 'search-modal__inner-container' } }}
|
426
|
+
>
|
427
|
+
<form
|
428
|
+
onSubmit={(event) => {
|
429
|
+
event.preventDefault();
|
430
|
+
setValue(inputValue);
|
431
|
+
closeModal();
|
432
|
+
}}
|
433
|
+
className="modal modal--dark search-modal"
|
434
|
+
>
|
435
|
+
<ModalTitle title="Edit Execution Context" />
|
436
|
+
<div className="execution-context-editor__form-section">
|
437
|
+
<div className="execution-context-editor__form-section__label">
|
438
|
+
Key
|
439
|
+
</div>
|
440
|
+
<div className="execution-context-editor__form-section__content">
|
441
|
+
<input
|
442
|
+
className="execution-context-editor__form-section__content__input panel__content__form__section__input"
|
443
|
+
spellCheck={false}
|
444
|
+
disabled={isReadOnly}
|
445
|
+
value={inputValue}
|
446
|
+
onChange={changeValue}
|
447
|
+
/>
|
448
|
+
</div>
|
449
|
+
</div>
|
450
|
+
|
451
|
+
{/* Title input */}
|
452
|
+
<div className="execution-context-editor__form-section">
|
453
|
+
<div className="execution-context-editor__form-section__label">
|
454
|
+
Title
|
455
|
+
</div>
|
456
|
+
<div className="execution-context-editor__form-section__content">
|
457
|
+
<input
|
458
|
+
className="execution-context-editor__form-section__content__input panel__content__form__section__input"
|
459
|
+
spellCheck={false}
|
460
|
+
disabled={isReadOnly}
|
461
|
+
value={executionContext.title ?? ''}
|
462
|
+
onChange={(event): void =>
|
463
|
+
dataSpace_setExecutionContextTitle(
|
464
|
+
executionContext,
|
465
|
+
event.target.value,
|
466
|
+
)
|
467
|
+
}
|
468
|
+
/>
|
469
|
+
</div>
|
470
|
+
</div>
|
471
|
+
|
472
|
+
{/* Description input */}
|
473
|
+
<div className="execution-context-editor__form-section">
|
474
|
+
<div className="execution-context-editor__form-section__label">
|
475
|
+
Description
|
476
|
+
</div>
|
477
|
+
<div className="execution-context-editor__form-section__content">
|
478
|
+
<textarea
|
479
|
+
className="execution-context-editor__form-section__content__textarea panel__content__form__section__input"
|
480
|
+
spellCheck={false}
|
481
|
+
disabled={isReadOnly}
|
482
|
+
value={executionContext.description ?? ''}
|
483
|
+
onChange={(event): void =>
|
484
|
+
dataSpace_setExecutionContextDescription(
|
485
|
+
executionContext,
|
486
|
+
event.target.value,
|
487
|
+
)
|
488
|
+
}
|
489
|
+
rows={4}
|
490
|
+
/>
|
491
|
+
</div>
|
492
|
+
</div>
|
493
|
+
|
494
|
+
<div className="search-modal__actions">
|
495
|
+
<button className="btn btn--dark" disabled={isReadOnly}>
|
496
|
+
Done
|
497
|
+
</button>
|
498
|
+
</div>
|
499
|
+
</form>
|
500
|
+
</Dialog>
|
501
|
+
);
|
502
|
+
},
|
503
|
+
);
|
504
|
+
|
505
|
+
const ExecutionContextMenu = observer(
|
506
|
+
forwardRef<
|
507
|
+
HTMLDivElement,
|
508
|
+
{
|
509
|
+
dataSpaceExecutionContextState: DataSpaceExecutionContextState;
|
510
|
+
dataSpaceExecutionContext: DataSpaceExecutionContext;
|
511
|
+
isReadOnly: boolean;
|
512
|
+
}
|
513
|
+
>(function TestContainerContextMenu(props, ref) {
|
514
|
+
const { dataSpaceExecutionContextState, dataSpaceExecutionContext } = props;
|
515
|
+
const rename = (): void => {
|
516
|
+
dataSpaceExecutionContextState.setExecutionContextToRename(
|
517
|
+
dataSpaceExecutionContext,
|
518
|
+
);
|
519
|
+
};
|
520
|
+
const remove = (): void => {
|
521
|
+
dataSpaceExecutionContextState.removeExecutionContext(
|
522
|
+
dataSpaceExecutionContext,
|
523
|
+
);
|
524
|
+
};
|
525
|
+
const add = (): void => {
|
526
|
+
dataSpaceExecutionContextState.setNewExecutionContextModal(true);
|
527
|
+
};
|
528
|
+
return (
|
529
|
+
<MenuContent ref={ref}>
|
530
|
+
<MenuContentItem onClick={rename}>Rename</MenuContentItem>
|
531
|
+
<MenuContentItem onClick={remove}>Delete</MenuContentItem>
|
532
|
+
<MenuContentItem onClick={add}>Create a new key</MenuContentItem>
|
533
|
+
</MenuContent>
|
534
|
+
);
|
535
|
+
}),
|
536
|
+
);
|
537
|
+
|
538
|
+
const ExecutionContextItem = observer(
|
539
|
+
(props: {
|
540
|
+
dataSpaceExecutionContextState: DataSpaceExecutionContextState;
|
541
|
+
dataSpaceExecutionContext: DataSpaceExecutionContext;
|
542
|
+
isReadOnly: boolean;
|
543
|
+
}) => {
|
544
|
+
const {
|
545
|
+
dataSpaceExecutionContextState,
|
546
|
+
dataSpaceExecutionContext,
|
547
|
+
isReadOnly,
|
548
|
+
} = props;
|
549
|
+
const [isSelectedFromContextMenu, setIsSelectedFromContextMenu] =
|
550
|
+
useState(false);
|
551
|
+
const isActive =
|
552
|
+
dataSpaceExecutionContextState.selectedExecutionContext ===
|
553
|
+
dataSpaceExecutionContext;
|
554
|
+
|
555
|
+
const openKeyedExecution = (): void =>
|
556
|
+
dataSpaceExecutionContextState.setSelectedExecutionContext(
|
557
|
+
dataSpaceExecutionContext,
|
558
|
+
);
|
559
|
+
const onContextMenuOpen = (): void => setIsSelectedFromContextMenu(true);
|
560
|
+
const onContextMenuClose = (): void => setIsSelectedFromContextMenu(false);
|
561
|
+
return (
|
562
|
+
<ContextMenu
|
563
|
+
className={clsx(
|
564
|
+
'service-multi-execution-editor__item',
|
565
|
+
{
|
566
|
+
'service-multi-execution-editor__item--selected-from-context-menu':
|
567
|
+
!isActive && isSelectedFromContextMenu,
|
568
|
+
},
|
569
|
+
{ 'service-multi-execution-editor__item--active': isActive },
|
570
|
+
)}
|
571
|
+
disabled={isReadOnly}
|
572
|
+
content={
|
573
|
+
<ExecutionContextMenu
|
574
|
+
dataSpaceExecutionContextState={dataSpaceExecutionContextState}
|
575
|
+
dataSpaceExecutionContext={dataSpaceExecutionContext}
|
576
|
+
isReadOnly={isReadOnly}
|
577
|
+
/>
|
578
|
+
}
|
579
|
+
menuProps={{ elevation: 7 }}
|
580
|
+
onOpen={onContextMenuOpen}
|
581
|
+
onClose={onContextMenuClose}
|
582
|
+
>
|
583
|
+
<button
|
584
|
+
className={clsx('service-multi-execution-editor__item__label')}
|
585
|
+
onClick={openKeyedExecution}
|
586
|
+
tabIndex={-1}
|
587
|
+
>
|
588
|
+
{dataSpaceExecutionContext.name}
|
589
|
+
</button>
|
590
|
+
</ContextMenu>
|
591
|
+
);
|
592
|
+
},
|
593
|
+
);
|
594
|
+
|
595
|
+
export const DataSpaceExecutionContextEditor = observer(() => {
|
596
|
+
const editorStore = useEditorStore();
|
597
|
+
|
598
|
+
const dataSpaceState =
|
599
|
+
editorStore.tabManagerState.getCurrentEditorState(DataSpaceEditorState);
|
600
|
+
const executionContextState = dataSpaceState.executionContextState;
|
601
|
+
|
602
|
+
const addExecutionKey = (): void => {
|
603
|
+
executionContextState.setNewExecutionContextModal(true);
|
604
|
+
};
|
605
|
+
|
606
|
+
return (
|
607
|
+
<div className="service-execution-editor__execution">
|
608
|
+
<ResizablePanelGroup orientation="vertical">
|
609
|
+
<ResizablePanel size={300} minSize={200}>
|
610
|
+
<div className="service-multi-execution-editor__panel">
|
611
|
+
<PanelHeader>
|
612
|
+
<div className="panel__header__title">
|
613
|
+
<div className="panel__header__title__content">
|
614
|
+
Execution Contexts
|
615
|
+
</div>
|
616
|
+
</div>
|
617
|
+
<PanelHeaderActions>
|
618
|
+
<PanelHeaderActionItem
|
619
|
+
disabled={dataSpaceState.isReadOnly}
|
620
|
+
onClick={addExecutionKey}
|
621
|
+
title="Add an execution context"
|
622
|
+
>
|
623
|
+
<PlusIcon />
|
624
|
+
</PanelHeaderActionItem>
|
625
|
+
</PanelHeaderActions>
|
626
|
+
</PanelHeader>
|
627
|
+
|
628
|
+
{executionContextState.executionContexts.map((executionContext) => (
|
629
|
+
<ExecutionContextItem
|
630
|
+
key={executionContext.name}
|
631
|
+
dataSpaceExecutionContextState={executionContextState}
|
632
|
+
dataSpaceExecutionContext={executionContext}
|
633
|
+
isReadOnly={dataSpaceState.isReadOnly}
|
634
|
+
/>
|
635
|
+
))}
|
636
|
+
{!executionContextState.executionContexts.length && (
|
637
|
+
<BlankPanelPlaceholder
|
638
|
+
text="Add an execution context"
|
639
|
+
onClick={addExecutionKey}
|
640
|
+
clickActionType="add"
|
641
|
+
tooltipText="Click to add an execution context"
|
642
|
+
/>
|
643
|
+
)}
|
644
|
+
</div>
|
645
|
+
{executionContextState.newExecutionContextModal && (
|
646
|
+
<NewExecutionContextModal
|
647
|
+
executionState={executionContextState}
|
648
|
+
isReadOnly={dataSpaceState.isReadOnly}
|
649
|
+
/>
|
650
|
+
)}
|
651
|
+
{executionContextState.executionContextToRename && (
|
652
|
+
<RenameModal
|
653
|
+
val={executionContextState.executionContextToRename.name}
|
654
|
+
isReadOnly={dataSpaceState.isReadOnly}
|
655
|
+
showModal={true}
|
656
|
+
closeModal={(): void =>
|
657
|
+
executionContextState.setExecutionContextToRename(undefined)
|
658
|
+
}
|
659
|
+
setValue={(val: string): void =>
|
660
|
+
executionContextState.renameExecutionContext(
|
661
|
+
guaranteeNonNullable(
|
662
|
+
executionContextState.executionContextToRename,
|
663
|
+
),
|
664
|
+
val,
|
665
|
+
)
|
666
|
+
}
|
667
|
+
executionContext={executionContextState.executionContextToRename}
|
668
|
+
/>
|
669
|
+
)}
|
670
|
+
</ResizablePanel>
|
671
|
+
<ResizablePanelSplitter>
|
672
|
+
<ResizablePanelSplitterLine color="var(--color-dark-grey-200)" />
|
673
|
+
</ResizablePanelSplitter>
|
674
|
+
<ResizablePanel minSize={56}>
|
675
|
+
{executionContextState.selectedExecutionContext ? (
|
676
|
+
<DataSpaceExecutionContextConfigurationEditor
|
677
|
+
executionContextState={executionContextState}
|
678
|
+
executionContext={executionContextState.selectedExecutionContext}
|
679
|
+
/>
|
680
|
+
) : (
|
681
|
+
<BlankPanelPlaceholder
|
682
|
+
text="Add an execution context"
|
683
|
+
onClick={addExecutionKey}
|
684
|
+
clickActionType="add"
|
685
|
+
tooltipText="Click to add an execution context"
|
686
|
+
/>
|
687
|
+
)}
|
688
|
+
</ResizablePanel>
|
689
|
+
</ResizablePanelGroup>
|
690
|
+
</div>
|
691
|
+
);
|
692
|
+
});
|