UNPKG

@finos/legend-studio

Version:
221 lines 16.7 kB
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 { useEffect, useRef } from 'react'; import { LogEvent, prettyCONSTName, assertErrorThrown, guaranteeNonNullable, } from '@finos/legend-shared'; import { observer } from 'mobx-react-lite'; import { ProjectConfigurationEditorState, CONFIGURATION_EDITOR_TAB, } from '../../../../stores/editor-state/ProjectConfigurationEditorState.js'; import { compareLabelFn, clsx, CustomSelectorInput, PlusIcon, TimesIcon, CheckCircleIcon, ExclamationCircleIcon, ExternalLinkSquareIcon, } from '@finos/legend-art'; import { flowResult } from 'mobx'; import { ProjectDependency, } from '@finos/legend-server-sdlc'; import { useEditorStore } from '../../EditorStoreProvider.js'; import { ActionAlertActionType, ActionAlertType, useApplicationStore, } from '@finos/legend-application'; import { LEGEND_STUDIO_APP_EVENT } from '../../../../stores/LegendStudioAppEvent.js'; import { SNAPSHOT_VERSION_ALIAS, MASTER_SNAPSHOT_ALIAS, compareSemVerVersions, generateGAVCoordinates, } from '@finos/legend-server-depot'; const buildProjectOption = (project) => ({ label: project.coordinates, value: project, }); const ProjectStructureEditor = observer((props) => { const { projectConfig, isReadOnly } = props; const editorStore = useEditorStore(); const applicationStore = useApplicationStore(); const latestVersion = editorStore.projectConfigurationEditorState.latestProjectStructureVersion; const currentProjectExtensionVersion = projectConfig.projectStructureVersion.extensionVersion ?? -1; const latestProjectExtensionVersion = latestVersion?.extensionVersion ?? -1; const isVersionOutdated = latestVersion && (latestVersion.version > projectConfig.projectStructureVersion.version || latestProjectExtensionVersion > currentProjectExtensionVersion); const changeGroupId = (event) => { if (!isReadOnly) { projectConfig.setGroupId(event.target.value); } }; const changeArtifactId = (event) => { if (!isReadOnly) { projectConfig.setArtifactId(event.target.value); } }; const updateVersion = () => { flowResult(editorStore.projectConfigurationEditorState.updateToLatestStructure()).catch(applicationStore.alertUnhandledError); }; return (_jsxs("div", { className: "panel__content__lists", children: [_jsxs("div", { className: "project-configuration-editor__project__structure__version", children: [_jsxs("div", { className: "project-configuration-editor__project__structure__version__label", children: [_jsx("div", { className: "project-configuration-editor__project__structure__version__label__status", children: isVersionOutdated ? (_jsx(ExclamationCircleIcon, { className: "project-configuration-editor__project__structure__version__label__status--outdated", title: "Project structure is outdated" })) : (_jsx(CheckCircleIcon, { className: "project-configuration-editor__project__structure__version__label__status--up-to-date", title: "Project structure is up to date" })) }), _jsxs("div", { className: "project-configuration-editor__project__structure__version__label__text", children: ["PROJECT STRUCTURE VERSION", ' ', ` ${projectConfig.projectStructureVersion.fullVersion}`] })] }), isVersionOutdated && (_jsxs("button", { className: "project-configuration-editor__project__structure__version__update-btn", disabled: isReadOnly, onClick: updateVersion, tabIndex: -1, title: `Current project structure is outdated. Click to update to the latest version (v${latestVersion.fullVersion}})`, children: ["Update to version ", latestVersion.fullVersion] }))] }), _jsx("div", { className: "panel__content__form", children: _jsxs("div", { className: "panel__content__form__section", children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Group ID" }), _jsx("div", { className: "panel__content__form__section__header__prompt", children: "The domain for artifacts generated as part of the project build pipeline and published to an artifact repository" }), _jsx("input", { className: "panel__content__form__section__input", spellCheck: false, disabled: isReadOnly, value: projectConfig.groupId, onChange: changeGroupId })] }) }), _jsx("div", { className: "panel__content__form", children: _jsxs("div", { className: "panel__content__form__section", children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Artifact ID" }), _jsx("div", { className: "panel__content__form__section__header__prompt", children: "The identifier (within the domain specified by group ID) for artifacts generated as part of the project build pipeline and published to an artifact repository" }), _jsx("input", { className: "panel__content__form__section__input", spellCheck: false, disabled: isReadOnly, value: projectConfig.artifactId, onChange: changeArtifactId })] }) })] })); }); const formatOptionLabel = (option) => (_jsxs("div", { className: "project-dependency-editor__label", children: [_jsx("div", { className: "project-dependency-editor__label__tag", children: option.value.projectId }), _jsx("div", { className: "project-dependency-editor__label__name", children: option.value.coordinates })] })); const ProjectDependencyEditor = observer((props) => { // init const { projectDependency, deleteValue, isReadOnly } = props; const editorStore = useEditorStore(); const applicationStore = useApplicationStore(); const projectSelectorRef = useRef(null); const versionSelectorRef = useRef(null); const configState = editorStore.projectConfigurationEditorState; // project const selectedProject = configState.projects.get(projectDependency.projectId); const selectedProjectOption = selectedProject ? buildProjectOption(selectedProject) : null; const projectDisabled = !configState.associatedProjectsAndVersionsFetched || configState.isReadOnly; const projectsOptions = Array.from(configState.projects.values()) .map(buildProjectOption) .sort(compareLabelFn); const onProjectSelectionChange = (val) => { if ((val !== null || selectedProjectOption !== null) && (!val || !selectedProjectOption || val.value !== selectedProjectOption.value)) { projectDependency.setProjectId(val?.value.coordinates ?? ''); if (val) { projectDependency.setVersionId(val.value.latestVersion); } } }; // version const version = projectDependency.versionId; const versions = selectedProject?.versions ?? []; let versionOptions = versions .slice() .sort((v1, v2) => compareSemVerVersions(v2, v1)) .map((v) => ({ value: v, label: v })); versionOptions = [ { label: SNAPSHOT_VERSION_ALIAS, value: MASTER_SNAPSHOT_ALIAS }, ...versionOptions, ]; const selectedVersionOption = versionOptions.find((v) => v.value === version) ?? null; const versionDisabled = Boolean(!versions.length || !projectDependency.projectId.length) || !configState.associatedProjectsAndVersionsFetched || isReadOnly; const onVersionSelectionChange = (val) => { if ((val !== null || selectedVersionOption !== null) && (!val || !selectedVersionOption || val.value !== selectedVersionOption.value)) { try { projectDependency.setVersionId(val?.value ?? ''); } catch (error) { assertErrorThrown(error); applicationStore.log.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE), error); } } }; const openProject = () => { if (!projectDependency.isLegacyDependency) { const projectDependencyVersionId = projectDependency.versionId === MASTER_SNAPSHOT_ALIAS ? SNAPSHOT_VERSION_ALIAS : projectDependency.versionId; applicationStore.navigator.openNewWindow(`${applicationStore.config.baseUrl}view/archive/${generateGAVCoordinates(guaranteeNonNullable(projectDependency.groupId), guaranteeNonNullable(projectDependency.artifactId), projectDependencyVersionId)}`); } }; const projectSelectorPlaceholder = !projectDependency.projectId.length ? 'Choose project' : versionDisabled ? 'No project version found. Please create a new one.' : 'Select version'; return (_jsxs("div", { className: "project-dependency-editor", children: [_jsx(CustomSelectorInput, { className: "project-dependency-editor__selector", ref: projectSelectorRef, disabled: projectDisabled, options: projectsOptions, isClearable: true, escapeClearsValue: true, onChange: onProjectSelectionChange, value: selectedProjectOption, isLoading: configState.isFetchingAssociatedProjectsAndVersions, formatOptionLabel: formatOptionLabel, darkMode: true }), _jsx(CustomSelectorInput, { className: "project-dependency-editor__selector", ref: versionSelectorRef, options: versionOptions, isClearable: true, escapeClearsValue: true, onChange: onVersionSelectionChange, value: selectedVersionOption, disabled: versionDisabled, placeholder: projectSelectorPlaceholder, isLoading: editorStore.projectConfigurationEditorState .isFetchingAssociatedProjectsAndVersions, darkMode: true }), _jsx("button", { className: "project-dependency-editor__visit-btn btn--dark btn--sm", disabled: projectDependency.isLegacyDependency || !selectedProject || !selectedVersionOption, onClick: openProject, tabIndex: -1, title: 'Open Project', children: _jsx(ExternalLinkSquareIcon, {}) }), _jsx("button", { className: "project-dependency-editor__remove-btn btn--dark btn--caution", disabled: isReadOnly, onClick: deleteValue, tabIndex: -1, title: 'Close', children: _jsx(TimesIcon, {}) })] })); }); export const ProjectConfigurationEditor = observer(() => { const editorStore = useEditorStore(); const applicationStore = useApplicationStore(); const configState = editorStore.getCurrentEditorState(ProjectConfigurationEditorState); const sdlcState = editorStore.sdlcState; const isReadOnly = editorStore.isInViewerMode; const selectedTab = configState.selectedTab; const tabs = [ CONFIGURATION_EDITOR_TAB.PROJECT_STRUCTURE, CONFIGURATION_EDITOR_TAB.PROJECT_DEPENDENCIES, ]; const changeTab = (tab) => () => configState.setSelectedTab(tab); let addButtonTitle = ''; switch (selectedTab) { case CONFIGURATION_EDITOR_TAB.PROJECT_DEPENDENCIES: addButtonTitle = 'Add project dependencies'; break; default: break; } const currentProjectConfiguration = configState.currentProjectConfiguration; const deleteProjectDependency = (val) => () => currentProjectConfiguration.deleteProjectDependency(val); const addValue = () => { if (!isReadOnly) { if (selectedTab === CONFIGURATION_EDITOR_TAB.PROJECT_DEPENDENCIES) { const currentProjects = Array.from(configState.projects.values()); if (currentProjects.length) { const projectToAdd = currentProjects[0]; const dependencyToAdd = new ProjectDependency(projectToAdd.coordinates); dependencyToAdd.setVersionId(projectToAdd.latestVersion); currentProjectConfiguration.addProjectDependency(dependencyToAdd); } else { currentProjectConfiguration.addProjectDependency(new ProjectDependency('')); } } } }; const disableAddButton = selectedTab === CONFIGURATION_EDITOR_TAB.PROJECT_STRUCTURE || isReadOnly; const updateConfigs = () => { if (editorStore.hasUnpushedChanges) { editorStore.setActionAlertInfo({ message: 'You have unpushed changes', prompt: 'This action will discard these changes and refresh the application', type: ActionAlertType.CAUTION, onEnter: () => editorStore.setBlockGlobalHotkeys(true), onClose: () => editorStore.setBlockGlobalHotkeys(false), actions: [ { label: 'Proceed to update project dependencies', type: ActionAlertActionType.PROCEED_WITH_CAUTION, handler: () => { editorStore.setIgnoreNavigationBlocking(true); flowResult(configState.updateConfigs()).catch(applicationStore.alertUnhandledError); }, }, { label: 'Abort', type: ActionAlertActionType.PROCEED, default: true, }, ], }); } else { flowResult(configState.updateConfigs()).catch(applicationStore.alertUnhandledError); } }; useEffect(() => { if (configState.projectConfiguration && selectedTab === CONFIGURATION_EDITOR_TAB.PROJECT_DEPENDENCIES && !configState.associatedProjectsAndVersionsFetched) { flowResult(configState.fectchAssociatedProjectsAndVersions()).catch(applicationStore.alertUnhandledError); } }, [applicationStore, configState, selectedTab]); if (!configState.projectConfiguration) { return null; } return (_jsx("div", { className: "project-configuration-editor", children: _jsxs("div", { className: "panel", children: [_jsxs("div", { className: "panel__header", children: [_jsxs("div", { className: "panel__header__title", children: [_jsx("div", { className: "panel__header__title__label", children: "project configuration" }), _jsx("div", { className: "panel__header__title__content", children: sdlcState.currentProject?.name ?? '(unknown)' })] }), _jsx("button", { // TODO: remove this ugly button when we integrate project configuration into change detection flow className: "project-configuration-editor__update-btn", disabled: isReadOnly || configState.isUpdatingConfiguration || currentProjectConfiguration.hashCode === configState.originalConfig.hashCode, onClick: updateConfigs, tabIndex: -1, children: "Update" })] }), _jsxs("div", { className: "panel__header project-configuration-editor__tabs__header", children: [_jsx("div", { className: "project-configuration-editor__tabs", children: tabs.map((tab) => (_jsx("button", { onClick: changeTab(tab), className: clsx('project-configuration-editor__tab', { 'project-configuration-editor__tab--active': tab === selectedTab, }), children: prettyCONSTName(tab) }, tab))) }), _jsx("div", { className: "panel__header__actions", children: _jsx("button", { className: "panel__header__action", disabled: disableAddButton, tabIndex: -1, onClick: addValue, title: addButtonTitle, children: _jsx(PlusIcon, {}) }) })] }), _jsxs("div", { className: "panel__content project-configuration-editor__content", children: [selectedTab === CONFIGURATION_EDITOR_TAB.PROJECT_STRUCTURE && (_jsx(ProjectStructureEditor, { projectConfig: currentProjectConfiguration, isReadOnly: isReadOnly })), selectedTab === CONFIGURATION_EDITOR_TAB.PROJECT_DEPENDENCIES && (_jsx("div", { className: "panel__content__lists", children: currentProjectConfiguration.projectDependencies.map((projectDependency) => (_jsx(ProjectDependencyEditor, { projectDependency: projectDependency, deleteValue: deleteProjectDependency(projectDependency), isReadOnly: isReadOnly }, projectDependency._UUID))) }))] })] }) })); }); //# sourceMappingURL=ProjectConfigurationEditor.js.map