UNPKG

@finos/legend-studio

Version:
146 lines 11.9 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } 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 { useRef, useEffect } from 'react'; import { observer } from 'mobx-react-lite'; import { Link } from 'react-router-dom'; import { EntityDiffViewState } from '../../../stores/editor-state/entity-diff-editor-state/EntityDiffViewState.js'; import { EntityDiffSideBarItem } from '../../editor/edit-panel/diff-editor/EntityDiffView.js'; import { clsx, PanelLoadingIndicator, TruncatedGitMergeIcon, RefreshIcon, InfoCircleIcon, TimesIcon, PlusIcon, ExternalLinkSquareIcon, } from '@finos/legend-art'; import { ACTIVITY_MODE } from '../../../stores/EditorConfig.js'; import { formatDistanceToNow } from 'date-fns'; import { generateReviewRoute } from '../../../stores/LegendStudioRouter.js'; import { LEGEND_STUDIO_TEST_ID } from '../../LegendStudioTestID.js'; import { flowResult } from 'mobx'; import { entityDiffSorter } from '../../../stores/EditorSDLCState.js'; import { useEditorStore } from '../EditorStoreProvider.js'; import { ActionAlertType, ActionAlertActionType, } from '@finos/legend-application'; import { useLegendStudioApplicationStore } from '../../LegendStudioBaseStoreProvider.js'; export const WorkspaceReviewDiffs = observer(() => { const editorStore = useEditorStore(); const workspaceReviewState = editorStore.workspaceReviewState; const currentEditorState = editorStore.currentEditorState; const changes = editorStore.changeDetectionState.aggregatedWorkspaceChanges; const isSelectedDiff = (diff) => currentEditorState instanceof EntityDiffViewState && diff.oldPath === currentEditorState.fromEntityPath && diff.newPath === currentEditorState.toEntityPath; const openChange = (diff) => () => workspaceReviewState.openReviewChange(diff); return (_jsxs("div", { className: "panel side-bar__panel workspace-review__diffs", children: [_jsxs("div", { className: "panel__header", children: [_jsxs("div", { className: "panel__header__title", children: [_jsx("div", { className: "panel__header__title__content", children: "CHANGES" }), _jsx("div", { className: "side-bar__panel__title__info", title: "All changes made in the workspace since the revision the workspace is created", children: _jsx(InfoCircleIcon, {}) })] }), _jsx("div", { className: "side-bar__panel__header__changes-count", "data-testid": LEGEND_STUDIO_TEST_ID.SIDEBAR_PANEL_HEADER__CHANGES_COUNT, children: changes.length })] }), _jsx("div", { className: "panel__content", children: changes .slice() .sort(entityDiffSorter) .map((diff) => (_jsx(EntityDiffSideBarItem, { diff: diff, isSelected: isSelectedDiff(diff), openDiff: openChange(diff) }, diff.key))) })] })); }); export const WorkspaceReview = observer(() => { const editorStore = useEditorStore(); const applicationStore = useLegendStudioApplicationStore(); const workspaceReviewState = editorStore.workspaceReviewState; const workspaceContainsSnapshotDependencies = editorStore.projectConfigurationEditorState.containsSnapshotDependencies; const workspaceReview = workspaceReviewState.workspaceReview; // Review Title const reviewTitleInputRef = useRef(null); const editReviewTitle = (event) => { if (!workspaceReview) { workspaceReviewState.setReviewTitle(event.target.value); } }; const isDispatchingAction = workspaceReviewState.isCreatingWorkspaceReview || workspaceReviewState.isFetchingCurrentWorkspaceReview || workspaceReviewState.isRefreshingWorkspaceChangesDetector || workspaceReviewState.isCommittingWorkspaceReview || workspaceReviewState.isClosingWorkspaceReview || workspaceReviewState.isRecreatingWorkspaceAfterCommittingReview; const refresh = () => { flowResult(workspaceReviewState.refreshWorkspaceChanges()).catch(applicationStore.alertUnhandledError); flowResult(workspaceReviewState.fetchCurrentWorkspaceReview()).catch(applicationStore.alertUnhandledError); }; const closeReview = () => { workspaceReviewState.setReviewTitle(''); flowResult(workspaceReviewState.closeWorkspaceReview()).catch(applicationStore.alertUnhandledError); }; const commitReview = () => { if (workspaceReview && !isDispatchingAction) { const commit = () => { workspaceReviewState.setReviewTitle(''); flowResult(workspaceReviewState.commitWorkspaceReview(workspaceReview)).catch(applicationStore.alertUnhandledError); }; 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 commit review', type: ActionAlertActionType.PROCEED_WITH_CAUTION, handler: () => { editorStore.setIgnoreNavigationBlocking(true); commit(); }, }, { label: 'Abort', type: ActionAlertActionType.PROCEED, default: true, }, ], }); } else { commit(); } } }; const createReview = () => { if (workspaceReviewState.reviewTitle && !workspaceReview && !isDispatchingAction) { flowResult(workspaceReviewState.createWorkspaceReview(workspaceReviewState.reviewTitle)).catch(applicationStore.alertUnhandledError); } }; // since the review can be changed by other people, we can refresh it more proactively // the diffs are caused by the current user though, so we should handle that as part // of `syncWithWorkspace` for example; in case it is bad, user can click refresh to make it right again useEffect(() => { flowResult(workspaceReviewState.fetchCurrentWorkspaceReview()).catch(applicationStore.alertUnhandledError); }, [applicationStore, workspaceReviewState]); useEffect(() => { if (editorStore.activeActivity === ACTIVITY_MODE.WORKSPACE_REVIEW) { reviewTitleInputRef.current?.focus(); } }, [editorStore.activeActivity]); return (_jsxs("div", { className: "panel workspace-review", children: [_jsxs("div", { className: "panel__header side-bar__header", children: [_jsx("div", { className: "panel__header__title workspace-review__header__title", children: _jsx("div", { className: "panel__header__title__content side-bar__header__title__content", children: "REVIEW" }) }), _jsxs("div", { className: "panel__header__actions side-bar__header__actions", children: [_jsx("button", { className: clsx('panel__header__action side-bar__header__action workspace-review__refresh-btn', { 'workspace-review__refresh-btn--loading': workspaceReviewState.isRefreshingWorkspaceChangesDetector, }), disabled: isDispatchingAction, onClick: refresh, tabIndex: -1, title: "Refresh", children: _jsx(RefreshIcon, {}) }), _jsx("button", { className: "panel__header__action side-bar__header__action workspace-review__close-btn", disabled: !workspaceReview || isDispatchingAction, onClick: closeReview, tabIndex: -1, title: "Close review", children: _jsx(TimesIcon, {}) })] })] }), _jsxs("div", { className: "panel__content side-bar__content", children: [_jsx(PanelLoadingIndicator, { isLoading: isDispatchingAction }), _jsxs("div", { className: "panel workspace-review", children: [!workspaceReview && (_jsx(_Fragment, { children: _jsxs("form", { className: "workspace-review__title", onSubmit: (e) => { e.preventDefault(); }, children: [_jsx("div", { className: "workspace-review__title__content", children: _jsx("input", { className: "workspace-review__title__content__input input--dark", ref: reviewTitleInputRef, spellCheck: false, value: workspaceReviewState.reviewTitle, disabled: Boolean(workspaceReview), onChange: editReviewTitle, placeholder: 'Title' }) }), _jsx("button", { className: clsx('btn--dark btn--sm', { 'btn--error': workspaceContainsSnapshotDependencies, }), onClick: createReview, disabled: isDispatchingAction || Boolean(workspaceReview) || !workspaceReviewState.reviewTitle || workspaceContainsSnapshotDependencies, title: !workspaceContainsSnapshotDependencies ? 'Create review' : `Can't create review: workspace has snapshot dependencies`, children: _jsx(PlusIcon, {}) })] }) })), workspaceReview && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "workspace-review__title", children: [_jsx("div", { className: "workspace-review__title__content", children: _jsx("div", { className: "workspace-review__title__content__input workspace-review__title__content__input--with-link", title: 'See review detail', children: _jsxs(Link, { className: "workspace-review__title__content__input__link", rel: "noopener noreferrer", target: "_blank", to: generateReviewRoute(workspaceReview.projectId, workspaceReview.id), children: [_jsx("span", { className: "workspace-review__title__content__input__link__review-name", children: workspaceReview.title }), _jsx("div", { className: "workspace-review__title__content__input__link__btn", children: _jsx(ExternalLinkSquareIcon, {}) })] }) }) }), _jsx("button", { className: clsx('btn--dark btn--sm workspace-review__merge-review-btn', { 'btn--error': workspaceContainsSnapshotDependencies }), onClick: commitReview, disabled: isDispatchingAction || Boolean(!workspaceReview) || workspaceContainsSnapshotDependencies, tabIndex: -1, title: !workspaceContainsSnapshotDependencies ? 'Commit review' : `Can't commit review: workspace has snapshot dependencies`, children: _jsx(TruncatedGitMergeIcon, {}) })] }), _jsxs("div", { className: "workspace-review__title__content__review-status", children: ["created", ' ', formatDistanceToNow(workspaceReview.createdAt, { includeSeconds: true, addSuffix: true, })] })] })), _jsx(WorkspaceReviewDiffs, {})] })] })] })); }); //# sourceMappingURL=WorkspaceReview.js.map