@finos/legend-application-studio 13.1.2 → 15.0.1
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/EditorComponentTestUtils.d.ts +3 -13
- package/lib/components/EditorComponentTestUtils.d.ts.map +1 -1
- package/lib/components/EditorComponentTestUtils.js +3 -22
- package/lib/components/EditorComponentTestUtils.js.map +1 -1
- package/lib/components/editor/edit-panel/EditPanel.js +4 -4
- package/lib/components/editor/edit-panel/EditPanel.js.map +1 -1
- package/lib/components/editor/edit-panel/{ModelLoader.d.ts → ModelImporter.d.ts} +2 -2
- package/lib/components/editor/edit-panel/ModelImporter.d.ts.map +1 -0
- package/lib/components/editor/edit-panel/ModelImporter.js +127 -0
- package/lib/components/editor/edit-panel/ModelImporter.js.map +1 -0
- package/lib/components/editor/edit-panel/external-format-editor/SchemaSetElementEditor.d.ts +7 -0
- package/lib/components/editor/edit-panel/external-format-editor/SchemaSetElementEditor.d.ts.map +1 -1
- package/lib/components/editor/edit-panel/external-format-editor/SchemaSetElementEditor.js +18 -42
- package/lib/components/editor/edit-panel/external-format-editor/SchemaSetElementEditor.js.map +1 -1
- package/lib/components/editor/edit-panel/external-format-editor/SchemaSetModelGenerationEditor.d.ts +24 -0
- package/lib/components/editor/edit-panel/external-format-editor/SchemaSetModelGenerationEditor.d.ts.map +1 -0
- package/lib/components/editor/edit-panel/external-format-editor/SchemaSetModelGenerationEditor.js +75 -0
- package/lib/components/editor/edit-panel/external-format-editor/SchemaSetModelGenerationEditor.js.map +1 -0
- package/lib/components/editor/edit-panel/mapping-editor/NewMappingElementModal.d.ts.map +1 -1
- package/lib/components/editor/edit-panel/mapping-editor/NewMappingElementModal.js +1 -2
- package/lib/components/editor/edit-panel/mapping-editor/NewMappingElementModal.js.map +1 -1
- package/lib/components/editor/side-bar/Explorer.js +4 -4
- package/lib/components/editor/side-bar/Explorer.js.map +1 -1
- package/lib/index.css +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/package.json +7 -7
- package/lib/stores/EditorGraphState.d.ts +1 -1
- package/lib/stores/EditorGraphState.d.ts.map +1 -1
- package/lib/stores/EditorGraphState.js +10 -10
- package/lib/stores/EditorGraphState.js.map +1 -1
- package/lib/stores/EditorStore.d.ts +3 -3
- package/lib/stores/EditorStore.d.ts.map +1 -1
- package/lib/stores/EditorStore.js +6 -8
- package/lib/stores/EditorStore.js.map +1 -1
- package/lib/stores/LegendStudioApplicationPlugin.d.ts +7 -5
- package/lib/stores/LegendStudioApplicationPlugin.d.ts.map +1 -1
- package/lib/stores/LegendStudioApplicationPlugin.js.map +1 -1
- package/lib/stores/editor-state/ExternalFormatState.d.ts +3 -2
- package/lib/stores/editor-state/ExternalFormatState.d.ts.map +1 -1
- package/lib/stores/editor-state/ExternalFormatState.js +11 -8
- package/lib/stores/editor-state/ExternalFormatState.js.map +1 -1
- package/lib/stores/editor-state/ModelImporterState.d.ts +100 -0
- package/lib/stores/editor-state/ModelImporterState.d.ts.map +1 -0
- package/lib/stores/editor-state/ModelImporterState.js +358 -0
- package/lib/stores/editor-state/ModelImporterState.js.map +1 -0
- package/lib/stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.d.ts +35 -12
- package/lib/stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.d.ts.map +1 -1
- package/lib/stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.js +141 -34
- package/lib/stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.js.map +1 -1
- package/lib/stores/editor-state/entity-diff-editor-state/EntityChangeConflictEditorState.js +1 -1
- package/lib/stores/editor-state/entity-diff-editor-state/EntityChangeConflictEditorState.js.map +1 -1
- package/lib/stores/graphModifier/DSLExternalFormat_GraphModifierHelper.d.ts +1 -0
- package/lib/stores/graphModifier/DSLExternalFormat_GraphModifierHelper.d.ts.map +1 -1
- package/lib/stores/graphModifier/DSLExternalFormat_GraphModifierHelper.js +3 -0
- package/lib/stores/graphModifier/DSLExternalFormat_GraphModifierHelper.js.map +1 -1
- package/package.json +15 -15
- package/src/components/EditorComponentTestUtils.tsx +2 -29
- package/src/components/editor/edit-panel/EditPanel.tsx +4 -4
- package/src/components/editor/edit-panel/ModelImporter.tsx +372 -0
- package/src/components/editor/edit-panel/external-format-editor/SchemaSetElementEditor.tsx +47 -163
- package/src/components/editor/edit-panel/external-format-editor/SchemaSetModelGenerationEditor.tsx +226 -0
- package/src/components/editor/edit-panel/mapping-editor/NewMappingElementModal.tsx +1 -2
- package/src/components/editor/side-bar/Explorer.tsx +8 -8
- package/src/index.ts +1 -0
- package/src/stores/EditorGraphState.ts +13 -12
- package/src/stores/EditorStore.ts +7 -9
- package/src/stores/LegendStudioApplicationPlugin.ts +16 -7
- package/src/stores/editor-state/ExternalFormatState.ts +15 -12
- package/src/stores/editor-state/ModelImporterState.ts +514 -0
- package/src/stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.ts +203 -46
- package/src/stores/editor-state/entity-diff-editor-state/EntityChangeConflictEditorState.ts +1 -1
- package/src/stores/graphModifier/DSLExternalFormat_GraphModifierHelper.ts +5 -0
- package/tsconfig.json +3 -2
- package/lib/components/editor/edit-panel/ModelLoader.d.ts.map +0 -1
- package/lib/components/editor/edit-panel/ModelLoader.js +0 -95
- package/lib/components/editor/edit-panel/ModelLoader.js.map +0 -1
- package/lib/stores/editor-state/ModelLoaderState.d.ts +0 -52
- package/lib/stores/editor-state/ModelLoaderState.d.ts.map +0 -1
- package/lib/stores/editor-state/ModelLoaderState.js +0 -199
- package/lib/stores/editor-state/ModelLoaderState.js.map +0 -1
- package/src/components/editor/edit-panel/ModelLoader.tsx +0 -259
- package/src/stores/editor-state/ModelLoaderState.ts +0 -280
|
@@ -0,0 +1,372 @@
|
|
|
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 { observer } from 'mobx-react-lite';
|
|
18
|
+
import {
|
|
19
|
+
type ModelImporterEditorState,
|
|
20
|
+
ModelImporterState,
|
|
21
|
+
ExtensionModelImporterEditorState,
|
|
22
|
+
MODEL_IMPORT_NATIVE_INPUT_TYPE,
|
|
23
|
+
NativeModelImporterEditorState,
|
|
24
|
+
ExternalFormatModelImporterState,
|
|
25
|
+
} from '../../../stores/editor-state/ModelImporterState.js';
|
|
26
|
+
import { prettyCONSTName } from '@finos/legend-shared';
|
|
27
|
+
import {
|
|
28
|
+
DropdownMenu,
|
|
29
|
+
MenuContent,
|
|
30
|
+
MenuContentItem,
|
|
31
|
+
CaretDownIcon,
|
|
32
|
+
CheckSquareIcon,
|
|
33
|
+
TruckLoadingIcon,
|
|
34
|
+
EmptySquareIcon,
|
|
35
|
+
BlankPanelContent,
|
|
36
|
+
PanelLoadingIndicator,
|
|
37
|
+
clsx,
|
|
38
|
+
} from '@finos/legend-art';
|
|
39
|
+
import { flowResult } from 'mobx';
|
|
40
|
+
import { useEditorStore } from '../EditorStoreProvider.js';
|
|
41
|
+
import {
|
|
42
|
+
ActionAlertType,
|
|
43
|
+
ActionAlertActionType,
|
|
44
|
+
useApplicationStore,
|
|
45
|
+
EDITOR_LANGUAGE,
|
|
46
|
+
useApplicationNavigationContext,
|
|
47
|
+
} from '@finos/legend-application';
|
|
48
|
+
import { StudioTextInputEditor } from '../../shared/StudioTextInputEditor.js';
|
|
49
|
+
import type { ModelImporterExtensionConfiguration } from '../../../stores/LegendStudioApplicationPlugin.js';
|
|
50
|
+
import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../stores/LegendStudioApplicationNavigationContext.js';
|
|
51
|
+
import { SCHEMA_SET_TAB_TYPE } from '../../../stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.js';
|
|
52
|
+
import { SchemaSetModelGenerationEditor } from './external-format-editor/SchemaSetModelGenerationEditor.js';
|
|
53
|
+
import { SchemaSetGeneralEditor } from './external-format-editor/SchemaSetElementEditor.js';
|
|
54
|
+
|
|
55
|
+
const ExternalFormatModelImporterEditor = observer(
|
|
56
|
+
(props: { externalFormatState: ExternalFormatModelImporterState }) => {
|
|
57
|
+
const { externalFormatState } = props;
|
|
58
|
+
const schemaSetEditorState = externalFormatState.schemaSetEditorState;
|
|
59
|
+
const editorStore = schemaSetEditorState.editorStore;
|
|
60
|
+
const schemaSet = schemaSetEditorState.schemaSet;
|
|
61
|
+
const currentTab = schemaSetEditorState.selectedTab;
|
|
62
|
+
const isFetchingDescriptions =
|
|
63
|
+
editorStore.graphState.graphGenerationState.externalFormatState
|
|
64
|
+
.fetchingDescriptionsState.isInProgress;
|
|
65
|
+
const changeTab =
|
|
66
|
+
(tab: SCHEMA_SET_TAB_TYPE): (() => void) =>
|
|
67
|
+
(): void =>
|
|
68
|
+
schemaSetEditorState.setSelectedTab(tab);
|
|
69
|
+
const renderMainEditPanel = (): React.ReactNode => {
|
|
70
|
+
if (isFetchingDescriptions) {
|
|
71
|
+
return (
|
|
72
|
+
<BlankPanelContent>Fetching format descriptions</BlankPanelContent>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
if (currentTab === SCHEMA_SET_TAB_TYPE.SCHEMAS) {
|
|
76
|
+
return (
|
|
77
|
+
<SchemaSetGeneralEditor
|
|
78
|
+
schemaSetEditorState={schemaSetEditorState}
|
|
79
|
+
isReadOnly={false}
|
|
80
|
+
/>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
const supportsModelGeneraiton =
|
|
84
|
+
schemaSetEditorState.schemaSetModelGenerationState.description
|
|
85
|
+
?.supportsModelGeneration;
|
|
86
|
+
return supportsModelGeneraiton ? (
|
|
87
|
+
<SchemaSetModelGenerationEditor
|
|
88
|
+
modelGenerationState={
|
|
89
|
+
schemaSetEditorState.schemaSetModelGenerationState
|
|
90
|
+
}
|
|
91
|
+
isReadOnly={false}
|
|
92
|
+
/>
|
|
93
|
+
) : (
|
|
94
|
+
<BlankPanelContent>
|
|
95
|
+
Format {schemaSet.format} does not support Model Generation
|
|
96
|
+
</BlankPanelContent>
|
|
97
|
+
);
|
|
98
|
+
};
|
|
99
|
+
return (
|
|
100
|
+
<div className="panel schema-set-panel">
|
|
101
|
+
<div className="panel__content model-loader">
|
|
102
|
+
<PanelLoadingIndicator isLoading={isFetchingDescriptions} />
|
|
103
|
+
<div className="panel__header">
|
|
104
|
+
<div className="uml-element-editor__tabs">
|
|
105
|
+
{Object.values(SCHEMA_SET_TAB_TYPE).map((tab) => (
|
|
106
|
+
<div
|
|
107
|
+
key={tab}
|
|
108
|
+
onClick={changeTab(tab)}
|
|
109
|
+
className={clsx('relational-connection-editor__tab', {
|
|
110
|
+
'relational-connection-editor__tab--active':
|
|
111
|
+
tab === currentTab,
|
|
112
|
+
})}
|
|
113
|
+
>
|
|
114
|
+
{prettyCONSTName(tab)}
|
|
115
|
+
</div>
|
|
116
|
+
))}
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<div className="panel__content file-generation-editor__content">
|
|
121
|
+
{currentTab === SCHEMA_SET_TAB_TYPE.SCHEMAS && (
|
|
122
|
+
<SchemaSetGeneralEditor
|
|
123
|
+
schemaSetEditorState={schemaSetEditorState}
|
|
124
|
+
isReadOnly={false}
|
|
125
|
+
/>
|
|
126
|
+
)}
|
|
127
|
+
|
|
128
|
+
{currentTab === SCHEMA_SET_TAB_TYPE.GENERATE_MODEL &&
|
|
129
|
+
renderMainEditPanel()}
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
);
|
|
134
|
+
},
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
export const ModelImporter = observer(() => {
|
|
138
|
+
const editorStore = useEditorStore();
|
|
139
|
+
const applicationStore = useApplicationStore();
|
|
140
|
+
const modelImporterState =
|
|
141
|
+
editorStore.getCurrentEditorState(ModelImporterState);
|
|
142
|
+
const nativeInputTypes = Object.values(MODEL_IMPORT_NATIVE_INPUT_TYPE);
|
|
143
|
+
const extraModelImporterExtensionsConfigs =
|
|
144
|
+
modelImporterState.extensionConfigs;
|
|
145
|
+
const externalFormatDescriptions =
|
|
146
|
+
modelImporterState.editorStore.graphState.graphGenerationState
|
|
147
|
+
.externalFormatState.externalFormatDescriptionsWithModelGenerationSupport;
|
|
148
|
+
// replace flag
|
|
149
|
+
const replace = modelImporterState.replace;
|
|
150
|
+
const toggleReplace = (): void => modelImporterState.setReplaceFlag(!replace);
|
|
151
|
+
const label = modelImporterState.modelImportEditorState.label;
|
|
152
|
+
const modelImportEditorState = modelImporterState.modelImportEditorState;
|
|
153
|
+
const loadModel = (): void => {
|
|
154
|
+
if (editorStore.hasUnpushedChanges) {
|
|
155
|
+
editorStore.setActionAlertInfo({
|
|
156
|
+
message: 'You have unpushed changes',
|
|
157
|
+
prompt:
|
|
158
|
+
'This action will discard these changes and refresh the application',
|
|
159
|
+
type: ActionAlertType.CAUTION,
|
|
160
|
+
onEnter: (): void => editorStore.setBlockGlobalHotkeys(true),
|
|
161
|
+
onClose: (): void => editorStore.setBlockGlobalHotkeys(false),
|
|
162
|
+
actions: [
|
|
163
|
+
{
|
|
164
|
+
label: 'Proceed to load model',
|
|
165
|
+
type: ActionAlertActionType.PROCEED_WITH_CAUTION,
|
|
166
|
+
handler: (): void => {
|
|
167
|
+
editorStore.setIgnoreNavigationBlocking(true);
|
|
168
|
+
flowResult(
|
|
169
|
+
modelImporterState.modelImportEditorState.loadModel(),
|
|
170
|
+
).catch(applicationStore.alertUnhandledError);
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
label: 'Abort',
|
|
175
|
+
type: ActionAlertActionType.PROCEED,
|
|
176
|
+
default: true,
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
});
|
|
180
|
+
} else {
|
|
181
|
+
flowResult(modelImporterState.modelImportEditorState.loadModel()).catch(
|
|
182
|
+
applicationStore.alertUnhandledError,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
useApplicationNavigationContext(
|
|
187
|
+
LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.MODEL_LOADER,
|
|
188
|
+
);
|
|
189
|
+
const renderExtraActions = (): React.ReactNode => {
|
|
190
|
+
if (modelImportEditorState instanceof NativeModelImporterEditorState) {
|
|
191
|
+
// actions
|
|
192
|
+
const loadCurrentProjectEntities = applicationStore.guardUnhandledError(
|
|
193
|
+
() => flowResult(modelImportEditorState.loadCurrentProjectEntities()),
|
|
194
|
+
);
|
|
195
|
+
return (
|
|
196
|
+
<button
|
|
197
|
+
className="model-loader__header__configs__load-project-entities-btn"
|
|
198
|
+
tabIndex={-1}
|
|
199
|
+
onClick={loadCurrentProjectEntities}
|
|
200
|
+
title="Load current project entities"
|
|
201
|
+
>
|
|
202
|
+
<TruckLoadingIcon />
|
|
203
|
+
</button>
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
return null;
|
|
207
|
+
};
|
|
208
|
+
const renderModelImporterEditor = (): React.ReactNode => {
|
|
209
|
+
if (modelImportEditorState instanceof ExtensionModelImporterEditorState) {
|
|
210
|
+
return modelImportEditorState.config.renderer(
|
|
211
|
+
modelImportEditorState.rendererState,
|
|
212
|
+
);
|
|
213
|
+
} else if (
|
|
214
|
+
modelImportEditorState instanceof NativeModelImporterEditorState
|
|
215
|
+
) {
|
|
216
|
+
const updateModel = (val: string): void =>
|
|
217
|
+
modelImportEditorState.setModelText(val);
|
|
218
|
+
return (
|
|
219
|
+
<div className="panel__content model-loader__editor">
|
|
220
|
+
<StudioTextInputEditor
|
|
221
|
+
language={
|
|
222
|
+
modelImportEditorState.nativeType ===
|
|
223
|
+
MODEL_IMPORT_NATIVE_INPUT_TYPE.PURE_GRAMMAR
|
|
224
|
+
? EDITOR_LANGUAGE.PURE
|
|
225
|
+
: EDITOR_LANGUAGE.JSON
|
|
226
|
+
}
|
|
227
|
+
inputValue={modelImportEditorState.modelText}
|
|
228
|
+
updateInput={updateModel}
|
|
229
|
+
showMiniMap={true}
|
|
230
|
+
/>
|
|
231
|
+
</div>
|
|
232
|
+
);
|
|
233
|
+
} else if (
|
|
234
|
+
modelImportEditorState instanceof ExternalFormatModelImporterState
|
|
235
|
+
) {
|
|
236
|
+
return (
|
|
237
|
+
<ExternalFormatModelImporterEditor
|
|
238
|
+
externalFormatState={modelImportEditorState}
|
|
239
|
+
/>
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
return null;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
return (
|
|
246
|
+
<div className="panel model-loader">
|
|
247
|
+
<div className="panel__header model-loader__header">
|
|
248
|
+
<div className="model-loader__header__configs">
|
|
249
|
+
<DropdownMenu
|
|
250
|
+
content={
|
|
251
|
+
<MenuContent className="model-loader__header__configs__type__menu">
|
|
252
|
+
<div className="model-loader__header__configs__type-option__group model-loader__header__configs__type-option__group--native">
|
|
253
|
+
<div className="model-loader__header__configs__type-option__group__name">
|
|
254
|
+
native
|
|
255
|
+
</div>
|
|
256
|
+
<div className="model-loader__header__configs__type-option__group__options">
|
|
257
|
+
{nativeInputTypes.map((inputType) => (
|
|
258
|
+
<MenuContentItem
|
|
259
|
+
key={inputType}
|
|
260
|
+
className="model-loader__header__configs__type-option__group__option"
|
|
261
|
+
onClick={(): ModelImporterEditorState =>
|
|
262
|
+
modelImporterState.setNativeImportType(inputType)
|
|
263
|
+
}
|
|
264
|
+
>
|
|
265
|
+
{prettyCONSTName(inputType)}
|
|
266
|
+
</MenuContentItem>
|
|
267
|
+
))}
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
{Boolean(externalFormatDescriptions.length) && (
|
|
271
|
+
<>
|
|
272
|
+
<div className="model-loader__header__configs__type-option__group__separator" />
|
|
273
|
+
<div className="model-loader__header__configs__type-option__group model-loader__header__configs__type-option__group--external">
|
|
274
|
+
<div className="model-loader__header__configs__type-option__group__name">
|
|
275
|
+
external
|
|
276
|
+
</div>
|
|
277
|
+
<div className="model-loader__header__configs__type-option__group__options">
|
|
278
|
+
{externalFormatDescriptions.map((inputType) => (
|
|
279
|
+
<MenuContentItem
|
|
280
|
+
key={inputType.name}
|
|
281
|
+
className="model-loader__header__configs__type-option__group__option"
|
|
282
|
+
onClick={() =>
|
|
283
|
+
modelImporterState.setExternalFormatImportFormat(
|
|
284
|
+
inputType,
|
|
285
|
+
)
|
|
286
|
+
}
|
|
287
|
+
>
|
|
288
|
+
{inputType.name}
|
|
289
|
+
</MenuContentItem>
|
|
290
|
+
))}
|
|
291
|
+
</div>
|
|
292
|
+
</div>
|
|
293
|
+
</>
|
|
294
|
+
)}
|
|
295
|
+
{Boolean(extraModelImporterExtensionsConfigs.length > 0) && (
|
|
296
|
+
<>
|
|
297
|
+
<div className="model-loader__header__configs__type-option__group__separator" />
|
|
298
|
+
<div className="model-loader__header__configs__type-option__group model-loader__header__configs__type-option__group--extension">
|
|
299
|
+
<div className="model-loader__header__configs__type-option__group__name">
|
|
300
|
+
extensions
|
|
301
|
+
</div>
|
|
302
|
+
<div className="model-loader__header__configs__type-option__group__options">
|
|
303
|
+
{extraModelImporterExtensionsConfigs.map(
|
|
304
|
+
(config: ModelImporterExtensionConfiguration) => (
|
|
305
|
+
<MenuContentItem
|
|
306
|
+
key={config.key}
|
|
307
|
+
className="model-loader__header__configs__type-option__group__option"
|
|
308
|
+
onClick={() =>
|
|
309
|
+
modelImporterState.setModelImporterExtension(
|
|
310
|
+
config,
|
|
311
|
+
)
|
|
312
|
+
}
|
|
313
|
+
>
|
|
314
|
+
{config.label ?? prettyCONSTName(config.key)}
|
|
315
|
+
</MenuContentItem>
|
|
316
|
+
),
|
|
317
|
+
)}
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
</>
|
|
321
|
+
)}
|
|
322
|
+
</MenuContent>
|
|
323
|
+
}
|
|
324
|
+
menuProps={{
|
|
325
|
+
anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
|
|
326
|
+
transformOrigin: { vertical: 'top', horizontal: 'right' },
|
|
327
|
+
}}
|
|
328
|
+
>
|
|
329
|
+
<div className="model-loader__header__configs__type">
|
|
330
|
+
<div className="model-loader__header__configs__type__label">
|
|
331
|
+
{prettyCONSTName(label)}
|
|
332
|
+
</div>
|
|
333
|
+
<div className="model-loader__header__configs__type__icon">
|
|
334
|
+
<CaretDownIcon />
|
|
335
|
+
</div>
|
|
336
|
+
</div>
|
|
337
|
+
</DropdownMenu>
|
|
338
|
+
{modelImportEditorState.allowHardReplace && (
|
|
339
|
+
<div
|
|
340
|
+
className="model-loader__header__configs__edit-mode"
|
|
341
|
+
onClick={toggleReplace}
|
|
342
|
+
>
|
|
343
|
+
<div className="model-loader__header__configs__edit-mode__icon">
|
|
344
|
+
{replace ? <CheckSquareIcon /> : <EmptySquareIcon />}
|
|
345
|
+
</div>
|
|
346
|
+
<div className="model-loader__header__configs__edit-mode__label">
|
|
347
|
+
replace
|
|
348
|
+
</div>
|
|
349
|
+
</div>
|
|
350
|
+
)}
|
|
351
|
+
{renderExtraActions()}
|
|
352
|
+
</div>
|
|
353
|
+
<div className="model-loader__header__action">
|
|
354
|
+
<button
|
|
355
|
+
className="btn--dark model-loader__header__load-btn"
|
|
356
|
+
onClick={loadModel}
|
|
357
|
+
disabled={
|
|
358
|
+
modelImportEditorState.loadModelActionState.isInProgress ||
|
|
359
|
+
modelImportEditorState.isLoadingDisabled
|
|
360
|
+
}
|
|
361
|
+
tabIndex={-1}
|
|
362
|
+
title="Load model"
|
|
363
|
+
>
|
|
364
|
+
Load
|
|
365
|
+
</button>
|
|
366
|
+
</div>
|
|
367
|
+
</div>
|
|
368
|
+
|
|
369
|
+
{renderModelImporterEditor()}
|
|
370
|
+
</div>
|
|
371
|
+
);
|
|
372
|
+
});
|
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
ResizablePanelSplitterLine,
|
|
25
25
|
LockIcon,
|
|
26
26
|
PlusIcon,
|
|
27
|
-
RefreshIcon,
|
|
28
27
|
PanelLoadingIndicator,
|
|
29
28
|
UploadIcon,
|
|
30
29
|
Dialog,
|
|
@@ -33,25 +32,17 @@ import {
|
|
|
33
32
|
MenuContent,
|
|
34
33
|
MenuContentItem,
|
|
35
34
|
} from '@finos/legend-art';
|
|
36
|
-
import {
|
|
37
|
-
type GenerationProperty,
|
|
38
|
-
ExternalFormatSchema as Schema,
|
|
39
|
-
} from '@finos/legend-graph';
|
|
35
|
+
import { ExternalFormatSchema as Schema } from '@finos/legend-graph';
|
|
40
36
|
import { flowResult } from 'mobx';
|
|
41
|
-
import { useMemo } from 'react';
|
|
42
37
|
import {
|
|
43
38
|
SchemaSetEditorState,
|
|
39
|
+
type InnerSchemaSetEditorState,
|
|
44
40
|
SCHEMA_SET_TAB_TYPE,
|
|
45
41
|
} from '../../../../stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.js';
|
|
46
42
|
import { EDITOR_LANGUAGE } from '@finos/legend-application';
|
|
47
43
|
import { StudioTextInputEditor } from '../../../shared/StudioTextInputEditor.js';
|
|
48
44
|
import { getEditorLanguageFromFormat } from '../../../../stores/editor-state/FileGenerationViewerState.js';
|
|
49
|
-
import {
|
|
50
|
-
debounce,
|
|
51
|
-
guaranteeNonNullable,
|
|
52
|
-
prettyCONSTName,
|
|
53
|
-
} from '@finos/legend-shared';
|
|
54
|
-
import { GenerationPropertyEditor } from '../element-generation-editor/FileGenerationEditor.js';
|
|
45
|
+
import { guaranteeNonNullable, prettyCONSTName } from '@finos/legend-shared';
|
|
55
46
|
import { useEditorStore } from '../../EditorStoreProvider.js';
|
|
56
47
|
import {
|
|
57
48
|
externalFormat_schemaSet_addSchema,
|
|
@@ -60,9 +51,12 @@ import {
|
|
|
60
51
|
externalFormat_schema_setId,
|
|
61
52
|
externalFormat_schema_setLocation,
|
|
62
53
|
} from '../../../../stores/graphModifier/DSLExternalFormat_GraphModifierHelper.js';
|
|
54
|
+
import { SchemaSetModelGenerationEditor } from './SchemaSetModelGenerationEditor.js';
|
|
63
55
|
|
|
64
56
|
const SchemaLoader = observer(
|
|
65
|
-
(props: {
|
|
57
|
+
(props: {
|
|
58
|
+
schemaSetEditorState: InnerSchemaSetEditorState | SchemaSetEditorState;
|
|
59
|
+
}) => {
|
|
66
60
|
const { schemaSetEditorState } = props;
|
|
67
61
|
const importState = schemaSetEditorState.importSchemaContentState;
|
|
68
62
|
const onClose = (): void => importState.closeModal();
|
|
@@ -199,19 +193,23 @@ const SchemaBasicEditor = observer(
|
|
|
199
193
|
},
|
|
200
194
|
);
|
|
201
195
|
|
|
202
|
-
const SchemaSetGeneralEditor = observer(
|
|
203
|
-
(props: {
|
|
204
|
-
|
|
196
|
+
export const SchemaSetGeneralEditor = observer(
|
|
197
|
+
(props: {
|
|
198
|
+
schemaSetEditorState: InnerSchemaSetEditorState | SchemaSetEditorState;
|
|
199
|
+
isReadOnly: boolean;
|
|
200
|
+
}) => {
|
|
201
|
+
const { schemaSetEditorState, isReadOnly } = props;
|
|
205
202
|
const schemaSet = schemaSetEditorState.schemaSet;
|
|
206
203
|
const applicationStore = schemaSetEditorState.editorStore.applicationStore;
|
|
207
204
|
const importSchemaContentState =
|
|
208
205
|
schemaSetEditorState.importSchemaContentState;
|
|
209
206
|
const currentSchema = schemaSetEditorState.currentSchema;
|
|
210
|
-
const isReadOnly = schemaSetEditorState.isReadOnly;
|
|
211
207
|
const description =
|
|
212
208
|
schemaSetEditorState.schemaSetModelGenerationState.description;
|
|
213
209
|
// TEMPROARY engine api should return `fileformat`.
|
|
214
|
-
const language =
|
|
210
|
+
const language = description
|
|
211
|
+
? getEditorLanguageFromFormat(description.name)
|
|
212
|
+
: EDITOR_LANGUAGE.TEXT;
|
|
215
213
|
const changeState =
|
|
216
214
|
(schema: Schema): (() => void) =>
|
|
217
215
|
(): void => {
|
|
@@ -246,7 +244,10 @@ const SchemaSetGeneralEditor = observer(
|
|
|
246
244
|
}
|
|
247
245
|
};
|
|
248
246
|
const validateSchema = (): void => {
|
|
249
|
-
if (
|
|
247
|
+
if (
|
|
248
|
+
currentSchema &&
|
|
249
|
+
schemaSetEditorState instanceof SchemaSetEditorState
|
|
250
|
+
) {
|
|
250
251
|
flowResult(schemaSetEditorState.validateSchema(currentSchema)).catch(
|
|
251
252
|
applicationStore.alertUnhandledError,
|
|
252
253
|
);
|
|
@@ -332,15 +333,17 @@ const SchemaSetGeneralEditor = observer(
|
|
|
332
333
|
</div>
|
|
333
334
|
</div>
|
|
334
335
|
<div className="panel__header__actions">
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
336
|
+
{schemaSetEditorState instanceof SchemaSetEditorState && (
|
|
337
|
+
<button
|
|
338
|
+
className="btn--dark model-loader__header__load-btn"
|
|
339
|
+
onClick={validateSchema}
|
|
340
|
+
disabled={!currentSchema}
|
|
341
|
+
tabIndex={-1}
|
|
342
|
+
title="Validate Schema"
|
|
343
|
+
>
|
|
344
|
+
Validate
|
|
345
|
+
</button>
|
|
346
|
+
)}
|
|
344
347
|
</div>
|
|
345
348
|
</div>
|
|
346
349
|
<div className="schema-set-panel__content">
|
|
@@ -366,133 +369,6 @@ const SchemaSetGeneralEditor = observer(
|
|
|
366
369
|
},
|
|
367
370
|
);
|
|
368
371
|
|
|
369
|
-
const SchemaSetModelGenerationEditor = observer(
|
|
370
|
-
(props: { schemaSetEditorState: SchemaSetEditorState }) => {
|
|
371
|
-
const { schemaSetEditorState } = props;
|
|
372
|
-
const applicationStore = schemaSetEditorState.editorStore.applicationStore;
|
|
373
|
-
const schemaSet = schemaSetEditorState.schemaSet;
|
|
374
|
-
const modelGenerationState =
|
|
375
|
-
schemaSetEditorState.schemaSetModelGenerationState;
|
|
376
|
-
const description = modelGenerationState.description;
|
|
377
|
-
const properties = description.modelGenerationProperties;
|
|
378
|
-
const isReadOnly = schemaSetEditorState.isReadOnly;
|
|
379
|
-
const debouncedRegenerate = useMemo(
|
|
380
|
-
() =>
|
|
381
|
-
debounce(() => flowResult(modelGenerationState.generateModel()), 500),
|
|
382
|
-
[modelGenerationState],
|
|
383
|
-
);
|
|
384
|
-
const update = (
|
|
385
|
-
generationProperty: GenerationProperty,
|
|
386
|
-
newValue: object,
|
|
387
|
-
): void => {
|
|
388
|
-
debouncedRegenerate.cancel();
|
|
389
|
-
modelGenerationState.updateGenerationParameters(
|
|
390
|
-
generationProperty,
|
|
391
|
-
newValue,
|
|
392
|
-
);
|
|
393
|
-
debouncedRegenerate()?.catch(applicationStore.alertUnhandledError);
|
|
394
|
-
};
|
|
395
|
-
const regenerate = (): void => {
|
|
396
|
-
modelGenerationState.generateModel();
|
|
397
|
-
};
|
|
398
|
-
const getConfigValue = (name: string): unknown | undefined =>
|
|
399
|
-
modelGenerationState.getConfigValue(name);
|
|
400
|
-
|
|
401
|
-
const importGeneratedElements = (): void => {
|
|
402
|
-
modelGenerationState.importGrammar();
|
|
403
|
-
};
|
|
404
|
-
return (
|
|
405
|
-
<div className="panel__content file-generation-editor__content">
|
|
406
|
-
<ResizablePanelGroup orientation="vertical">
|
|
407
|
-
<ResizablePanel size={250} minSize={50}>
|
|
408
|
-
<div className="panel file-generation-editor__configuration">
|
|
409
|
-
<div className="panel__header">
|
|
410
|
-
<div className="panel__header__title">
|
|
411
|
-
<div className="panel__header__title__label">{`${schemaSet.format} configuration`}</div>
|
|
412
|
-
</div>
|
|
413
|
-
<div className="panel__header__actions">
|
|
414
|
-
<button
|
|
415
|
-
className="panel__header__action file-generation-editor__configuration__reset-btn"
|
|
416
|
-
tabIndex={-1}
|
|
417
|
-
disabled={isReadOnly || !properties.length}
|
|
418
|
-
onClick={regenerate}
|
|
419
|
-
title={'Reset to default configuration'}
|
|
420
|
-
>
|
|
421
|
-
<RefreshIcon />
|
|
422
|
-
</button>
|
|
423
|
-
</div>
|
|
424
|
-
</div>
|
|
425
|
-
<div className="panel__content">
|
|
426
|
-
<div className="file-generation-editor__configuration__content">
|
|
427
|
-
{modelGenerationState.modelGenerationProperties.map(
|
|
428
|
-
(abstractGenerationProperty) => (
|
|
429
|
-
<GenerationPropertyEditor
|
|
430
|
-
key={abstractGenerationProperty.name}
|
|
431
|
-
update={update}
|
|
432
|
-
isReadOnly={isReadOnly}
|
|
433
|
-
getConfigValue={getConfigValue}
|
|
434
|
-
property={abstractGenerationProperty}
|
|
435
|
-
/>
|
|
436
|
-
),
|
|
437
|
-
)}
|
|
438
|
-
</div>
|
|
439
|
-
</div>
|
|
440
|
-
</div>
|
|
441
|
-
</ResizablePanel>
|
|
442
|
-
<ResizablePanelSplitter>
|
|
443
|
-
<ResizablePanelSplitterLine color="var(--color-dark-grey-200)" />
|
|
444
|
-
</ResizablePanelSplitter>
|
|
445
|
-
<ResizablePanel>
|
|
446
|
-
<div className="panel generation-result-viewer__file">
|
|
447
|
-
<div className="panel__header">
|
|
448
|
-
<div className="panel__header__title">
|
|
449
|
-
<div className="panel__header__title__label">result</div>
|
|
450
|
-
</div>
|
|
451
|
-
<div className="panel__header__actions">
|
|
452
|
-
<button
|
|
453
|
-
className={clsx(
|
|
454
|
-
'panel__header__action generation-result-viewer__regenerate-btn',
|
|
455
|
-
{
|
|
456
|
-
' generation-result-viewer__regenerate-btn--loading':
|
|
457
|
-
modelGenerationState.isGenerating,
|
|
458
|
-
},
|
|
459
|
-
)}
|
|
460
|
-
tabIndex={-1}
|
|
461
|
-
disabled={modelGenerationState.isGenerating}
|
|
462
|
-
onClick={regenerate}
|
|
463
|
-
title={'Re-generate'}
|
|
464
|
-
>
|
|
465
|
-
<RefreshIcon />
|
|
466
|
-
</button>
|
|
467
|
-
<button
|
|
468
|
-
className="btn--dark model-loader__header__load-btn"
|
|
469
|
-
onClick={importGeneratedElements}
|
|
470
|
-
disabled={modelGenerationState.generationValue === ''}
|
|
471
|
-
tabIndex={-1}
|
|
472
|
-
title="Import generated elements"
|
|
473
|
-
>
|
|
474
|
-
Import
|
|
475
|
-
</button>
|
|
476
|
-
</div>
|
|
477
|
-
</div>
|
|
478
|
-
<div className="panel__content">
|
|
479
|
-
<PanelLoadingIndicator
|
|
480
|
-
isLoading={modelGenerationState.isGenerating}
|
|
481
|
-
/>
|
|
482
|
-
<StudioTextInputEditor
|
|
483
|
-
inputValue={modelGenerationState.generationValue}
|
|
484
|
-
isReadOnly={true}
|
|
485
|
-
language={EDITOR_LANGUAGE.PURE}
|
|
486
|
-
/>
|
|
487
|
-
</div>
|
|
488
|
-
</div>
|
|
489
|
-
</ResizablePanel>
|
|
490
|
-
</ResizablePanelGroup>
|
|
491
|
-
</div>
|
|
492
|
-
);
|
|
493
|
-
},
|
|
494
|
-
);
|
|
495
|
-
|
|
496
372
|
export const SchemaSetEditor = observer(() => {
|
|
497
373
|
const editorStore = useEditorStore();
|
|
498
374
|
const schemaSetEditorState =
|
|
@@ -513,17 +389,23 @@ export const SchemaSetEditor = observer(() => {
|
|
|
513
389
|
<BlankPanelContent>Fetching format descriptions</BlankPanelContent>
|
|
514
390
|
);
|
|
515
391
|
}
|
|
516
|
-
if (currentTab === SCHEMA_SET_TAB_TYPE.
|
|
392
|
+
if (currentTab === SCHEMA_SET_TAB_TYPE.SCHEMAS) {
|
|
517
393
|
return (
|
|
518
|
-
<SchemaSetGeneralEditor
|
|
394
|
+
<SchemaSetGeneralEditor
|
|
395
|
+
schemaSetEditorState={schemaSetEditorState}
|
|
396
|
+
isReadOnly={isReadOnly}
|
|
397
|
+
/>
|
|
519
398
|
);
|
|
520
399
|
}
|
|
521
400
|
const supportsModelGeneraiton =
|
|
522
401
|
schemaSetEditorState.schemaSetModelGenerationState.description
|
|
523
|
-
|
|
402
|
+
?.supportsModelGeneration;
|
|
524
403
|
return supportsModelGeneraiton ? (
|
|
525
404
|
<SchemaSetModelGenerationEditor
|
|
526
|
-
|
|
405
|
+
modelGenerationState={
|
|
406
|
+
schemaSetEditorState.schemaSetModelGenerationState
|
|
407
|
+
}
|
|
408
|
+
isReadOnly={isReadOnly}
|
|
527
409
|
/>
|
|
528
410
|
) : (
|
|
529
411
|
<BlankPanelContent>
|
|
@@ -531,11 +413,12 @@ export const SchemaSetEditor = observer(() => {
|
|
|
531
413
|
</BlankPanelContent>
|
|
532
414
|
);
|
|
533
415
|
};
|
|
416
|
+
|
|
534
417
|
return (
|
|
535
418
|
<div className="panel schema-set-panel">
|
|
536
419
|
<div className="schema-set-panel__header">
|
|
537
420
|
<div className="schema-set-panel__header__title">
|
|
538
|
-
{isReadOnly && (
|
|
421
|
+
{schemaSetEditorState.isReadOnly && (
|
|
539
422
|
<div className="schema-set-panel__header__lock">
|
|
540
423
|
<LockIcon />
|
|
541
424
|
</div>
|
|
@@ -544,7 +427,7 @@ export const SchemaSetEditor = observer(() => {
|
|
|
544
427
|
Schema Set
|
|
545
428
|
</div>
|
|
546
429
|
<div className="schema-set-panel__header__title__content">
|
|
547
|
-
{schemaSet.name}
|
|
430
|
+
{schemaSetEditorState.schemaSet.name}
|
|
548
431
|
</div>
|
|
549
432
|
</div>
|
|
550
433
|
</div>
|
|
@@ -568,13 +451,14 @@ export const SchemaSetEditor = observer(() => {
|
|
|
568
451
|
</div>
|
|
569
452
|
|
|
570
453
|
<div className="panel__content file-generation-editor__content">
|
|
571
|
-
{currentTab === SCHEMA_SET_TAB_TYPE.
|
|
454
|
+
{currentTab === SCHEMA_SET_TAB_TYPE.SCHEMAS && (
|
|
572
455
|
<SchemaSetGeneralEditor
|
|
573
456
|
schemaSetEditorState={schemaSetEditorState}
|
|
457
|
+
isReadOnly={isReadOnly}
|
|
574
458
|
/>
|
|
575
459
|
)}
|
|
576
460
|
|
|
577
|
-
{currentTab === SCHEMA_SET_TAB_TYPE.
|
|
461
|
+
{currentTab === SCHEMA_SET_TAB_TYPE.GENERATE_MODEL &&
|
|
578
462
|
renderMainEditPanel()}
|
|
579
463
|
</div>
|
|
580
464
|
</div>
|