@finos/legend-application-studio
Version:
Legend Studio application core
123 lines • 14.6 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, Dialog, PanelLoadingIndicator, TimesIcon, RefreshIcon, InfoCircleIcon, DownloadIcon, UploadIcon, CloudDownloadIcon, ResizablePanelGroup, ResizablePanel, ResizablePanelSplitter, ResizablePanelSplitterLine, CloudUploadIcon, PanelContent, Modal, ModalBody, ModalFooter, ModalHeader, ModalFooterButton, } from '@finos/legend-art';
import { EntityDiffViewState } from '../../../stores/editor/editor-state/entity-diff-editor-state/EntityDiffViewState.js';
import { EntityDiffSideBarItem } from '../editor-group/diff-editor/EntityDiffView.js';
import { LEGEND_STUDIO_TEST_ID } from '../../../__lib__/LegendStudioTesting.js';
import { flowResult } from 'mobx';
import { entityDiffSorter } from '../../../stores/editor/EditorSDLCState.js';
import { useEditorStore } from '../EditorStoreProvider.js';
import { useApplicationStore } from '@finos/legend-application';
import { useEffect } from 'react';
import { EntityChangeConflictEditorState } from '../../../stores/editor/editor-state/entity-diff-editor-state/EntityChangeConflictEditorState.js';
import { EntityChangeConflictSideBarItem } from '../editor-group/diff-editor/EntityChangeConflictEditor.js';
import { FormLocalChangesState } from '../../../stores/editor/sidebar-state/LocalChangesState.js';
import { GRAPH_EDITOR_MODE } from '../../../stores/editor/EditorConfig.js';
const PatchLoader = observer(() => {
const editorStore = useEditorStore();
const applicationStore = editorStore.applicationStore;
const localChangesState = editorStore.localChangesState;
const patchState = localChangesState.patchLoaderState;
const onClose = () => patchState.closeModal();
const onChange = (event) => {
const file = event.target.files?.[0];
if (file) {
patchState.loadPatchFile(file);
}
};
const upload = () => {
patchState.applyChanges();
};
const deleteChange = (change) => patchState.deleteChange(change);
return (_jsx(Dialog, { onClose: onClose, open: patchState.showModal, children: _jsxs(Modal, { darkMode: !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled, className: "modal--scrollable patch-loader", children: [_jsx(ModalHeader, { title: "Patch Loader" }), _jsxs(ModalBody, { children: [_jsx(PanelLoadingIndicator, { isLoading: patchState.isLoadingChanges }), _jsx("div", { children: _jsx("input", { type: "file", name: "myFiles", onChange: onChange }) }), Boolean(patchState.overiddingChanges.length) && (_jsxs("div", { className: "panel__content__form__section", children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Overriding Changes" }), _jsx("div", { className: "panel__content__form__section__header__prompt", children: "The following element changes will be overridden by the patch" }), _jsx("div", { className: "panel__content__form__section__list", children: _jsx("div", { className: "panel__content__form__section__list__items", children: patchState.overiddingChanges.map((value) => (_jsxs("div", { className: "panel__content__form__section__list__item", children: [_jsx("div", { className: "panel__content__form__section__list__item__value", children: value.entityPath }), _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: () => deleteChange(value), tabIndex: -1, children: _jsx(TimesIcon, {}) }) })] }, value.entityPath))) }) })] }))] }), _jsx(ModalFooter, { children: _jsx(ModalFooterButton, { className: "blocking-alert__action--standard", text: "Apply Patch", onClick: upload, disabled: !patchState.changes?.length || !patchState.isValidPatch }) })] }) }));
});
export const LocalChanges = observer(() => {
const editorStore = useEditorStore();
const sdlcState = editorStore.sdlcState;
const applicationStore = useApplicationStore();
const localChangesState = editorStore.localChangesState;
const updateState = localChangesState.workspaceSyncState;
// Actions
const downloadLocalChanges = () => localChangesState.downloadLocalChanges();
const uploadPatchChanges = () => localChangesState.patchLoaderState.openModal(editorStore.localChangesState.computeLocalEntityChanges());
const pushLocalChanges = applicationStore.guardUnhandledError(() => flowResult(localChangesState.pushLocalChanges()));
const refreshLocalChanges = applicationStore.guardUnhandledError(() => flowResult(localChangesState.refreshLocalChanges()));
const pullRemoteWorkspace = () => {
if (!localChangesState.refreshWorkspaceSyncStatusState.isInProgress) {
flowResult(updateState.pullChanges()).catch(applicationStore.alertUnhandledError);
}
};
const isDispatchingAction = localChangesState.pushChangesState.isInProgress ||
localChangesState.refreshLocalChangesDetectorState.isInProgress ||
localChangesState.workspaceSyncState.pullChangesState.isInProgress ||
localChangesState.refreshWorkspaceSyncStatusState.isInProgress;
// Changes
const currentTabState = editorStore.tabManagerState.currentTab;
const isSelectedDiff = (diff) => currentTabState instanceof EntityDiffViewState &&
diff.oldPath === currentTabState.fromEntityPath &&
diff.newPath === currentTabState.toEntityPath;
const changes = editorStore.changeDetectionState.workspaceLocalLatestRevisionState.changes;
const openChange = (diff) => () => {
if (localChangesState instanceof FormLocalChangesState) {
localChangesState.openLocalChange(diff);
}
};
// Local/Remote Workspace Conflicts
const conflicts = editorStore.changeDetectionState.potentialWorkspacePullConflicts;
const isSelectedConflict = (conflict) => currentTabState instanceof EntityChangeConflictEditorState &&
conflict.entityPath === currentTabState.entityPath;
const openPotentialConflict = (conflict) => () => {
if (localChangesState instanceof FormLocalChangesState) {
localChangesState.openPotentialWorkspacePullConflict(conflict);
}
};
// Local/Remote Workspace Changes
const workspacePullChanges = editorStore.changeDetectionState.aggregatedWorkspaceRemoteChanges;
const changesWithoutConflicts = workspacePullChanges.filter((change) => !conflicts
.map((conflict) => conflict.entityPath)
.includes(change.entityPath));
const openWorkspacePullChange = (diff) => () => {
if (localChangesState instanceof FormLocalChangesState) {
localChangesState.openWorkspacePullChange(diff);
}
};
// check if workspace is still in-sync
useEffect(() => {
flowResult(localChangesState.refreshWorkspaceSyncStatus()).catch(applicationStore.alertUnhandledError);
}, [applicationStore, localChangesState]);
return (_jsxs("div", { className: "panel local-changes", children: [_jsxs("div", { className: "panel__header side-bar__header", children: [_jsx("div", { className: "panel__header__title local-changes__header__title", children: _jsx("div", { className: "panel__header__title__content side-bar__header__title__content", children: "LOCAL CHANGES" }) }), _jsxs("div", { className: "panel__header__actions side-bar__header__actions", children: [_jsx("button", { className: "panel__header__action side-bar__header__action local-changes__download-patch-btn", onClick: downloadLocalChanges, disabled: isDispatchingAction ||
editorStore.workspaceUpdaterState.isUpdatingWorkspace ||
!changes.length, tabIndex: -1, title: "Download local entity changes", children: _jsx(DownloadIcon, {}) }), _jsx("button", { className: "panel__header__action side-bar__header__action local-changes__download-patch-btn", onClick: uploadPatchChanges, disabled: isDispatchingAction ||
editorStore.workspaceUpdaterState.isUpdatingWorkspace ||
!editorStore.changeDetectionState.initState.hasSucceeded ||
editorStore.graphEditorMode.mode !== GRAPH_EDITOR_MODE.FORM, tabIndex: -1, title: "Upload local entity changes", children: _jsx(UploadIcon, {}) }), _jsx("button", { className: clsx('panel__header__action side-bar__header__action local-changes__refresh-btn', {
'local-changes__refresh-btn--loading': localChangesState.refreshLocalChangesDetectorState
.isInProgress,
}), onClick: refreshLocalChanges, disabled: isDispatchingAction, tabIndex: -1, title: "Refresh", children: _jsx(RefreshIcon, {}) }), _jsx("button", { className: clsx('panel__header__action side-bar__header__action local-changes__push-changes-btn', {
'local-changes__push-changes-btn--loading': localChangesState.pushChangesState.isInProgress,
}), onClick: pushLocalChanges, disabled: isDispatchingAction ||
editorStore.workspaceUpdaterState.isUpdatingWorkspace, tabIndex: -1, title: "Push local changes (Ctrl + S)", children: _jsx(CloudUploadIcon, {}) }), _jsx("button", { className: "panel__header__action side-bar__header__action workspace-updater__update-btn", onClick: pullRemoteWorkspace, disabled: isDispatchingAction ||
!sdlcState.remoteWorkspaceRevision ||
!sdlcState.isWorkspaceOutOfSync, tabIndex: -1, title: "Pull remote workspace changes", children: _jsx(CloudDownloadIcon, {}) })] })] }), _jsxs("div", { className: "panel__content side-bar__content", children: [_jsx(PanelLoadingIndicator, { isLoading: isDispatchingAction }), localChangesState.patchLoaderState.showModal && _jsx(PatchLoader, {}), _jsxs(ResizablePanelGroup, { orientation: "horizontal", children: [_jsx(ResizablePanel, { size: 600, minSize: 28, children: _jsxs("div", { className: "panel side-bar__panel", 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 local changes that have not been yet pushed with the server", 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(PanelContent, { children: changes.toSorted(entityDiffSorter).map((diff) => (_jsx(EntityDiffSideBarItem, { diff: diff, isSelected: isSelectedDiff(diff), openDiff: openChange(diff) }, diff.key))) })] }) }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-dark-grey-100)" }) }), _jsx(ResizablePanel, { minSize: 28, children: _jsxs("div", { className: "panel side-bar__panel", children: [_jsxs("div", { className: "panel__header", children: [_jsxs("div", { className: "panel__header__title", children: [_jsx("div", { className: "panel__header__title__content", children: "INCOMING REMOTE REVISIONS" }), _jsx("div", { className: "side-bar__panel__title__info", title: "All incoming remote revisions since last syncing of workspace", children: _jsx(InfoCircleIcon, {}) })] }), _jsx("div", { className: "side-bar__panel__header__changes-count", children: updateState.incomingRevisions.length })] }), _jsx(PanelContent, { children: updateState.incomingRevisions.map((revision) => (_jsx("div", { className: "side-bar__panel__item", children: _jsxs("div", { className: "local-changes__revision", children: [_jsx("span", { className: "local-changes__revision__name", children: revision.message }), _jsx("span", { className: "local-changes__revision__info", children: revision.committerName })] }) }, revision.id))) })] }) }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-dark-grey-100)" }) }), _jsx(ResizablePanel, { minSize: 28, children: _jsxs("div", { className: "panel side-bar__panel", children: [_jsxs("div", { className: "panel__header", children: [_jsxs("div", { className: "panel__header__title", children: [_jsx("div", { className: "panel__header__title__content", children: "INCOMING REMOTE CHANGES" }), _jsx("div", { className: "side-bar__panel__title__info", title: 'All changes made to remote workspace since last syncing of workspace.\nPotential workspace sync conflicts are also shown if they exist', children: _jsx(InfoCircleIcon, {}) })] }), _jsx("div", { className: "side-bar__panel__header__changes-count", "data-testid": LEGEND_STUDIO_TEST_ID.SIDEBAR_PANEL_HEADER__CHANGES_COUNT, children: workspacePullChanges.length })] }), _jsxs(PanelContent, { children: [conflicts
.toSorted((a, b) => a.entityName.localeCompare(b.entityName))
.map((conflict) => (_jsx(EntityChangeConflictSideBarItem, { conflict: conflict, isSelected: isSelectedConflict(conflict), openConflict: openPotentialConflict(conflict) }, `conflict-${conflict.entityPath}`))), Boolean(conflicts.length) &&
Boolean(changesWithoutConflicts.length) && (_jsx("div", { className: "diff-panel__item-section-separator" })), changesWithoutConflicts
.toSorted(entityDiffSorter)
.map((diff) => (_jsx(EntityDiffSideBarItem, { diff: diff, isSelected: isSelectedDiff(diff), openDiff: openWorkspacePullChange(diff) }, diff.key)))] })] }) })] })] })] }));
});
//# sourceMappingURL=LocalChanges.js.map