@craftercms/studio-ui
Version:
Services, components, models & utils to build CrafterCMS authoring extensions.
287 lines (285 loc) • 9.94 kB
JavaScript
/*
* 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 React, { useCallback, useEffect, useState } from 'react';
import DialogBody from '../../DialogBody/DialogBody';
import DialogFooter from '../../DialogFooter/DialogFooter';
import { FormattedMessage } from 'react-intl';
import InputLabel from '@mui/material/InputLabel';
import FormControl from '@mui/material/FormControl';
import Select from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
import { makeStyles } from 'tss-react/mui';
import { pull } from '../../../services/repositories';
import SecondaryButton from '../../SecondaryButton';
import PrimaryButton from '../../PrimaryButton';
import { isBlank } from '../../../utils/string';
import {
getStoredPullMergeStrategy,
removeStoredPullMergeStrategy,
setStoredPullMergeStrategy
} from '../../../utils/state';
import useActiveSite from '../../../hooks/useActiveSite';
import useActiveUser from '../../../hooks/useActiveUser';
import Alert from '@mui/material/Alert';
import Box from '@mui/material/Box';
import { Typography } from '@mui/material';
import Button from '@mui/material/Button';
import { fetchLegacySite } from '../../../services/sites';
import useSpreadState from '../../../hooks/useSpreadState';
import Skeleton from '@mui/material/Skeleton';
const useStyles = makeStyles()((theme) => ({
formControl: {
marginBottom: '15px'
},
pullBranchLabel: {
padding: `${theme.spacing(1.5)} ${theme.spacing(2)}`,
border: `1px solid ${theme.palette.divider}`,
borderRadius: 4,
color: theme.palette.text.primary,
display: 'flex',
alignItems: 'center'
},
pullBranchLabelWithError: {
justifyContent: 'space-between'
},
pullBranchLabelHeading: {
display: 'inline-block',
fontWeight: theme.typography.fontWeightMedium,
marginRight: theme.spacing(1)
},
pullBranchLabelError: {
color: theme.palette.error.main
},
pullInfo: {
alignItems: 'center',
marginTop: theme.spacing(2)
}
}));
export function PullDialogContainer(props) {
// region const { ... } = props
const {
remoteName,
mergeStrategies,
onClose,
onPullSuccess,
onPullError,
onPullStart,
disabled = false,
isSubmitting = false
} = props;
// endregion
const [selectedMergeStrategy, setSelectedMergeStrategy] = useState('');
const { classes, cx } = useStyles();
const { uuid, id: siteId } = useActiveSite();
const { username } = useActiveUser();
const [sandboxState, setSandboxState] = useSpreadState({
branch: '',
error: null,
loading: false
});
const onMergeStrategyChange = (e) => {
setSelectedMergeStrategy(e.target.value);
};
const onCloseButtonClick = (e) => onClose(e, null);
const onSubmit = (e) => {
e.preventDefault();
if (!isBlank(sandboxState.branch)) {
onPullStart === null || onPullStart === void 0 ? void 0 : onPullStart();
pull({
siteId,
remoteName,
remoteBranch: sandboxState.branch,
mergeStrategy: selectedMergeStrategy
}).subscribe({
next(result) {
onPullSuccess === null || onPullSuccess === void 0 ? void 0 : onPullSuccess(result);
},
error({ response }) {
onPullError === null || onPullError === void 0 ? void 0 : onPullError(response.response);
}
});
}
};
const fetchSandboxBranch = useCallback(() => {
setSandboxState({ loading: true, error: null });
fetchLegacySite(siteId).subscribe({
next: ({ sandboxBranch }) => {
setSandboxState({
branch: sandboxBranch,
error: null,
loading: false
});
},
error: (error) => {
setSandboxState({
error: error,
loading: false
});
}
});
}, [siteId, setSandboxState]);
useEffect(() => {
if (
!selectedMergeStrategy &&
(mergeStrategies === null || mergeStrategies === void 0 ? void 0 : mergeStrategies.length)
) {
const storedPullMergeStrategy = getStoredPullMergeStrategy(uuid, username);
if (storedPullMergeStrategy) {
let strategy = mergeStrategies.find((ms) => ms.key === storedPullMergeStrategy);
if (strategy) {
setSelectedMergeStrategy(storedPullMergeStrategy);
} else {
removeStoredPullMergeStrategy(uuid, username);
}
} else {
setSelectedMergeStrategy(mergeStrategies[0].key);
}
}
}, [mergeStrategies, selectedMergeStrategy, uuid, username]);
useEffect(() => {
if (selectedMergeStrategy) {
setStoredPullMergeStrategy(uuid, username, selectedMergeStrategy);
}
}, [selectedMergeStrategy, uuid, username]);
useEffect(() => {
fetchSandboxBranch();
}, [fetchSandboxBranch]);
return React.createElement(
'form',
{ onSubmit: onSubmit },
React.createElement(
DialogBody,
null,
React.createElement(
Box,
{
className: cx(
classes.pullBranchLabel,
classes.formControl,
sandboxState.error && classes.pullBranchLabelWithError
)
},
sandboxState.error
? React.createElement(
React.Fragment,
null,
React.createElement(
Typography,
{ className: classes.pullBranchLabelError },
React.createElement(FormattedMessage, {
id: 'repositories.sandboxBranchRetrievalError',
defaultMessage: 'Unable to retrieve project\u2019s branch'
})
),
React.createElement(
Button,
{ onClick: fetchSandboxBranch, size: 'small' },
React.createElement(FormattedMessage, { id: 'words.retry', defaultMessage: 'Retry' })
)
)
: React.createElement(
React.Fragment,
null,
React.createElement(
Typography,
{ color: 'textSecondary', className: classes.pullBranchLabelHeading },
React.createElement(FormattedMessage, { id: 'words.branch', defaultMessage: 'Branch' })
),
sandboxState.loading
? React.createElement(Skeleton, {
variant: 'text',
width: '30%',
animation: 'wave',
sx: { display: 'inline-flex' }
})
: sandboxState.branch
)
),
React.createElement(
FormControl,
{ variant: 'outlined', fullWidth: true, disabled: disabled || isSubmitting },
React.createElement(
InputLabel,
{ id: 'mergeStrategyLabel' },
React.createElement(FormattedMessage, {
id: 'repositories.mergeStrategyLabel',
defaultMessage: 'Merge Strategy'
})
),
React.createElement(
Select,
{
labelId: 'mergeStrategyLabel',
name: 'mergeStrategy',
value: selectedMergeStrategy,
onChange: onMergeStrategyChange,
label: React.createElement(FormattedMessage, {
id: 'repositories.mergeStrategyLabel',
defaultMessage: 'Merge Strategy'
}),
fullWidth: true
},
mergeStrategies.map((strategy) =>
React.createElement(MenuItem, { key: strategy.key, value: strategy.key }, strategy.value)
)
)
),
React.createElement(
Alert,
{ severity: 'info', variant: 'outlined', className: classes.pullInfo },
React.createElement(
Typography,
null,
React.createElement(FormattedMessage, {
id: 'repositories.pullFromCreatedBranchOnlyHint',
defaultMessage:
'You may only pull from the branch the site was created from; any feature branch work should be merged upstream.'
})
)
)
),
React.createElement(
DialogFooter,
null,
React.createElement(
SecondaryButton,
{ onClick: onCloseButtonClick, disabled: disabled || isSubmitting },
React.createElement(FormattedMessage, { id: 'words.cancel', defaultMessage: 'Cancel' })
),
React.createElement(
PrimaryButton,
{ type: 'submit', disabled: disabled || isBlank(sandboxState.branch), loading: isSubmitting },
React.createElement(FormattedMessage, { id: 'words.pull', defaultMessage: 'Pull' })
)
)
);
}
export default PullDialogContainer;