@finos/legend-studio
Version:
153 lines • 17.2 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
* Copyright (c) 2020-present, Goldman Sachs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { observer } from 'mobx-react-lite';
import { clsx, ContextMenu, ResizablePanel, ResizablePanelGroup, ResizablePanelSplitter, ResizablePanelSplitterLine, LockIcon, PlusIcon, RefreshIcon, PanelLoadingIndicator, UploadIcon, Dialog, TimesIcon, BlankPanelContent, MenuContent, MenuContentItem, } from '@finos/legend-art';
import { ExternalFormatSchema as Schema, } from '@finos/legend-graph';
import { flowResult } from 'mobx';
import { useMemo } from 'react';
import { SchemaSetEditorState, SCHEMA_SET_TAB_TYPE, } from '../../../../stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.js';
import { EDITOR_LANGUAGE } from '@finos/legend-application';
import { StudioTextInputEditor } from '../../../shared/StudioTextInputEditor.js';
import { getEditorLanguageFromFormat } from '../../../../stores/editor-state/FileGenerationViewerState.js';
import { debounce, guaranteeNonNullable, prettyCONSTName, } from '@finos/legend-shared';
import { GenerationPropertyEditor } from '../element-generation-editor/FileGenerationEditor.js';
import { useEditorStore } from '../../EditorStoreProvider.js';
import { externalFormat_schemaSet_addSchema, externalFormat_schemaSet_deleteSchema, externalFormat_schema_setContent, externalFormat_schema_setId, externalFormat_schema_setLocation, } from '../../../../stores/graphModifier/DSLExternalFormat_GraphModifierHelper.js';
const SchemaLoader = observer((props) => {
const { schemaSetEditorState } = props;
const importState = schemaSetEditorState.importSchemaContentState;
const onClose = () => importState.closeModal();
const onChange = (event) => {
const fileList = event.target.files;
if (fileList) {
importState.setFiles(Array.from(fileList));
}
};
const importSchemas = () => {
if (importState.files) {
importState.importSchemas(importState.files);
}
};
return (_jsx(Dialog, { onClose: onClose, open: importState.importSchemaModal, TransitionProps: {
appear: false, // disable transition
}, children: _jsxs("div", { className: "modal modal--dark modal--scrollable patch-loader", children: [_jsx("div", { className: "modal__header", children: _jsx("div", { className: "modal__title", children: _jsx("div", { className: "modal__title__label", children: "Schema Content Loader" }) }) }), _jsxs("div", { className: "modal__body", children: [_jsx(PanelLoadingIndicator, { isLoading: importState.loadingSchemaContentState.isInProgress }), _jsx("div", { children: _jsx("input", { id: "upload-file", type: "file", name: "myFiles", onChange: onChange, multiple: true }) }), importState.files && (_jsxs("div", { className: "panel__content__form__section", children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Schema Files" }), _jsx("div", { className: "panel__content__form__section__list", children: _jsx("div", { className: "panel__content__form__section__list__items", children: importState.files.map((value) => (_jsxs("div", { className: "panel__content__form__section__list__item", children: [_jsx("div", { className: "panel__content__form__section__list__item__value", children: value.name }), _jsx("div", { className: "panel__content__form__section__list__item__actions", children: _jsx("button", { title: "Remove change", className: "panel__content__form__section__list__item__remove-btn", onClick: () => importState.removeFile(value), tabIndex: -1, children: _jsx(TimesIcon, {}) }) })] }, value.name))) }) })] }))] }), _jsx("div", { className: "modal__footer", children: _jsx("button", { type: "button", className: "btn btn--dark blocking-alert__action--standard", onClick: importSchemas, disabled: !importState.files?.length, children: "Import Schemas" }) })] }) }));
});
const SchemaBasicEditor = observer((props) => {
const { schema, isReadOnly, language } = props;
const changeId = (event) => externalFormat_schema_setId(schema, event.target.value);
const changeLocation = (event) => externalFormat_schema_setLocation(schema, event.target.value);
return (_jsxs("div", { className: "schema-editor", children: [_jsx("input", { className: "schema-editor__id", disabled: isReadOnly, value: schema.id, spellCheck: false, onChange: changeId, placeholder: `Id` }), _jsx("input", { className: "schema-editor__location", disabled: isReadOnly, value: schema.location, spellCheck: false, onChange: changeLocation, placeholder: `Location` }), _jsx("div", { className: clsx('schema-editor__content'), children: _jsx("div", { className: "schema-editor__content__input", children: _jsx(StudioTextInputEditor, { inputValue: schema.content, language: language, updateInput: (val) => {
externalFormat_schema_setContent(schema, val);
}, hideGutter: true }) }) })] }));
});
const SchemaSetGeneralEditor = observer((props) => {
const { schemaSetEditorState } = props;
const schemaSet = schemaSetEditorState.schemaSet;
const applicationStore = schemaSetEditorState.editorStore.applicationStore;
const importSchemaContentState = schemaSetEditorState.importSchemaContentState;
const currentSchema = schemaSetEditorState.currentSchema;
const isReadOnly = schemaSetEditorState.isReadOnly;
const description = schemaSetEditorState.schemaSetModelGenerationState.description;
// TEMPROARY engine api should return `fileformat`.
const language = getEditorLanguageFromFormat(description.name);
const changeState = (schema) => () => {
schemaSetEditorState.setCurrentSchema(schema);
};
const getIndex = (value) => guaranteeNonNullable(schemaSet.schemas.findIndex((schema) => value === schema), `Can't find schema '${value}' in schema set '${schemaSet.path}'`);
const addSchema = () => {
if (!isReadOnly) {
const schema = new Schema();
externalFormat_schema_setContent(schema, '');
externalFormat_schemaSet_addSchema(schemaSet, schema);
schemaSetEditorState.setCurrentSchema(schema);
}
};
const openSchemaLoader = () => importSchemaContentState.setImportSchemaModal(true);
const deleteSchema = (val) => () => {
externalFormat_schemaSet_deleteSchema(schemaSet, val);
if (schemaSet.schemas.length !== 0) {
schemaSetEditorState.setCurrentSchema(schemaSet.schemas[schemaSet.schemas.length - 1]);
}
if (schemaSet.schemas.length === 0) {
schemaSetEditorState.setCurrentSchema(undefined);
}
};
const validateSchema = () => {
if (currentSchema) {
flowResult(schemaSetEditorState.validateSchema(currentSchema)).catch(applicationStore.alertUnhandledError);
}
};
return (_jsxs(ResizablePanelGroup, { orientation: "vertical", children: [_jsx(ResizablePanel, { minSize: 30, size: 300, children: _jsxs("div", { className: "schema-set-panel", children: [_jsxs("div", { className: "schema-set-panel__header", children: [_jsx("div", { className: "panel__header__title", children: _jsx("div", { className: "panel__header__title__label", children: `${schemaSet.format} configuration` }) }), _jsxs("div", { className: "schema-set-panel__header__actions", children: [_jsx("button", { className: "schema-set-panel__header__action", onClick: openSchemaLoader, disabled: isReadOnly, tabIndex: -1, title: 'Import Schemas', children: _jsx(UploadIcon, {}) }), _jsx("button", { className: "schema-set-panel__header__action", onClick: addSchema, disabled: isReadOnly, tabIndex: -1, title: 'Add Schema', children: _jsx(PlusIcon, {}) })] })] }), schemaSet.schemas.map((schema, index) => (_jsx(ContextMenu, { className: clsx('schema-set-panel__item', {
'schema-set-panel__item--active': currentSchema === schema,
}), disabled: isReadOnly, content: _jsx(MenuContent, { children: _jsx(MenuContentItem, { onClick: deleteSchema(schema), children: "Delete" }) }), menuProps: { elevation: 7 }, children: _jsx("div", { className: "schema-set-panel__item__label", onClick: changeState(schema), children: schema.id ? schema.id : `Schema${index + 1}` }) }, schema._UUID)))] }) }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-dark-grey-200)" }) }), _jsx(ResizablePanel, { children: _jsxs("div", { className: "schema-set-panel", children: [_jsxs("div", { className: "schema-set-panel__header", children: [_jsxs("div", { className: "schema-set-panel__header__title", children: [isReadOnly && (_jsx("div", { className: "schema-set-panel__header__lock", children: _jsx(LockIcon, {}) })), _jsx("div", { className: "schema-set-panel__header__title__label", children: "Schema" }), _jsx("div", { className: "schema-set-panel__header__title__content", children: currentSchema !== undefined
? currentSchema.id
? currentSchema.id
: `Schema${getIndex(currentSchema) + 1}`
: '' })] }), _jsx("div", { className: "panel__header__actions", children: _jsx("button", { className: "btn--dark model-loader__header__load-btn", onClick: validateSchema, disabled: !currentSchema, tabIndex: -1, title: "Validate Schema", children: "Validate" }) })] }), _jsx("div", { className: "schema-set-panel__content", children: _jsxs("div", { className: "schema-set-panel__content__lists", children: [schemaSetEditorState.importSchemaContentState
.importSchemaModal && (_jsx(SchemaLoader, { schemaSetEditorState: schemaSetEditorState })), currentSchema !== undefined && (_jsx(SchemaBasicEditor, { language: language, schema: currentSchema, isReadOnly: isReadOnly }, currentSchema._UUID))] }) })] }) })] }));
});
const SchemaSetModelGenerationEditor = observer((props) => {
const { schemaSetEditorState } = props;
const applicationStore = schemaSetEditorState.editorStore.applicationStore;
const schemaSet = schemaSetEditorState.schemaSet;
const modelGenerationState = schemaSetEditorState.schemaSetModelGenerationState;
const description = modelGenerationState.description;
const properties = description.modelGenerationProperties;
const isReadOnly = schemaSetEditorState.isReadOnly;
const debouncedRegenerate = useMemo(() => debounce(() => flowResult(modelGenerationState.generateModel()), 500), [modelGenerationState]);
const update = (generationProperty, newValue) => {
debouncedRegenerate.cancel();
modelGenerationState.updateGenerationParameters(generationProperty, newValue);
debouncedRegenerate()?.catch(applicationStore.alertUnhandledError);
};
const regenerate = () => {
modelGenerationState.generateModel();
};
const getConfigValue = (name) => modelGenerationState.getConfigValue(name);
const importGeneratedElements = () => {
modelGenerationState.importGrammar();
};
return (_jsx("div", { className: "panel__content file-generation-editor__content", children: _jsxs(ResizablePanelGroup, { orientation: "vertical", children: [_jsx(ResizablePanel, { size: 250, minSize: 50, children: _jsxs("div", { className: "panel file-generation-editor__configuration", children: [_jsxs("div", { className: "panel__header", children: [_jsx("div", { className: "panel__header__title", children: _jsx("div", { className: "panel__header__title__label", children: `${schemaSet.format} configuration` }) }), _jsx("div", { className: "panel__header__actions", children: _jsx("button", { className: "panel__header__action file-generation-editor__configuration__reset-btn", tabIndex: -1, disabled: isReadOnly || !properties.length, onClick: regenerate, title: 'Reset to default configuration', children: _jsx(RefreshIcon, {}) }) })] }), _jsx("div", { className: "panel__content dnd__dropzone", children: _jsx("div", { className: "file-generation-editor__configuration__content", children: modelGenerationState.modelGenerationProperties.map((abstractGenerationProperty) => (_jsx(GenerationPropertyEditor, { update: update, isReadOnly: isReadOnly, getConfigValue: getConfigValue, property: abstractGenerationProperty }, abstractGenerationProperty.name))) }) })] }) }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-dark-grey-200)" }) }), _jsx(ResizablePanel, { children: _jsxs("div", { className: "panel generation-result-viewer__file", children: [_jsxs("div", { className: "panel__header", children: [_jsx("div", { className: "panel__header__title", children: _jsx("div", { className: "panel__header__title__label", children: "result" }) }), _jsxs("div", { className: "panel__header__actions", children: [_jsx("button", { className: clsx('panel__header__action generation-result-viewer__regenerate-btn', {
' generation-result-viewer__regenerate-btn--loading': modelGenerationState.isGenerating,
}), tabIndex: -1, disabled: modelGenerationState.isGenerating, onClick: regenerate, title: 'Re-generate', children: _jsx(RefreshIcon, {}) }), _jsx("button", { className: "btn--dark model-loader__header__load-btn", onClick: importGeneratedElements, disabled: modelGenerationState.generationValue === '', tabIndex: -1, title: "Import generated elements", children: "Import" })] })] }), _jsxs("div", { className: "panel__content", children: [_jsx(PanelLoadingIndicator, { isLoading: modelGenerationState.isGenerating }), _jsx(StudioTextInputEditor, { inputValue: modelGenerationState.generationValue, isReadOnly: true, language: EDITOR_LANGUAGE.PURE })] })] }) })] }) }));
});
export const SchemaSetEditor = observer(() => {
const editorStore = useEditorStore();
const schemaSetEditorState = editorStore.getCurrentEditorState(SchemaSetEditorState);
const isReadOnly = schemaSetEditorState.isReadOnly;
const schemaSet = schemaSetEditorState.schemaSet;
const currentTab = schemaSetEditorState.selectedTab;
const isFetchingDescriptions = editorStore.graphState.graphGenerationState.externalFormatState
.fetchingDescriptionsState.isInProgress;
const changeTab = (tab) => () => schemaSetEditorState.setSelectedTab(tab);
const renderMainEditPanel = () => {
if (isFetchingDescriptions) {
return (_jsx(BlankPanelContent, { children: "Fetching format descriptions" }));
}
if (currentTab === SCHEMA_SET_TAB_TYPE.GENERAL) {
return (_jsx(SchemaSetGeneralEditor, { schemaSetEditorState: schemaSetEditorState }));
}
const supportsModelGeneraiton = schemaSetEditorState.schemaSetModelGenerationState.description
.supportsModelGeneration;
return supportsModelGeneraiton ? (_jsx(SchemaSetModelGenerationEditor, { schemaSetEditorState: schemaSetEditorState })) : (_jsxs(BlankPanelContent, { children: ["Format ", schemaSet.format, " does not support Model Generation"] }));
};
return (_jsxs("div", { className: "panel schema-set-panel", children: [_jsx("div", { className: "schema-set-panel__header", children: _jsxs("div", { className: "schema-set-panel__header__title", children: [isReadOnly && (_jsx("div", { className: "schema-set-panel__header__lock", children: _jsx(LockIcon, {}) })), _jsx("div", { className: "schema-set-panel__header__title__label", children: "Schema Set" }), _jsx("div", { className: "schema-set-panel__header__title__content", children: schemaSet.name })] }) }), _jsxs("div", { className: "panel__content", children: [_jsx(PanelLoadingIndicator, { isLoading: isFetchingDescriptions }), _jsx("div", { className: "panel__header", children: _jsx("div", { className: "uml-element-editor__tabs", children: Object.values(SCHEMA_SET_TAB_TYPE).map((tab) => (_jsx("div", { onClick: changeTab(tab), className: clsx('relational-connection-editor__tab', {
'relational-connection-editor__tab--active': tab === currentTab,
}), children: prettyCONSTName(tab) }, tab))) }) }), _jsxs("div", { className: "panel__content file-generation-editor__content", children: [currentTab === SCHEMA_SET_TAB_TYPE.GENERAL && (_jsx(SchemaSetGeneralEditor, { schemaSetEditorState: schemaSetEditorState })), currentTab === SCHEMA_SET_TAB_TYPE.MODEL_GENERATION &&
renderMainEditPanel()] })] })] }));
});
//# sourceMappingURL=SchemaSetElementEditor.js.map