Commit 76ec4c90 authored by Eric Rosenbaum's avatar Eric Rosenbaum

More error handling, moved to confirmation step

parent a305a096
......@@ -101,6 +101,7 @@
"studio.transfer.forgotPassword": "Forgot password?",
"studio.transfer.alert.somethingWentWrong": "Something went wrong transferring this studio to a new host.",
"studio.transfer.alert.wasntTheRightPassword": "Hmm, that wasn’t the right password.",
"studio.transfer.alert.thisUserCannotBecomeHost": "This user cannot become the host — try transfering to another manager",
"studio.remove": "Remove",
"studio.promote": "Promote",
......
......@@ -15,6 +15,7 @@ const Errors = keyMirror({
UNKNOWN_USERNAME: null,
RATE_LIMIT: null,
MANAGER_LIMIT: null,
CONFLICT: null,
UNHANDLED: null
});
......@@ -28,6 +29,7 @@ const normalizeError = (err, body, res) => {
if (res.statusCode === 403 && body.mute_status) return Errors.USER_MUTED;
if (res.statusCode === 401 || res.statusCode === 403) return Errors.PERMISSION;
if (res.statusCode === 404) return Errors.UNKNOWN_USERNAME;
if (res.statusCode === 409) return Errors.CONFLICT;
if (res.statusCode === 429) return Errors.RATE_LIMIT;
if (res.statusCode !== 200) return Errors.SERVER;
if (body && body.status === 'error') {
......
......@@ -2,6 +2,7 @@ import React, {useState} from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {FormattedMessage} from 'react-intl';
const {injectIntl, intlShape} = require('react-intl');
import ModalInnerContent from '../../../components/modal/base/modal-inner-content.jsx';
......@@ -11,11 +12,16 @@ import ValidationMessage from '../../../components/forms/validation-message.jsx'
import {managers} from '../lib/redux-modules';
import {useAlertContext} from '../../../components/alert/alert-context';
import {Errors, transferHost} from '../lib/studio-member-actions';
import './transfer-host-modal.scss';
const TransferHostConfirmation = ({
handleBack,
handleTransfer,
handleClose,
handleTransferHost,
intl,
items,
hostId,
selectedId
......@@ -25,12 +31,45 @@ const TransferHostConfirmation = ({
const newHostUsername = items.find(item => item.id === selectedId).username;
const newHostImage = items.find(item => item.id === selectedId).profile.images['90x90'];
const [passwordInputValue, setPasswordInputValue] = useState('');
const [validationError, setValidationError] = useState(null);
const {errorAlert, successAlert} = useAlertContext();
const errorToMessageId = error => {
switch (error) {
case Errors.RATE_LIMIT: return 'studio.alertTransferRateLimit';
case Errors.CONFLICT: return 'studio.transfer.alert.thisUserCannotBecomeHost';
default: return 'studio.transfer.alert.somethingWentWrong';
}
};
const handleSubmit = () => {
handleTransfer(passwordInputValue, newHostUsername, selectedId);
handleTransferHost(passwordInputValue, newHostUsername, selectedId)
.then(() => {
handleClose();
successAlert({
id: 'studio.alertTransfer',
values: {name: newHostUsername}
});
})
.catch(e => {
// For password errors, show validation alert without closing the modal
if (e === Errors.PERMISSION) {
setValidationError(e);
return;
}
// For other errors, close the modal and show an alert
handleClose();
errorAlert({
id: errorToMessageId(e)
});
});
};
const handleChangePasswordInput = e => {
setPasswordInputValue(e.target.value);
setValidationError(null);
};
return (
<ModalInnerContent>
<div className="transfer-outcome">
......@@ -84,11 +123,11 @@ const TransferHostConfirmation = ({
value={passwordInputValue}
onChange={handleChangePasswordInput} // eslint-disable-line react/jsx-no-bind
/>
<ValidationMessage
{validationError && <ValidationMessage
className="transfer-password-validation"
message={<FormattedMessage id="studio.transfer.alert.wasntTheRightPassword" />}
message={intl.formatMessage({id: 'studio.transfer.alert.wasntTheRightPassword'})}
mode="error"
/>
/>}
</div>
<div className="transfer-forgot-link">
<a
......@@ -122,7 +161,8 @@ const TransferHostConfirmation = ({
TransferHostConfirmation.propTypes = {
handleBack: PropTypes.func,
handleTransfer: PropTypes.func,
handleClose: PropTypes.func,
intl: intlShape,
items: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.id,
username: PropTypes.string,
......@@ -132,13 +172,18 @@ TransferHostConfirmation.propTypes = {
})
})
})),
handleTransferHost: PropTypes.func,
selectedId: PropTypes.number,
hostId: PropTypes.number
};
export default connect(
const connectedConfirmationStep = connect(
state => ({
hostId: state.studio.owner,
...managers.selector(state)
})
}), {
handleTransferHost: transferHost
}
)(TransferHostConfirmation);
export default injectIntl(connectedConfirmationStep);
......@@ -19,8 +19,7 @@ const STEPS = keyMirror({
});
const TransferHostModal = ({
handleClose,
handleTransfer
handleClose
}) => {
const [step, setStep] = useState(STEPS.info);
const [selectedId, setSelectedId] = useState(null);
......@@ -47,15 +46,13 @@ const TransferHostModal = ({
{step === STEPS.confirmation && <TransferHostConfirmation
handleClose={handleClose}
handleBack={() => setStep(STEPS.selection)} // eslint-disable-line react/jsx-no-bind
handleTransfer={handleTransfer}
selectedId={selectedId}
/>}
</Modal>);
};
TransferHostModal.propTypes = {
handleClose: PropTypes.func,
handleTransfer: PropTypes.func
handleClose: PropTypes.func
};
export default TransferHostModal;
......@@ -18,8 +18,7 @@ import {
Errors,
promoteCurator,
removeCurator,
removeManager,
transferHost
removeManager
} from './lib/studio-member-actions';
import {selectStudioHasReachedManagerLimit} from '../../redux/studio';
......@@ -30,7 +29,7 @@ import removeIcon from './icons/remove-icon.svg';
import promoteIcon from './icons/curator-icon.svg';
const StudioMemberTile = ({
canRemove, canPromote, onRemove, canTransferHost, onPromote, onTransferHost,
canRemove, canPromote, onRemove, canTransferHost, onPromote,
isCreator, hasReachedManagerLimit, // mapState props
username, image // own props
}) => {
......@@ -135,22 +134,6 @@ const StudioMemberTile = ({
{transferHostModalOpen &&
<TransferHostModal
handleClose={() => setTransferHostModalOpen(false)}
handleTransfer={(password, newHostUsername, newHostUsernameId) => {
onTransferHost(password, newHostUsername, newHostUsernameId)
.then(() => {
setTransferHostModalOpen(false);
successAlert({
id: 'studio.alertTransfer',
values: {name: newHostUsername}
});
})
.catch(() => {
setTransferHostModalOpen(false);
errorAlert({
id: 'studio.transfer.alert.somethingWentWrong'
});
});
}}
/>
}
</div>
......@@ -163,7 +146,6 @@ StudioMemberTile.propTypes = {
canTransferHost: PropTypes.bool,
onRemove: PropTypes.func,
onPromote: PropTypes.func,
onTransferHost: PropTypes.func,
username: PropTypes.string,
image: PropTypes.string,
isCreator: PropTypes.bool,
......@@ -179,8 +161,7 @@ const ManagerTile = connect(
isCreator: state.studio.owner === ownProps.id
}),
{
onRemove: removeManager,
onTransferHost: transferHost
onRemove: removeManager
}
)(StudioMemberTile);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment