UNPKG

@craftercms/studio-ui

Version:

Services, components, models & utils to build CrafterCMS authoring extensions.

264 lines (262 loc) 9.56 kB
/* * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ import RepoGridUI from './RepoGridUI'; import React, { useState } from 'react'; import PullDialog from '../PullDialog'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import PushDialog from '../PushDialog'; import { deleteRemote as deleteRemoteService } from '../../../services/repositories'; import { showSystemNotification } from '../../../state/actions/system'; import { showErrorDialog } from '../../../state/reducers/dialogs/error'; import { useDispatch } from 'react-redux'; import { useActiveSiteId } from '../../../hooks/useActiveSiteId'; import { useEnhancedDialogState } from '../../../hooks/useEnhancedDialogState'; import SnackbarContent, { snackbarContentClasses } from '@mui/material/SnackbarContent'; import InputBase from '@mui/material/InputBase'; import Button from '@mui/material/Button'; import Snackbar from '@mui/material/Snackbar'; import { useSnackbar } from 'notistack'; import { copyToClipboard } from '../../../utils/system'; import PublishCommitDialog from '../PublishCommitDialog/PublishCommitDialog'; import useSpreadState from '../../../hooks/useSpreadState'; import RepoGridSkeleton from './RepoGridSkeleton'; const messages = defineMessages({ mergeStrategyNone: { id: 'repositories.mergeStrategyNone', defaultMessage: 'None' }, mergeStrategyOurs: { id: 'repositories.mergeStrategyOurs', defaultMessage: 'Accept Ours' }, mergeStrategyTheirs: { id: 'repositories.mergeStrategyTheirs', defaultMessage: 'Accept Theirs' }, remoteDeleteSuccessMessage: { id: 'repositories.remoteDeleteSuccessMessage', defaultMessage: 'Remote repository deleted successfully.' }, pullSuccessMessage: { id: 'repositories.pullSuccessMessage', defaultMessage: 'Successfully pulled {numberOfCommits} commits. Would you like to publish this now?' }, pullSuccessNoChangesMessage: { id: 'repositories.pullSuccessNoChangesMessage', defaultMessage: 'Pull successful: already up to date.' }, pushSuccessMessage: { id: 'repositories.pushSuccessMessage', defaultMessage: 'Successfully pushed.' } }); export function RepoGrid(props) { const { repositories, disableActions, fetchStatus, fetchRepositories } = props; const [repositoriesPushDialogBranches, setRepositoriesPushDialogBranches] = useState([]); const [pullRemoteName, setPullRemoteName] = useState(null); const [pushRemoteName, setPushRemoteName] = useState(null); const { formatMessage } = useIntl(); const mergeStrategies = [ { key: 'none', value: formatMessage(messages.mergeStrategyNone) }, { key: 'ours', value: formatMessage(messages.mergeStrategyOurs) }, { key: 'theirs', value: formatMessage(messages.mergeStrategyTheirs) } ]; const siteId = useActiveSiteId(); const dispatch = useDispatch(); const pushToRemoteDialogState = useEnhancedDialogState(); const pullFromRemoteDialogState = useEnhancedDialogState(); const { enqueueSnackbar } = useSnackbar(); const [postPullState, setPostPullState] = useSpreadState({ openPublishCommitDialog: false, openPostPullSnack: false, mergeCommitId: '', commitsMerged: 0 }); const onClickPull = (remoteName, branches) => { setPullRemoteName(remoteName); pullFromRemoteDialogState.onOpen(); }; const onClickPush = (remoteName, branches) => { setRepositoriesPushDialogBranches(branches); setPushRemoteName(remoteName); pushToRemoteDialogState.onOpen(); }; const onPullSuccess = (result) => { fetchStatus(); pullFromRemoteDialogState.onClose(); if (result.mergeCommitId) { setPostPullState(Object.assign({ openPostPullSnack: true }, result)); } else { dispatch( showSystemNotification({ message: formatMessage(messages.pullSuccessNoChangesMessage) }) ); } }; const onPullError = (response) => { fetchStatus(); pullFromRemoteDialogState.onClose(); dispatch( showSystemNotification({ message: response.message, options: { variant: 'error' } }) ); }; const onPushSuccess = () => { pushToRemoteDialogState.onResetState(); dispatch( showSystemNotification({ message: formatMessage(messages.pushSuccessMessage) }) ); }; const onPushError = (response) => { pushToRemoteDialogState.onClose(); dispatch(showErrorDialog({ error: response })); }; const deleteRemote = (remoteName) => { deleteRemoteService(siteId, remoteName).subscribe( () => { fetchRepositories(); dispatch( showSystemNotification({ message: formatMessage(messages.remoteDeleteSuccessMessage) }) ); }, ({ response }) => { dispatch(showErrorDialog({ error: response })); } ); }; const onClosePostPullSnack = () => setPostPullState({ openPostPullSnack: false }); return React.createElement( React.Fragment, null, repositories ? React.createElement(RepoGridUI, { repositories: repositories, disableActions: disableActions, onPullClick: onClickPull, onPushClick: onClickPush, onDeleteRemote: deleteRemote }) : React.createElement(RepoGridSkeleton, null), React.createElement( Snackbar, { autoHideDuration: 10000, onClose: onClosePostPullSnack, open: postPullState.openPostPullSnack, sx: { maxWidth: '500px' } }, React.createElement(SnackbarContent, { sx: { [`.${snackbarContentClasses.message}`]: { width: '100%' } }, message: React.createElement( React.Fragment, null, formatMessage(messages.pullSuccessMessage, { numberOfCommits: postPullState.commitsMerged }), React.createElement(InputBase, { sx: { display: 'block', mt: 1, borderRadius: 1, pr: 0.5, pl: 0.5 }, autoFocus: true, value: postPullState.mergeCommitId, readOnly: true, onClick: (e) => { e.target.select(); copyToClipboard(postPullState.mergeCommitId).then(function () { enqueueSnackbar('Copied'); }); } }) ), action: React.createElement( React.Fragment, null, React.createElement( Button, { size: 'small', onClick: () => setPostPullState({ openPublishCommitDialog: true, openPostPullSnack: false }) }, React.createElement(FormattedMessage, { id: 'words.yes', defaultMessage: 'Yes' }) ), React.createElement( Button, { size: 'small', onClick: onClosePostPullSnack }, React.createElement(FormattedMessage, { id: 'words.no', defaultMessage: 'No' }) ) ) }) ), React.createElement(PullDialog, { open: pullFromRemoteDialogState.open, onClose: pullFromRemoteDialogState.onClose, remoteName: pullRemoteName, mergeStrategies: mergeStrategies, onPullSuccess: onPullSuccess, onPullError: onPullError, isMinimized: pullFromRemoteDialogState.isMinimized, isSubmitting: pullFromRemoteDialogState.isSubmitting, hasPendingChanges: pullFromRemoteDialogState.hasPendingChanges }), React.createElement(PushDialog, { open: pushToRemoteDialogState.open, branches: repositoriesPushDialogBranches, remoteName: pushRemoteName, onClose: pushToRemoteDialogState.onClose, onPushSuccess: onPushSuccess, onPushError: onPushError, isMinimized: pushToRemoteDialogState.isMinimized, isSubmitting: pushToRemoteDialogState.isSubmitting, hasPendingChanges: pushToRemoteDialogState.hasPendingChanges, onSubmittingChange: pushToRemoteDialogState.onSubmittingChange }), React.createElement(PublishCommitDialog, { commitId: postPullState.mergeCommitId, open: postPullState.openPublishCommitDialog, onClose: () => { setPostPullState({ openPublishCommitDialog: false }); } }) ); } export default RepoGrid;