@finos/legend-application-studio
Version:
Legend Studio application core
251 lines • 22.5 kB
JavaScript
import { jsx as _jsx, Fragment as _Fragment, 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 { createContext, useContext, useEffect, useMemo, useState, useRef, } from 'react';
import { observer, useLocalObservable } from 'mobx-react-lite';
import { clsx, AssistantIcon, compareLabelFn, GitBranchIcon, CustomSelectorInput, LongArrowRightIcon, DividerWithText, SearchIcon, BaseCard, OpenIcon, Dialog, MarkdownTextViewer, Modal, } from '@finos/legend-art';
import { LEGEND_STUDIO_TEST_ID } from '../../__lib__/LegendStudioTesting.js';
import { generateEditorRoute, LEGEND_STUDIO_ROUTE_PATTERN_TOKEN, } from '../../__lib__/LegendStudioNavigation.js';
import { flowResult } from 'mobx';
import { useApplicationNavigationContext } from '@finos/legend-application';
import { useParams } from '@finos/legend-application/browser';
import { LEGEND_STUDIO_DOCUMENTATION_KEY } from '../../__lib__/LegendStudioDocumentation.js';
import { CreateProjectModal } from './CreateProjectModal.js';
import { ActivityBarMenu } from '../editor/ActivityBar.js';
import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../__lib__/LegendStudioApplicationNavigationContext.js';
import { CreateWorkspaceModal } from './CreateWorkspaceModal.js';
import { useLegendStudioApplicationStore, useLegendStudioBaseStore, } from '../LegendStudioFrameworkProvider.js';
import { buildProjectOption, getProjectOptionLabelFormatter, } from './ProjectSelectorUtils.js';
import { buildWorkspaceOption, formatWorkspaceOptionLabel, } from './WorkspaceSelectorUtils.js';
import { debounce, guaranteeNonNullable } from '@finos/legend-shared';
import { WorkspaceSetupStore } from '../../stores/workspace-setup/WorkspaceSetupStore.js';
import { openShowcaseManager } from '../../stores/ShowcaseManagerState.js';
const WorkspaceSetupStoreContext = createContext(undefined);
export const DEFAULT_WORKSPACE_SOURCE = 'HEAD';
export const ShowcaseCard = (props) => {
const applicationStore = useLegendStudioApplicationStore();
const appDocUrl = applicationStore.documentationService.url;
return (_jsx(BaseCard, { className: "workspace-setup__content__card", cardMedia: undefined, cardName: "Showcase Projects", cardContent: _jsxs("div", { className: "workspace-setup__content__card__content", children: ["Review showcase projects with sample project code and re-use existing code snippets to quickly build your model.", ' ', !props.hideDocumentation && (_jsxs(_Fragment, { children: ["Review Studio", ' ', _jsx("a", { href: appDocUrl, target: "_blank", rel: "noreferrer", className: "workspace-setup__content__link", children: "documentation" }), "."] }))] }), cardActions: [
{
title: 'Showcase explorer',
content: (_jsx("div", { className: "workspace-setup__content__card__action__icon", children: _jsx(OpenIcon, {}) })),
action: () => openShowcaseManager(applicationStore),
},
], isStable: true }));
};
export const DocumentationCard = () => {
const applicationStore = useLegendStudioApplicationStore();
const appDocUrl = applicationStore.documentationService.url;
return (_jsx(BaseCard, { className: "workspace-setup__content__card", cardName: "Documentation", cardContent: _jsxs("div", { className: "workspace-setup__content__card__content", children: ["Review Studio", ' ', _jsx("a", { href: appDocUrl, target: "_blank", rel: "noreferrer", className: "workspace-setup__content__link", children: "documentation" }), "."] }), cardActions: [
{
title: 'Review documentation',
content: (_jsx("div", { className: "workspace-setup__content__card__action__icon", children: _jsx(OpenIcon, {}) })),
action: () => {
if (appDocUrl) {
applicationStore.navigationService.navigator.visitAddress(appDocUrl);
}
},
},
], isStable: true }));
};
export const ProductionCard = () => {
const applicationStore = useLegendStudioApplicationStore();
const productionDocument = applicationStore.documentationService.getDocEntry(LEGEND_STUDIO_DOCUMENTATION_KEY.APPLICATION_PRODUCTION);
return (productionDocument?.title &&
productionDocument.markdownText &&
productionDocument.text && (_jsx(BaseCard, { className: "workspace-setup__content__card", cardName: productionDocument.title, cardContent: productionDocument.markdownText.value, cardActions: [
{
title: productionDocument.text,
content: (_jsx("div", { className: "workspace-setup__content__card__action__icon", children: _jsx(OpenIcon, {}) })),
action: () => {
if (productionDocument.url) {
applicationStore.navigationService.navigator.visitAddress(productionDocument.url);
}
},
},
], isStable: true })));
};
export const SandboxCard = () => {
const applicationStore = useLegendStudioApplicationStore();
const sandboxDocument = applicationStore.documentationService.getDocEntry(LEGEND_STUDIO_DOCUMENTATION_KEY.APPLICATION_SANDBOX);
return (sandboxDocument?.title &&
sandboxDocument.markdownText &&
sandboxDocument.text && (_jsx(BaseCard, { className: "workspace-setup__content__card", cardName: sandboxDocument.title, cardContent: sandboxDocument.markdownText.value, cardActions: [
{
title: sandboxDocument.text,
content: (_jsx("div", { className: "workspace-setup__content__card__action__icon", children: _jsx(OpenIcon, {}) })),
action: () => {
if (sandboxDocument.url) {
applicationStore.navigationService.navigator.visitAddress(sandboxDocument.url);
}
},
},
], isStable: true })));
};
export const RuleEngagementCard = () => {
const applicationStore = useLegendStudioApplicationStore();
const ruleEngagementDocument = applicationStore.documentationService.getDocEntry(LEGEND_STUDIO_DOCUMENTATION_KEY.APPLICATION_RULE_ENGAGEMENT);
return (ruleEngagementDocument?.title &&
ruleEngagementDocument.markdownText &&
ruleEngagementDocument.text && (_jsx(BaseCard, { className: "workspace-setup__content__card", cardMedia: undefined, cardName: ruleEngagementDocument.title, cardContent: ruleEngagementDocument.markdownText.value, cardActions: [
{
title: ruleEngagementDocument.text,
content: (_jsx("div", { className: "workspace-setup__content__card__action__icon", children: _jsx(OpenIcon, {}) })),
action: () => {
if (ruleEngagementDocument.url) {
applicationStore.navigationService.navigator.visitAddress(ruleEngagementDocument.url);
}
},
},
], isStable: true })));
};
const WorkspaceSetupStoreProvider = ({ children }) => {
const applicationStore = useLegendStudioApplicationStore();
const baseStore = useLegendStudioBaseStore();
const store = useLocalObservable(() => new WorkspaceSetupStore(applicationStore, baseStore.sdlcServerClient));
return (_jsx(WorkspaceSetupStoreContext.Provider, { value: store, children: children }));
};
export const useWorkspaceSetupStore = () => guaranteeNonNullable(useContext(WorkspaceSetupStoreContext), `Can't find workspace setup store in context`);
const withWorkspaceSetupStore = (WrappedComponent) => function WithWorkspaceSetupStore() {
return (_jsx(WorkspaceSetupStoreProvider, { children: _jsx(WrappedComponent, {}) }));
};
const SandboxAccessModal = observer(() => {
const setupStore = useWorkspaceSetupStore();
const closeModal = () => setupStore.setSandboxModal(false);
const applicationStore = setupStore.applicationStore;
const documentation = applicationStore.documentationService.getDocEntry(LEGEND_STUDIO_DOCUMENTATION_KEY.SETUP_CREATE_SANDBOX_UNAUTHORIZED);
return (_jsx(Dialog, { open: true, onClose: closeModal, children: _jsxs(Modal, { darkMode: !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled, className: "sandbox-project-modal", children: [_jsx("div", { className: "sandbox-project-modal__header", children: _jsx("div", { className: "sandbox-project-modal__header__label", children: "Create Sandbox Project" }) }), _jsx("div", { className: "sandbox-project-modal__form panel__content__form", children: _jsx("div", { className: "panel__content__form__section sandbox-project-modal__form__unsupported", children: "You do not have access to create a Sandbox Project" }) }), _jsx("div", { className: "sandbox-project-modal__content", children: documentation?.markdownText && (_jsx("div", { className: "panel__content__form__section", children: _jsx(MarkdownTextViewer, { value: documentation.markdownText }) })) })] }) }));
});
export const WorkspaceSetup = withWorkspaceSetupStore(observer(() => {
const params = useParams();
const projectId = params[LEGEND_STUDIO_ROUTE_PATTERN_TOKEN.PROJECT_ID];
const workspaceId = params[LEGEND_STUDIO_ROUTE_PATTERN_TOKEN.WORKSPACE_ID];
const groupWorkspaceId = params[LEGEND_STUDIO_ROUTE_PATTERN_TOKEN.GROUP_WORKSPACE_ID];
const setupStore = useWorkspaceSetupStore();
const applicationStore = useLegendStudioApplicationStore();
const [projectSearchText, setProjectSearchText] = useState('');
const goButtonRef = useRef(null);
//TODO: fix logo loading issue for localhost
const logoPath = `${applicationStore.config.baseAddress}favicon.ico`;
const toggleAssistant = () => applicationStore.assistantService.toggleAssistant();
// projects
const projectOptions = setupStore.projects
.map(buildProjectOption)
.sort(compareLabelFn);
const selectedProjectOption = setupStore.currentProject
? buildProjectOption(setupStore.currentProject)
: null;
const onProjectChange = (val) => {
if (val) {
flowResult(setupStore.changeProject(val.value)).catch(applicationStore.alertUnhandledError);
}
else {
setupStore.resetProject();
}
};
const showCreateProjectModal = () => setupStore.setShowCreateProjectModal(true);
const createSandboxProject = () => {
flowResult(setupStore.createSandboxProject()).catch(applicationStore.alertUnhandledError);
};
// project search text
const debouncedLoadProjects = useMemo(() => debounce((input) => {
flowResult(setupStore.loadProjects(input)).catch(applicationStore.alertUnhandledError);
}, 500), [applicationStore, setupStore]);
const onProjectSearchTextChange = (value) => {
if (value !== projectSearchText) {
setProjectSearchText(value);
debouncedLoadProjects.cancel();
debouncedLoadProjects(value);
}
};
// workspaces
const workspaceOptions = setupStore.workspaces
.map(buildWorkspaceOption)
.sort(compareLabelFn);
const selectedWorkspaceOption = setupStore.currentWorkspace
? buildWorkspaceOption(setupStore.currentWorkspace)
: null;
const onWorkspaceChange = (val) => {
if (val) {
setupStore.changeWorkspace(val.value);
if (!setupStore.currentProjectConfigurationStatus?.isConfigured) {
applicationStore.notificationService.notifyIllegalState(`Can't edit current workspace as the current project is not configured`);
}
goButtonRef.current?.focus();
}
else {
setupStore.resetWorkspace();
}
};
const showCreateWorkspaceModal = () => setupStore.setShowCreateWorkspaceModal(true);
const handleProceed = () => {
if (setupStore.currentProject && setupStore.currentWorkspace) {
applicationStore.navigationService.navigator.goToLocation(generateEditorRoute(setupStore.currentProject.projectId, setupStore.currentWorkspace.source, setupStore.currentWorkspace.workspaceId, setupStore.currentWorkspace.workspaceType));
}
};
useEffect(() => {
flowResult(setupStore.initialize(projectId, workspaceId, groupWorkspaceId)).catch(applicationStore.alertUnhandledError);
}, [
setupStore,
applicationStore,
projectId,
workspaceId,
groupWorkspaceId,
]);
useEffect(() => {
flowResult(setupStore.loadProjects('')).catch(applicationStore.alertUnhandledError);
flowResult(setupStore.loadSandboxProject()).catch(applicationStore.alertUnhandledError);
}, [setupStore, applicationStore]);
useApplicationNavigationContext(LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.SETUP);
return (_jsx("div", { className: "app__page", children: _jsxs("div", { className: "workspace-setup", children: [_jsxs("div", { className: "workspace-setup__body", children: [_jsx("div", { className: "activity-bar", children: _jsx(ActivityBarMenu, {}) }), _jsx("div", { className: "workspace-setup__content", "data-testid": LEGEND_STUDIO_TEST_ID.SETUP__CONTENT, children: _jsxs("div", { className: "workspace-setup__content__body", children: [_jsxs("div", { className: "workspace-setup__content__main", children: [_jsxs("div", { className: "workspace-setup__title", children: [_jsx("div", { className: "workspace-setup__logo", children: _jsx("img", { src: logoPath, className: "workspace-setup__logo__icon" }) }), _jsx("div", { className: "workspace-setup__title__header", children: "Welcome to Legend Studio" })] }), _jsx("div", { className: "workspace-setup__selectors", children: _jsxs("div", { className: "workspace-setup__selectors__container", children: [_jsxs("div", { className: "workspace-setup__selector", children: [_jsx("div", { className: "workspace-setup__selector__header", children: "Search for an existing project" }), _jsxs("div", { className: "workspace-setup__selector__content", children: [_jsx("div", { className: "workspace-setup__selector__content__icon", title: "project", children: _jsx(SearchIcon, { className: "workspace-setup__selector__content__icon--project" }) }), _jsx(CustomSelectorInput, { className: "workspace-setup__selector__content__input", options: projectOptions, isLoading: setupStore.loadProjectsState.isInProgress ||
setupStore.loadSandboxState.isInProgress, onInputChange: onProjectSearchTextChange, inputValue: projectSearchText, onChange: onProjectChange, value: selectedProjectOption, placeholder: "Search for project...", isClearable: true, escapeClearsValue: true, darkMode: !applicationStore.layoutService
.TEMPORARY__isLightColorThemeEnabled, formatOptionLabel: getProjectOptionLabelFormatter(applicationStore, setupStore.currentProjectConfigurationStatus), optionCustomization: {
rowHeight: window.innerHeight * 0.03,
} })] })] }), _jsxs("div", { className: "workspace-setup__selector", children: [_jsx("div", { className: "workspace-setup__selector__header", children: "Choose an existing workspace" }), _jsxs("div", { className: "workspace-setup__selector__content", children: [_jsx("div", { className: "workspace-setup__selector__content__icon", title: "workspace", children: _jsx(GitBranchIcon, { className: "workspace-setup__selector__content__icon--workspace" }) }), _jsx(CustomSelectorInput, { className: "workspace-setup__selector__content__input", options: workspaceOptions, onKeyDown: (event) => {
if (event.key === 'Enter') {
goButtonRef.current?.focus();
handleProceed();
}
}, disabled: !setupStore.currentProject ||
!setupStore.currentProjectConfigurationStatus ||
!setupStore.currentProjectConfigurationStatus
.isConfigured ||
setupStore.loadProjectsState.isInProgress ||
setupStore.loadWorkspacesState.isInProgress, isLoading: setupStore.loadWorkspacesState.isInProgress, onChange: onWorkspaceChange, formatOptionLabel: formatWorkspaceOptionLabel, value: selectedWorkspaceOption, placeholder: setupStore.loadWorkspacesState.isInProgress
? 'Loading workspaces...'
: !setupStore.currentProject
? 'In order to choose a workspace, a project must be chosen'
: workspaceOptions.length
? 'Choose an existing workspace'
: 'You have no workspaces. Please create one to proceed...', isClearable: true, escapeClearsValue: true, darkMode: !applicationStore.layoutService
.TEMPORARY__isLightColorThemeEnabled, optionCustomization: {
rowHeight: window.innerHeight * 0.03,
} })] })] })] }) }), _jsx("div", { className: "workspace-setup__actions-combo", children: _jsxs("div", { className: "workspace-setup__actions", children: [_jsx("button", { className: "workspace-setup__new-workspace-btn", onClick: showCreateWorkspaceModal, title: "Create a Workspace after choosing one project", disabled: !setupStore.currentProject ||
!setupStore.currentProjectConfigurationStatus
?.isConfigured, children: `Need to create a new workspace?` }), _jsx("div", { className: "workspace-setup__actions__button", children: _jsxs("button", { className: "workspace-setup__go-btn btn--dark", onClick: handleProceed, ref: goButtonRef, disabled: !setupStore.currentProject ||
!setupStore.currentProjectConfigurationStatus ||
!setupStore.currentProjectConfigurationStatus
.isConfigured ||
!setupStore.currentWorkspace ||
setupStore.createWorkspaceState.isInProgress ||
setupStore.createOrImportProjectState.isInProgress, children: [_jsx("div", { className: "workspace-setup__go-btn__label", children: "Go" }), _jsx(LongArrowRightIcon, { className: "workspace-setup__go-btn__icon" })] }) }), _jsx(DividerWithText, { className: "workspace-setup__divider", children: "OR" }), setupStore.sandboxModal && _jsx(SandboxAccessModal, {}), _jsxs("div", { className: "workspace-setup__actions__button", children: [_jsx("button", { className: "workspace-setup__new-btn btn--dark", onClick: showCreateProjectModal, title: "Create a Project", children: "Create New Project" }), setupStore.sandboxProject === true &&
setupStore.initState.hasCompleted &&
setupStore.supportsCreatingSandboxProject && (_jsx("button", { className: "workspace-setup__new-btn btn--dark", onClick: createSandboxProject, title: "Create Sandbox Project", children: "Create Sandbox Project" }))] })] }) })] }), _jsxs("div", { className: "workspace-setup__content__cards", children: [_jsx(RuleEngagementCard, {}), _jsx(ShowcaseCard, {}), _jsx(SandboxCard, {}), _jsx(ProductionCard, {})] }), setupStore.showCreateProjectModal && _jsx(CreateProjectModal, {}), setupStore.showCreateWorkspaceModal &&
setupStore.currentProject && (_jsx(CreateWorkspaceModal, { selectedProject: setupStore.currentProject }))] }) })] }), _jsxs("div", { "data-testid": LEGEND_STUDIO_TEST_ID.STATUS_BAR, className: "editor__status-bar", children: [_jsx("div", { className: "editor__status-bar__left" }), _jsx("div", { className: "editor__status-bar__right", children: _jsx("button", { className: clsx('editor__status-bar__action editor__status-bar__action__toggler', {
'editor__status-bar__action__toggler--active': !applicationStore.assistantService.isHidden,
}), onClick: toggleAssistant, tabIndex: -1, title: "Toggle assistant", children: _jsx(AssistantIcon, {}) }) })] })] }) }));
}));
//# sourceMappingURL=WorkspaceSetup.js.map