mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-29 05:00:43 +10:00
Merge pull request #506 from sharetribe/refactoring-error-storing
Refactoring error storing
This commit is contained in:
commit
50dd6d05fc
54 changed files with 319 additions and 193 deletions
|
|
@ -67,6 +67,30 @@ const template = params => {
|
|||
return templateTags(templatedWithHtmlAttributes)(tags);
|
||||
};
|
||||
|
||||
//
|
||||
// Clean Error details when stringifying Error.
|
||||
//
|
||||
const cleanErrorValue = value => {
|
||||
// This should not happen
|
||||
// Pick only selected few values to be stringified if Error object is encountered.
|
||||
// Other values might contain circular structures
|
||||
// (SDK's Axios library might add ctx and config which has such structures)
|
||||
if (value instanceof Error) {
|
||||
const { name, message, status, statusText, apiErrors } = value;
|
||||
return { type: 'error', name, message, status, statusText, apiErrors };
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
//
|
||||
// JSON replacer
|
||||
// This stringifies SDK types and errors.
|
||||
//
|
||||
const replacer = (key = null, value) => {
|
||||
const cleanedValue = cleanErrorValue(value);
|
||||
return types.replacer(key, cleanedValue);
|
||||
};
|
||||
|
||||
exports.render = function(requestUrl, context, preloadedState) {
|
||||
const { head, body } = renderApp(requestUrl, context, preloadedState);
|
||||
|
||||
|
|
@ -74,7 +98,7 @@ exports.render = function(requestUrl, context, preloadedState) {
|
|||
// For security reasons we ensure that preloaded state is considered as a string
|
||||
// by replacing '<' character with its unicode equivalent.
|
||||
// http://redux.js.org/docs/recipes/ServerRendering.html#security-considerations
|
||||
const serializedState = JSON.stringify(preloadedState, types.replacer).replace(/</g, '\\u003c');
|
||||
const serializedState = JSON.stringify(preloadedState, replacer).replace(/</g, '\\u003c');
|
||||
|
||||
// At this point the serializedState is a string, the second
|
||||
// JSON.stringify wraps it within double quotes and escapes the
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
|
|||
import classNames from 'classnames';
|
||||
import config from '../../config';
|
||||
import { canonicalURL, metaTagProps } from '../../util/seo';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
|
||||
import facebookImage from '../../assets/saunatimeFacebook-1200x630.jpg';
|
||||
import twitterImage from '../../assets/saunatimeTwitter-600x314.jpg';
|
||||
|
|
@ -164,7 +165,7 @@ class PageComponent extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
const { any, arrayOf, bool, func, instanceOf, number, shape, string } = PropTypes;
|
||||
const { any, arrayOf, bool, func, number, shape, string } = PropTypes;
|
||||
|
||||
PageComponent.defaultProps = {
|
||||
className: null,
|
||||
|
|
@ -190,8 +191,8 @@ PageComponent.propTypes = {
|
|||
className: string,
|
||||
rootClassName: string,
|
||||
children: any,
|
||||
authInfoError: instanceOf(Error),
|
||||
logoutError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
logoutError: propTypes.error,
|
||||
scrollingDisabled: bool,
|
||||
|
||||
// SEO related props
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ SaleDetailsPanelComponent.defaultProps = {
|
|||
declineSaleError: null,
|
||||
};
|
||||
|
||||
const { string, func, bool, instanceOf } = PropTypes;
|
||||
const { bool, func, string } = PropTypes;
|
||||
|
||||
SaleDetailsPanelComponent.propTypes = {
|
||||
rootClassName: string,
|
||||
|
|
@ -277,8 +277,8 @@ SaleDetailsPanelComponent.propTypes = {
|
|||
onDeclineSale: func.isRequired,
|
||||
acceptInProgress: bool.isRequired,
|
||||
declineInProgress: bool.isRequired,
|
||||
acceptSaleError: instanceOf(Error),
|
||||
declineSaleError: instanceOf(Error),
|
||||
acceptSaleError: propTypes.error,
|
||||
declineSaleError: propTypes.error,
|
||||
|
||||
// from injectIntl
|
||||
intl: intlShape.isRequired,
|
||||
|
|
|
|||
|
|
@ -354,7 +354,7 @@ TopbarComponent.defaultProps = {
|
|||
sendVerificationEmailError: null,
|
||||
};
|
||||
|
||||
const { bool, func, instanceOf, number, shape, string } = PropTypes;
|
||||
const { bool, func, number, shape, string } = PropTypes;
|
||||
|
||||
TopbarComponent.propTypes = {
|
||||
className: string,
|
||||
|
|
@ -373,7 +373,7 @@ TopbarComponent.propTypes = {
|
|||
onManageDisableScrolling: func.isRequired,
|
||||
onResendVerificationEmail: func.isRequired,
|
||||
sendVerificationEmailInProgress: bool.isRequired,
|
||||
sendVerificationEmailError: instanceOf(Error),
|
||||
sendVerificationEmailError: propTypes.error,
|
||||
|
||||
// These are passed from Page to keep Topbar rendering aware of location changes
|
||||
history: shape({
|
||||
|
|
|
|||
|
|
@ -236,23 +236,23 @@ AuthenticationPageComponent.defaultProps = {
|
|||
sendVerificationEmailError: null,
|
||||
};
|
||||
|
||||
const { bool, func, instanceOf, object, oneOf, shape } = PropTypes;
|
||||
const { bool, func, object, oneOf, shape } = PropTypes;
|
||||
|
||||
AuthenticationPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
authInProgress: bool.isRequired,
|
||||
currentUser: propTypes.currentUser,
|
||||
isAuthenticated: bool.isRequired,
|
||||
loginError: instanceOf(Error),
|
||||
logoutError: instanceOf(Error),
|
||||
loginError: propTypes.error,
|
||||
logoutError: propTypes.error,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
signupError: instanceOf(Error),
|
||||
signupError: propTypes.error,
|
||||
submitLogin: func.isRequired,
|
||||
submitSignup: func.isRequired,
|
||||
tab: oneOf(['login', 'signup']),
|
||||
|
||||
sendVerificationEmailInProgress: bool.isRequired,
|
||||
sendVerificationEmailError: instanceOf(Error),
|
||||
sendVerificationEmailError: propTypes.error,
|
||||
onResendVerificationEmail: func.isRequired,
|
||||
|
||||
// from withRouter
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { pick } from 'lodash';
|
||||
import { updatedEntities, denormalisedEntities } from '../../util/data';
|
||||
import { storableError } from '../../util/errors';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import * as log from '../../util/log';
|
||||
import { fetchCurrentUserHasOrdersSuccess } from '../../ducks/user.duck';
|
||||
|
|
@ -118,7 +119,7 @@ export const initiateOrder = params => (dispatch, getState, sdk) => {
|
|||
return orderId;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(initiateOrderError(e));
|
||||
dispatch(initiateOrderError(storableError(e)));
|
||||
log.error(e, 'initiate-order-failed', {
|
||||
listingId: params.listingId.uuid,
|
||||
bookingStart: params.bookingStart,
|
||||
|
|
@ -174,6 +175,6 @@ export const speculateTransaction = (listingId, bookingStart, bookingEnd) => (
|
|||
bookingStart: bookingStart,
|
||||
bookingEnd: bookingEnd,
|
||||
});
|
||||
return dispatch(speculateTransactionError(e));
|
||||
return dispatch(speculateTransactionError(storableError(e)));
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -385,7 +385,7 @@ CheckoutPageComponent.defaultProps = {
|
|||
const { func, instanceOf, shape, string, bool } = PropTypes;
|
||||
|
||||
CheckoutPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
listing: propTypes.listing,
|
||||
bookingDates: shape({
|
||||
bookingStart: instanceOf(Date).isRequired,
|
||||
|
|
@ -393,10 +393,10 @@ CheckoutPageComponent.propTypes = {
|
|||
}),
|
||||
fetchSpeculatedTransaction: func.isRequired,
|
||||
speculateTransactionInProgress: bool.isRequired,
|
||||
speculateTransactionError: instanceOf(Error),
|
||||
speculateTransactionError: propTypes.error,
|
||||
speculatedTransaction: propTypes.transaction,
|
||||
initiateOrderError: instanceOf(Error),
|
||||
logoutError: instanceOf(Error),
|
||||
initiateOrderError: propTypes.error,
|
||||
logoutError: propTypes.error,
|
||||
currentUser: propTypes.currentUser,
|
||||
params: shape({
|
||||
id: string,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { compose } from 'redux';
|
|||
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
|
||||
import { reduxForm, propTypes as formPropTypes } from 'redux-form';
|
||||
import classNames from 'classnames';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import * as validators from '../../util/validators';
|
||||
import { ensureCurrentUser } from '../../util/data';
|
||||
import {
|
||||
|
|
@ -264,18 +265,18 @@ ContactDetailsFormComponent.defaultProps = {
|
|||
sendVerificationEmailInProgress: false,
|
||||
};
|
||||
|
||||
const { bool, func, instanceOf, string } = PropTypes;
|
||||
const { bool, func, string } = PropTypes;
|
||||
|
||||
ContactDetailsFormComponent.propTypes = {
|
||||
...formPropTypes,
|
||||
rootClassName: string,
|
||||
className: string,
|
||||
changeEmailError: instanceOf(Error),
|
||||
changeEmailError: propTypes.error,
|
||||
inProgress: bool,
|
||||
intl: intlShape.isRequired,
|
||||
onResendVerificationEmail: func.isRequired,
|
||||
ready: bool.isRequired,
|
||||
sendVerificationEmailError: instanceOf(Error),
|
||||
sendVerificationEmailError: propTypes.error,
|
||||
sendVerificationEmailInProgress: bool,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { storableError } from '../../util/errors';
|
||||
import { currentUserShowSuccess } from '../../ducks/user.duck';
|
||||
|
||||
// ================ Action types ================ //
|
||||
|
|
@ -64,5 +65,5 @@ export const changeEmail = params => (dispatch, getState, sdk) => {
|
|||
dispatch(changeEmailSuccess());
|
||||
dispatch(currentUserShowSuccess(currentUser));
|
||||
})
|
||||
.catch(e => dispatch(changeEmailError(e)));
|
||||
.catch(e => dispatch(changeEmailError(storableError(e))));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -112,20 +112,20 @@ ContactDetailsPageComponent.defaultProps = {
|
|||
sendVerificationEmailError: null,
|
||||
};
|
||||
|
||||
const { bool, func, instanceOf } = PropTypes;
|
||||
const { bool, func } = PropTypes;
|
||||
|
||||
ContactDetailsPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
changeEmailError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
changeEmailError: propTypes.error,
|
||||
changeEmailInProgress: bool.isRequired,
|
||||
currentUser: propTypes.currentUser,
|
||||
emailChanged: bool.isRequired,
|
||||
logoutError: instanceOf(Error),
|
||||
logoutError: propTypes.error,
|
||||
onChange: func.isRequired,
|
||||
onSubmitChangeEmail: func.isRequired,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
sendVerificationEmailInProgress: bool.isRequired,
|
||||
sendVerificationEmailError: instanceOf(Error),
|
||||
sendVerificationEmailError: propTypes.error,
|
||||
onResendVerificationEmail: func.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { compose } from 'redux';
|
|||
import { reduxForm, propTypes as formPropTypes } from 'redux-form';
|
||||
import { intlShape, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { maxLength, required } from '../../util/validators';
|
||||
import { Form, Button, TextInputField } from '../../components';
|
||||
|
||||
|
|
@ -99,7 +100,7 @@ const EditListingDescriptionFormComponent = props => {
|
|||
|
||||
EditListingDescriptionFormComponent.defaultProps = { className: null, updateError: null };
|
||||
|
||||
const { func, string, bool, instanceOf } = PropTypes;
|
||||
const { bool, func, string } = PropTypes;
|
||||
|
||||
EditListingDescriptionFormComponent.propTypes = {
|
||||
...formPropTypes,
|
||||
|
|
@ -108,7 +109,7 @@ EditListingDescriptionFormComponent.propTypes = {
|
|||
onSubmit: func.isRequired,
|
||||
saveActionMsg: string.isRequired,
|
||||
updated: bool.isRequired,
|
||||
updateError: instanceOf(Error),
|
||||
updateError: propTypes.error,
|
||||
updateInProgress: bool.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ EditListingLocationFormComponent.defaultProps = {
|
|||
updateError: null,
|
||||
};
|
||||
|
||||
const { func, string, bool, instanceOf } = PropTypes;
|
||||
const { func, string, bool } = PropTypes;
|
||||
|
||||
EditListingLocationFormComponent.propTypes = {
|
||||
...formPropTypes,
|
||||
|
|
@ -108,7 +108,7 @@ EditListingLocationFormComponent.propTypes = {
|
|||
saveActionMsg: string.isRequired,
|
||||
selectedPlace: propTypes.place,
|
||||
updated: bool.isRequired,
|
||||
updateError: instanceOf(Error),
|
||||
updateError: propTypes.error,
|
||||
updateInProgress: bool.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { omit, omitBy, isUndefined } from 'lodash';
|
||||
import { types } from '../../util/sdkLoader';
|
||||
import { storableError } from '../../util/errors';
|
||||
import { addMarketplaceEntities } from '../../ducks/marketplaceData.duck';
|
||||
import * as log from '../../util/log';
|
||||
import { fetchCurrentUserHasListingsSuccess } from '../../ducks/user.duck';
|
||||
|
|
@ -245,7 +246,7 @@ export function requestShowListing(actionPayload) {
|
|||
dispatch(showListingsSuccess(response));
|
||||
return response;
|
||||
})
|
||||
.catch(e => dispatch(showListingsError(e)));
|
||||
.catch(e => dispatch(showListingsError(storableError(e))));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -281,7 +282,7 @@ export function requestCreateListing(data) {
|
|||
})
|
||||
.catch(e => {
|
||||
log.error(e, 'create-listing-failed', { listingData: cleanedData });
|
||||
return dispatch(createListingError(e));
|
||||
return dispatch(createListingError(storableError(e)));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
@ -294,7 +295,7 @@ export function requestImageUpload(actionPayload) {
|
|||
return sdk.images
|
||||
.uploadListingImage({ image: actionPayload.file })
|
||||
.then(resp => dispatch(uploadImageSuccess({ data: { id, imageId: resp.data.data.id } })))
|
||||
.catch(e => dispatch(uploadImageError({ id, error: e })));
|
||||
.catch(e => dispatch(uploadImageError({ id, error: storableError(e) })));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -320,7 +321,7 @@ export function requestUpdateListing(tab, data) {
|
|||
})
|
||||
.catch(e => {
|
||||
log.error(e, 'update-listing-failed', { listingData: cleanedData });
|
||||
return dispatch(updateListingError(e));
|
||||
return dispatch(updateListingError(storableError(e)));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,15 +177,15 @@ EditListingPageComponent.defaultProps = {
|
|||
sendVerificationEmailError: null,
|
||||
};
|
||||
|
||||
const { bool, func, instanceOf, object, shape, string, oneOf } = PropTypes;
|
||||
const { bool, func, object, shape, string, oneOf } = PropTypes;
|
||||
|
||||
EditListingPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
createStripeAccountError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
createStripeAccountError: propTypes.error,
|
||||
currentUser: propTypes.currentUser,
|
||||
fetchInProgress: bool.isRequired,
|
||||
getListing: func.isRequired,
|
||||
logoutError: instanceOf(Error),
|
||||
logoutError: propTypes.error,
|
||||
onCreateListing: func.isRequired,
|
||||
onCreateListingDraft: func.isRequired,
|
||||
onImageUpload: func.isRequired,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
|
|||
import { isEqual } from 'lodash';
|
||||
import { arrayMove } from 'react-sortable-hoc';
|
||||
import classNames from 'classnames';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { noEmptyArray } from '../../util/validators';
|
||||
import { isUploadListingImageOverLimitError } from '../../util/errors';
|
||||
import { Form, AddImages, Button, ValidationError } from '../../components';
|
||||
|
|
@ -31,7 +32,7 @@ const RenderAddImage = props => {
|
|||
);
|
||||
};
|
||||
|
||||
const { func, node, object, shape, string, bool, instanceOf } = PropTypes;
|
||||
const { bool, func, node, object, shape, string } = PropTypes;
|
||||
|
||||
RenderAddImage.propTypes = {
|
||||
accept: string.isRequired,
|
||||
|
|
@ -231,7 +232,7 @@ EditListingPhotosFormComponent.propTypes = {
|
|||
saveActionMsg: string.isRequired,
|
||||
updated: bool.isRequired,
|
||||
ready: bool.isRequired,
|
||||
updateError: instanceOf(Error),
|
||||
updateError: propTypes.error,
|
||||
updateInProgress: bool.isRequired,
|
||||
onRemoveImage: func.isRequired,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { reduxForm, propTypes as formPropTypes } from 'redux-form';
|
|||
import { intlShape, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import config from '../../config';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { required } from '../../util/validators';
|
||||
import { Form, Button, CurrencyInputField } from '../../components';
|
||||
|
||||
|
|
@ -70,7 +71,7 @@ export const EditListingPricingFormComponent = props => {
|
|||
|
||||
EditListingPricingFormComponent.defaultProps = { updateError: null };
|
||||
|
||||
const { func, string, bool, instanceOf } = PropTypes;
|
||||
const { bool, func, string } = PropTypes;
|
||||
|
||||
EditListingPricingFormComponent.propTypes = {
|
||||
...formPropTypes,
|
||||
|
|
@ -78,7 +79,7 @@ EditListingPricingFormComponent.propTypes = {
|
|||
onSubmit: func.isRequired,
|
||||
saveActionMsg: string.isRequired,
|
||||
updated: bool.isRequired,
|
||||
updateError: instanceOf(Error),
|
||||
updateError: propTypes.error,
|
||||
updateInProgress: bool.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -94,13 +94,13 @@ EmailVerificationFormComponent.defaultProps = {
|
|||
verificationError: null,
|
||||
};
|
||||
|
||||
const { instanceOf, bool } = PropTypes;
|
||||
const { bool } = PropTypes;
|
||||
|
||||
EmailVerificationFormComponent.propTypes = {
|
||||
...formPropTypes,
|
||||
inProgress: bool,
|
||||
currentUser: propTypes.currentUser.isRequired,
|
||||
verificationError: instanceOf(Error),
|
||||
verificationError: propTypes.error,
|
||||
};
|
||||
|
||||
const defaultFormName = 'EmailVerificationForm';
|
||||
|
|
|
|||
|
|
@ -87,16 +87,16 @@ EmailVerificationPageComponent.defaultProps = {
|
|||
verificationError: null,
|
||||
};
|
||||
|
||||
const { bool, func, instanceOf, shape, string } = PropTypes;
|
||||
const { bool, func, shape, string } = PropTypes;
|
||||
|
||||
EmailVerificationPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
currentUser: propTypes.currentUser,
|
||||
logoutError: instanceOf(Error),
|
||||
logoutError: propTypes.error,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
submitVerification: func.isRequired,
|
||||
emailVerificationInProgress: bool.isRequired,
|
||||
verificationError: instanceOf(Error),
|
||||
verificationError: propTypes.error,
|
||||
|
||||
// from withRouter
|
||||
location: shape({
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { reverse, sortBy } from 'lodash';
|
||||
import { storableError } from '../../util/errors';
|
||||
import { parse } from '../../util/urlHelpers';
|
||||
import { addMarketplaceEntities } from '../../ducks/marketplaceData.duck';
|
||||
|
||||
|
|
@ -102,7 +103,7 @@ export const loadData = (params, search) => (dispatch, getState, sdk) => {
|
|||
return response;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(fetchOrdersOrSalesError(e));
|
||||
dispatch(fetchOrdersOrSalesError(storableError(e)));
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import { TopbarContainer } from '../../containers';
|
|||
import { loadData } from './InboxPage.duck';
|
||||
import css from './InboxPage.css';
|
||||
|
||||
const { arrayOf, bool, instanceOf, number, oneOf, shape, string } = PropTypes;
|
||||
const { arrayOf, bool, number, oneOf, shape, string } = PropTypes;
|
||||
|
||||
const formatDate = (intl, date) => {
|
||||
return {
|
||||
|
|
@ -303,11 +303,11 @@ InboxPageComponent.propTypes = {
|
|||
tab: string.isRequired,
|
||||
}).isRequired,
|
||||
|
||||
authInfoError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
currentUser: propTypes.currentUser,
|
||||
fetchInProgress: bool.isRequired,
|
||||
fetchOrdersOrSalesError: instanceOf(Error),
|
||||
logoutError: instanceOf(Error),
|
||||
fetchOrdersOrSalesError: propTypes.error,
|
||||
logoutError: propTypes.error,
|
||||
pagination: propTypes.pagination,
|
||||
providerNotificationCount: number,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { compose } from 'redux';
|
|||
import { connect } from 'react-redux';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { injectIntl, intlShape } from 'react-intl';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { isScrollingDisabled } from '../../ducks/UI.duck';
|
||||
import config from '../../config';
|
||||
import { Page, HeroSection } from '../../components';
|
||||
|
|
@ -60,11 +61,11 @@ LandingPageComponent.defaultProps = {
|
|||
logoutError: null,
|
||||
};
|
||||
|
||||
const { bool, instanceOf, object } = PropTypes;
|
||||
const { bool, object } = PropTypes;
|
||||
|
||||
LandingPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
logoutError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
logoutError: propTypes.error,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
|
||||
// from withRouter
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { storableError } from '../../util/errors';
|
||||
import { addMarketplaceEntities } from '../../ducks/marketplaceData.duck';
|
||||
import { fetchCurrentUser } from '../../ducks/user.duck';
|
||||
|
||||
|
|
@ -50,6 +51,6 @@ export const showListing = listingId => (dispatch, getState, sdk) => {
|
|||
return data;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(showListingError(e));
|
||||
dispatch(showListingError(storableError(e)));
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ export const ActionBar = props => {
|
|||
}
|
||||
};
|
||||
|
||||
const { bool, func, instanceOf, object, oneOf, shape, string } = PropTypes;
|
||||
const { bool, func, object, oneOf, shape, string } = PropTypes;
|
||||
|
||||
ActionBar.propTypes = {
|
||||
isOwnListing: bool.isRequired,
|
||||
|
|
@ -495,13 +495,13 @@ ListingPageComponent.propTypes = {
|
|||
id: string.isRequired,
|
||||
slug: string,
|
||||
}).isRequired,
|
||||
authInfoError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
currentUser: propTypes.currentUser,
|
||||
getListing: func.isRequired,
|
||||
logoutError: instanceOf(Error),
|
||||
logoutError: propTypes.error,
|
||||
onManageDisableScrolling: func.isRequired,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
showListingError: instanceOf(Error),
|
||||
showListingError: propTypes.error,
|
||||
tab: oneOf(['book', 'listing']),
|
||||
useInitialValues: func.isRequired,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { shallow } from 'enzyme';
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
import { types } from '../../util/sdkLoader';
|
||||
import { createUser, createCurrentUser, createListing, fakeIntl } from '../../util/test-data';
|
||||
import { storableError } from '../../util/errors';
|
||||
import { renderShallow } from '../../util/test-helpers';
|
||||
import { addMarketplaceEntities } from '../../ducks/marketplaceData.duck';
|
||||
import { showListingRequest, showListingError, showListing } from './ListingPage.duck';
|
||||
|
|
@ -84,7 +85,7 @@ describe('ListingPage', () => {
|
|||
expect(dispatch.mock.calls).toEqual([
|
||||
[showListingRequest(id)],
|
||||
[expect.anything()], // fetchCurrentUser() call
|
||||
[showListingError(error)],
|
||||
[showListingError(storableError(error))],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { updatedEntities, denormalisedEntities } from '../../util/data';
|
||||
import { storableError } from '../../util/errors';
|
||||
|
||||
// ================ Action types ================ //
|
||||
|
||||
|
|
@ -246,7 +247,7 @@ export const queryOwnListings = queryParams => (dispatch, getState, sdk) => {
|
|||
return response;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(queryListingsError(e));
|
||||
dispatch(queryListingsError(storableError(e)));
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
|
@ -261,7 +262,7 @@ export const closeListing = listingId => (dispatch, getState, sdk) => {
|
|||
return response;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(closeListingError(e));
|
||||
dispatch(closeListingError(storableError(e)));
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -275,6 +276,6 @@ export const openListing = listingId => (dispatch, getState, sdk) => {
|
|||
return response;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(openListingError(e));
|
||||
dispatch(openListingError(storableError(e)));
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -152,27 +152,27 @@ ManageListingsPageComponent.defaultProps = {
|
|||
openingListingError: null,
|
||||
};
|
||||
|
||||
const { arrayOf, bool, func, instanceOf, object, shape, string } = PropTypes;
|
||||
const { arrayOf, bool, func, object, shape, string } = PropTypes;
|
||||
|
||||
ManageListingsPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
closingListing: shape({ uuid: string.isRequired }),
|
||||
closingListingError: shape({
|
||||
listingId: propTypes.uuid.isRequired,
|
||||
error: instanceOf(Error).isRequired,
|
||||
error: propTypes.error.isRequired,
|
||||
}),
|
||||
listings: arrayOf(propTypes.listing),
|
||||
logoutError: instanceOf(Error),
|
||||
logoutError: propTypes.error,
|
||||
onCloseListing: func.isRequired,
|
||||
onOpenListing: func.isRequired,
|
||||
openingListing: shape({ uuid: string.isRequired }),
|
||||
openingListingError: shape({
|
||||
listingId: propTypes.uuid.isRequired,
|
||||
error: instanceOf(Error).isRequired,
|
||||
error: propTypes.error.isRequired,
|
||||
}),
|
||||
pagination: propTypes.pagination,
|
||||
queryInProgress: bool.isRequired,
|
||||
queryListingsError: instanceOf(Error),
|
||||
queryListingsError: propTypes.error,
|
||||
queryParams: object,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { compose } from 'redux';
|
|||
import { connect } from 'react-redux';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import routeConfiguration from '../../routeConfiguration';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { createResourceLocatorString } from '../../util/routes';
|
||||
import { isScrollingDisabled } from '../../ducks/UI.duck';
|
||||
import { Page } from '../../components';
|
||||
|
|
@ -68,11 +69,11 @@ NotFoundPageComponent.defaultProps = {
|
|||
staticContext: {},
|
||||
};
|
||||
|
||||
const { bool, func, instanceOf, object, shape } = PropTypes;
|
||||
const { bool, func, object, shape } = PropTypes;
|
||||
|
||||
NotFoundPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
logoutError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
logoutError: propTypes.error,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
|
||||
// context object from StaticRouter, injected by the withRouter wrapper
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { types } from '../../util/sdkLoader';
|
||||
import { storableError } from '../../util/errors';
|
||||
import { addMarketplaceEntities } from '../../ducks/marketplaceData.duck';
|
||||
import { updatedEntities, denormalisedEntities } from '../../util/data';
|
||||
|
||||
|
|
@ -79,7 +80,7 @@ export const fetchOrder = id => (dispatch, getState, sdk) => {
|
|||
return response;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(fetchOrderError(e));
|
||||
dispatch(fetchOrderError(storableError(e)));
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -87,14 +87,14 @@ OrderPageComponent.defaultProps = {
|
|||
transaction: null,
|
||||
};
|
||||
|
||||
const { bool, instanceOf, oneOf, shape, string } = PropTypes;
|
||||
const { bool, oneOf, shape, string } = PropTypes;
|
||||
|
||||
OrderPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
currentUser: propTypes.currentUser,
|
||||
fetchOrderError: instanceOf(Error),
|
||||
fetchOrderError: propTypes.error,
|
||||
intl: intlShape.isRequired,
|
||||
logoutError: instanceOf(Error),
|
||||
logoutError: propTypes.error,
|
||||
params: shape({ id: string }).isRequired,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
tab: oneOf(['details', 'discussion']).isRequired,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { compose } from 'redux';
|
|||
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
|
||||
import { reduxForm, propTypes as formPropTypes } from 'redux-form';
|
||||
import classNames from 'classnames';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import * as validators from '../../util/validators';
|
||||
import { ensureCurrentUser } from '../../util/data';
|
||||
import { isChangePasswordWrongPassword } from '../../util/errors';
|
||||
|
|
@ -183,13 +184,13 @@ PasswordChangeFormComponent.defaultProps = {
|
|||
inProgress: false,
|
||||
};
|
||||
|
||||
const { bool, instanceOf, string } = PropTypes;
|
||||
const { bool, string } = PropTypes;
|
||||
|
||||
PasswordChangeFormComponent.propTypes = {
|
||||
...formPropTypes,
|
||||
rootClassName: string,
|
||||
className: string,
|
||||
changePasswordError: instanceOf(Error),
|
||||
changePasswordError: propTypes.error,
|
||||
inProgress: bool,
|
||||
intl: intlShape.isRequired,
|
||||
ready: bool.isRequired,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { storableError } from '../../util/errors';
|
||||
|
||||
// ================ Action types ================ //
|
||||
|
||||
export const CHANGE_PASSWORD_REQUEST = 'app/PasswordChangePage/CHANGE_PASSWORD_REQUEST';
|
||||
|
|
@ -59,7 +61,7 @@ export const changePassword = params => (dispatch, getState, sdk) => {
|
|||
.changePassword({ newPassword, currentPassword })
|
||||
.then(() => dispatch(changePasswordSuccess()))
|
||||
.catch(e => {
|
||||
dispatch(changePasswordError(e));
|
||||
dispatch(changePasswordError(storableError(storableError(e))));
|
||||
// This is thrown so that form can be cleared
|
||||
// after a timeout on changePassword submit handler
|
||||
throw e;
|
||||
|
|
|
|||
|
|
@ -101,14 +101,14 @@ PasswordChangePageComponent.defaultProps = {
|
|||
logoutError: null,
|
||||
};
|
||||
|
||||
const { bool, func, instanceOf } = PropTypes;
|
||||
const { bool, func } = PropTypes;
|
||||
|
||||
PasswordChangePageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
changePasswordError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
changePasswordError: propTypes.error,
|
||||
changePasswordInProgress: bool.isRequired,
|
||||
currentUser: propTypes.currentUser,
|
||||
logoutError: instanceOf(Error),
|
||||
logoutError: propTypes.error,
|
||||
onChange: func.isRequired,
|
||||
onSubmitChangePassword: func.isRequired,
|
||||
passwordChanged: bool.isRequired,
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ import { compose } from 'redux';
|
|||
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
|
||||
import { reduxForm, propTypes as formPropTypes } from 'redux-form';
|
||||
import classNames from 'classnames';
|
||||
import { Form, PrimaryButton, TextInputField, NamedLink } from '../../components';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import * as validators from '../../util/validators';
|
||||
import { isPasswordRecoveryEmailNotFoundError } from '../../util/errors';
|
||||
import { Form, PrimaryButton, TextInputField, NamedLink } from '../../components';
|
||||
|
||||
import css from './PasswordRecoveryForm.css';
|
||||
|
||||
|
|
@ -96,7 +97,7 @@ PasswordRecoveryFormComponent.defaultProps = {
|
|||
recoveryError: null,
|
||||
};
|
||||
|
||||
const { instanceOf, string, bool } = PropTypes;
|
||||
const { bool, string } = PropTypes;
|
||||
|
||||
PasswordRecoveryFormComponent.propTypes = {
|
||||
...formPropTypes,
|
||||
|
|
@ -104,7 +105,7 @@ PasswordRecoveryFormComponent.propTypes = {
|
|||
className: string,
|
||||
|
||||
inProgress: bool,
|
||||
recoveryError: instanceOf(Error),
|
||||
recoveryError: propTypes.error,
|
||||
|
||||
// from injectIntl
|
||||
intl: intlShape.isRequired,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { storableError } from '../../util/errors';
|
||||
|
||||
// ================ Action types ================ //
|
||||
|
||||
export const RECOVERY_REQUEST = 'app/PasswordRecoveryPage/RECOVERY_REQUEST';
|
||||
|
|
@ -75,5 +77,5 @@ export const recoverPassword = email => (dispatch, getState, sdk) => {
|
|||
return sdk.passwordReset
|
||||
.request({ email })
|
||||
.then(() => dispatch(passwordRecoverySuccess(email)))
|
||||
.catch(error => dispatch(passwordRecoveryError(error, email)));
|
||||
.catch(e => dispatch(passwordRecoveryError(storableError(e), email)));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,19 +3,20 @@ import PropTypes from 'prop-types';
|
|||
import { compose } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import {
|
||||
isPasswordRecoveryEmailNotFoundError,
|
||||
isPasswordRecoveryEmailNotVerifiedError,
|
||||
} from '../../util/errors';
|
||||
import { isScrollingDisabled } from '../../ducks/UI.duck';
|
||||
import { Page, InlineTextButton, IconKeys } from '../../components';
|
||||
import { PasswordRecoveryForm, TopbarContainer } from '../../containers';
|
||||
|
||||
import {
|
||||
recoverPassword,
|
||||
retypePasswordRecoveryEmail,
|
||||
clearPasswordRecoveryError,
|
||||
} from './PasswordRecoveryPage.duck';
|
||||
import { Page, InlineTextButton, IconKeys } from '../../components';
|
||||
import { PasswordRecoveryForm, TopbarContainer } from '../../containers';
|
||||
|
||||
import DoorIcon from './DoorIcon';
|
||||
import css from './PasswordRecoveryPage.css';
|
||||
|
||||
|
|
@ -166,14 +167,14 @@ PasswordRecoveryPageComponent.defaultProps = {
|
|||
recoveryError: null,
|
||||
};
|
||||
|
||||
const { bool, func, instanceOf, string } = PropTypes;
|
||||
const { bool, func, string } = PropTypes;
|
||||
|
||||
PasswordRecoveryPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
logoutError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
logoutError: propTypes.error,
|
||||
initialEmail: string,
|
||||
submittedEmail: string,
|
||||
recoveryError: instanceOf(Error),
|
||||
recoveryError: propTypes.error,
|
||||
recoveryInProgress: bool.isRequired,
|
||||
passwordRequested: bool.isRequired,
|
||||
onChange: func.isRequired,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { storableError } from '../../util/errors';
|
||||
|
||||
// ================ Action types ================ //
|
||||
|
||||
export const RESET_PASSWORD_REQUEST = 'app/PasswordResetPage/RESET_PASSWORD_REQUEST';
|
||||
|
|
@ -50,5 +52,5 @@ export const resetPassword = (email, passwordResetToken, newPassword) => (
|
|||
return sdk.passwordReset
|
||||
.reset(params)
|
||||
.then(() => dispatch(resetPasswordSuccess()))
|
||||
.catch(e => dispatch(resetPasswordError(e)));
|
||||
.catch(e => dispatch(resetPasswordError(storableError(e))));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@ import { compose } from 'redux';
|
|||
import { connect } from 'react-redux';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
|
||||
import { isScrollingDisabled } from '../../ducks/UI.duck';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { parse } from '../../util/urlHelpers';
|
||||
import { isScrollingDisabled } from '../../ducks/UI.duck';
|
||||
import { Page, NamedLink, IconKeys, IconKeysSuccess } from '../../components';
|
||||
import { PasswordResetForm, TopbarContainer } from '../../containers';
|
||||
|
||||
|
|
@ -130,14 +131,14 @@ PasswordResetPageComponent.defaultProps = {
|
|||
resetPasswordError: null,
|
||||
};
|
||||
|
||||
const { bool, func, instanceOf, shape, string } = PropTypes;
|
||||
const { bool, func, shape, string } = PropTypes;
|
||||
|
||||
PasswordResetPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
logoutError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
logoutError: propTypes.error,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
resetPasswordInProgress: bool.isRequired,
|
||||
resetPasswordError: instanceOf(Error),
|
||||
resetPasswordError: propTypes.error,
|
||||
onSubmitPassword: func.isRequired,
|
||||
|
||||
// from withRouter
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import { compose } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { isScrollingDisabled } from '../../ducks/UI.duck';
|
||||
import { Page } from '../../components';
|
||||
import { TopbarContainer } from '../../containers';
|
||||
|
|
@ -26,11 +27,11 @@ PayoutPreferencesPageComponent.defaultProps = {
|
|||
logoutError: null,
|
||||
};
|
||||
|
||||
const { bool, instanceOf } = PropTypes;
|
||||
const { bool } = PropTypes;
|
||||
|
||||
PayoutPreferencesPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
logoutError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
logoutError: propTypes.error,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import { compose } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { isScrollingDisabled } from '../../ducks/UI.duck';
|
||||
import { Page } from '../../components';
|
||||
import { TopbarContainer } from '../../containers';
|
||||
|
|
@ -26,11 +27,11 @@ ProfilePageComponent.defaultProps = {
|
|||
logoutError: null,
|
||||
};
|
||||
|
||||
const { bool, instanceOf, shape, string } = PropTypes;
|
||||
const { bool, shape, string } = PropTypes;
|
||||
|
||||
ProfilePageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
logoutError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
logoutError: propTypes.error,
|
||||
params: shape({ displayName: string.isRequired }).isRequired,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
|
|||
import { Field, reduxForm, propTypes as formPropTypes } from 'redux-form';
|
||||
import classNames from 'classnames';
|
||||
import { ensureCurrentUser } from '../../util/data';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import * as validators from '../../util/validators';
|
||||
import { isUploadProfileImageOverLimitError } from '../../util/errors';
|
||||
import { Form, Avatar, Button, ImageFromFile, IconSpinner, TextInputField } from '../../components';
|
||||
|
|
@ -60,7 +61,7 @@ const RenderAvatar = props => {
|
|||
};
|
||||
|
||||
RenderAvatar.defaultProps = { uploadImageError: null };
|
||||
const { bool, func, instanceOf, node, object, shape, string } = PropTypes;
|
||||
const { bool, func, node, object, shape, string } = PropTypes;
|
||||
|
||||
RenderAvatar.propTypes = {
|
||||
accept: string.isRequired,
|
||||
|
|
@ -73,7 +74,7 @@ RenderAvatar.propTypes = {
|
|||
}).isRequired,
|
||||
label: node.isRequired,
|
||||
type: string.isRequired,
|
||||
uploadImageError: instanceOf(Error),
|
||||
uploadImageError: propTypes.error,
|
||||
};
|
||||
|
||||
class ProfileSettingsFormComponent extends Component {
|
||||
|
|
@ -293,10 +294,10 @@ ProfileSettingsFormComponent.propTypes = {
|
|||
rootClassName: string,
|
||||
className: string,
|
||||
|
||||
uploadImageError: instanceOf(Error),
|
||||
uploadImageError: propTypes.error,
|
||||
uploadInProgress: bool.isRequired,
|
||||
updateInProgress: bool.isRequired,
|
||||
updateProfileError: instanceOf(Error),
|
||||
updateProfileError: propTypes.error,
|
||||
updateProfileReady: bool,
|
||||
|
||||
// from injectIntl
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { updatedEntities, denormalisedEntities } from '../../util/data';
|
||||
import { storableError } from '../../util/errors';
|
||||
import { currentUserShowSuccess } from '../../ducks/user.duck';
|
||||
|
||||
// ================ Action types ================ //
|
||||
|
|
@ -120,7 +121,7 @@ export function uploadImage(actionPayload) {
|
|||
const uploadedImage = resp.data.data;
|
||||
dispatch(uploadImageSuccess({ data: { id, uploadedImage } }));
|
||||
})
|
||||
.catch(e => dispatch(uploadImageError({ id, error: e })));
|
||||
.catch(e => dispatch(uploadImageError({ id, error: storableError(e) })));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -142,6 +143,6 @@ export const updateProfile = actionPayload => {
|
|||
// Update current user in state.user.currentUser through user.duck.js
|
||||
dispatch(currentUserShowSuccess(currentUser));
|
||||
})
|
||||
.catch(e => dispatch(updateProfileError(e)));
|
||||
.catch(e => dispatch(updateProfileError(storableError(e))));
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -114,10 +114,10 @@ ProfileSettingsPageComponent.defaultProps = {
|
|||
image: null,
|
||||
};
|
||||
|
||||
const { bool, func, instanceOf, object, shape, string } = PropTypes;
|
||||
const { bool, func, object, shape, string } = PropTypes;
|
||||
|
||||
ProfileSettingsPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
currentUser: propTypes.currentUser,
|
||||
image: shape({
|
||||
id: string,
|
||||
|
|
@ -125,14 +125,14 @@ ProfileSettingsPageComponent.propTypes = {
|
|||
file: object,
|
||||
uploadedImage: propTypes.image,
|
||||
}),
|
||||
logoutError: instanceOf(Error),
|
||||
logoutError: propTypes.error,
|
||||
onChange: func.isRequired,
|
||||
onImageUpload: func.isRequired,
|
||||
onUpdateProfile: func.isRequired,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
updateInProgress: bool.isRequired,
|
||||
updateProfileError: instanceOf(Error),
|
||||
uploadImageError: instanceOf(Error),
|
||||
updateProfileError: propTypes.error,
|
||||
uploadImageError: propTypes.error,
|
||||
uploadInProgress: bool.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { types } from '../../util/sdkLoader';
|
||||
import { storableError } from '../../util/errors';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import * as log from '../../util/log';
|
||||
import { addMarketplaceEntities } from '../../ducks/marketplaceData.duck';
|
||||
|
|
@ -122,7 +123,7 @@ export const fetchSale = id => (dispatch, getState, sdk) => {
|
|||
return response;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(fetchSaleError(e));
|
||||
dispatch(fetchSaleError(storableError(e)));
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
|
@ -142,7 +143,7 @@ export const acceptSale = id => (dispatch, getState, sdk) => {
|
|||
return response;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(acceptSaleError(e));
|
||||
dispatch(acceptSaleError(storableError(e)));
|
||||
log.error(e, 'accept-sale-failed', {
|
||||
txId: id,
|
||||
transition: propTypes.TX_TRANSITION_ACCEPT,
|
||||
|
|
@ -166,7 +167,7 @@ export const declineSale = id => (dispatch, getState, sdk) => {
|
|||
return response;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(declineSaleError(e));
|
||||
dispatch(declineSaleError(storableError(e)));
|
||||
log.error(e, 'redect-sale-failed', {
|
||||
txId: id,
|
||||
transition: propTypes.TX_TRANSITION_DECLINE,
|
||||
|
|
|
|||
|
|
@ -103,18 +103,18 @@ SalePageComponent.defaultProps = {
|
|||
transaction: null,
|
||||
};
|
||||
|
||||
const { bool, func, instanceOf, oneOf, shape, string } = PropTypes;
|
||||
const { bool, func, oneOf, shape, string } = PropTypes;
|
||||
|
||||
SalePageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
currentUser: propTypes.currentUser,
|
||||
fetchSaleError: instanceOf(Error),
|
||||
acceptSaleError: instanceOf(Error),
|
||||
declineSaleError: instanceOf(Error),
|
||||
fetchSaleError: propTypes.error,
|
||||
acceptSaleError: propTypes.error,
|
||||
declineSaleError: propTypes.error,
|
||||
acceptInProgress: bool.isRequired,
|
||||
declineInProgress: bool.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
logoutError: instanceOf(Error),
|
||||
logoutError: propTypes.error,
|
||||
onAcceptSale: func.isRequired,
|
||||
onDeclineSale: func.isRequired,
|
||||
params: shape({ id: string }).isRequired,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { unionWith } from 'lodash';
|
||||
import { storableError } from '../../util/errors';
|
||||
import { addMarketplaceEntities } from '../../ducks/marketplaceData.duck';
|
||||
|
||||
// ================ Action types ================ //
|
||||
|
|
@ -124,7 +125,7 @@ export const searchListings = searchParams => (dispatch, getState, sdk) => {
|
|||
return response;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(searchListingsError(e));
|
||||
dispatch(searchListingsError(storableError(e)));
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
|
@ -146,7 +147,7 @@ export const searchMapListings = searchParams => (dispatch, getState, sdk) => {
|
|||
return response;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(searchMapListingsError(e));
|
||||
dispatch(searchMapListingsError(storableError(e)));
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -354,19 +354,19 @@ SearchPageComponent.defaultProps = {
|
|||
tab: 'listings',
|
||||
};
|
||||
|
||||
const { array, bool, func, instanceOf, oneOf, object, shape, string } = PropTypes;
|
||||
const { array, bool, func, oneOf, object, shape, string } = PropTypes;
|
||||
|
||||
SearchPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
listings: array,
|
||||
mapListings: array,
|
||||
logoutError: instanceOf(Error),
|
||||
logoutError: propTypes.error,
|
||||
onManageDisableScrolling: func.isRequired,
|
||||
onSearchMapListings: func.isRequired,
|
||||
pagination: propTypes.pagination,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
searchInProgress: bool.isRequired,
|
||||
searchListingsError: instanceOf(Error),
|
||||
searchListingsError: propTypes.error,
|
||||
searchParams: object,
|
||||
tab: oneOf(['filters', 'listings', 'map']).isRequired,
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import { compose } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { isScrollingDisabled } from '../../ducks/UI.duck';
|
||||
import { Page } from '../../components';
|
||||
import { TopbarContainer } from '../../containers';
|
||||
|
|
@ -26,11 +27,11 @@ SecurityPageComponent.defaultProps = {
|
|||
logoutError: null,
|
||||
};
|
||||
|
||||
const { bool, instanceOf } = PropTypes;
|
||||
const { bool } = PropTypes;
|
||||
|
||||
SecurityPageComponent.propTypes = {
|
||||
authInfoError: instanceOf(Error),
|
||||
logoutError: instanceOf(Error),
|
||||
authInfoError: propTypes.error,
|
||||
logoutError: propTypes.error,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ TopbarContainerComponent.defaultProps = {
|
|||
sendVerificationEmailError: null,
|
||||
};
|
||||
|
||||
const { bool, func, instanceOf, number, object, shape } = PropTypes;
|
||||
const { bool, func, number, object, shape } = PropTypes;
|
||||
|
||||
TopbarContainerComponent.propTypes = {
|
||||
authInProgress: bool.isRequired,
|
||||
|
|
@ -66,7 +66,7 @@ TopbarContainerComponent.propTypes = {
|
|||
onLogout: func.isRequired,
|
||||
onManageDisableScrolling: func.isRequired,
|
||||
sendVerificationEmailInProgress: bool.isRequired,
|
||||
sendVerificationEmailError: instanceOf(Error),
|
||||
sendVerificationEmailError: propTypes.error,
|
||||
onResendVerificationEmail: func.isRequired,
|
||||
|
||||
// from withRouter
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { clearCurrentUser, fetchCurrentUser } from './user.duck';
|
||||
import { storableError } from '../util/errors';
|
||||
import * as log from '../util/log';
|
||||
|
||||
const authenticated = authInfo => authInfo.grantType === 'refresh_token';
|
||||
|
|
@ -124,7 +125,7 @@ export const authInfo = () => (dispatch, getState, sdk) => {
|
|||
return sdk
|
||||
.authInfo()
|
||||
.then(info => dispatch(authInfoSuccess(info)))
|
||||
.catch(e => dispatch(authInfoError(e)));
|
||||
.catch(e => dispatch(authInfoError(storableError(e))));
|
||||
};
|
||||
|
||||
export const login = (username, password) => (dispatch, getState, sdk) => {
|
||||
|
|
@ -139,7 +140,7 @@ export const login = (username, password) => (dispatch, getState, sdk) => {
|
|||
.login({ username, password })
|
||||
.then(() => dispatch(loginSuccess()))
|
||||
.then(() => dispatch(fetchCurrentUser()))
|
||||
.catch(e => dispatch(loginError(e)));
|
||||
.catch(e => dispatch(loginError(storableError(e))));
|
||||
};
|
||||
|
||||
export const logout = () => (dispatch, getState, sdk) => {
|
||||
|
|
@ -158,7 +159,7 @@ export const logout = () => (dispatch, getState, sdk) => {
|
|||
dispatch(userLogout());
|
||||
log.clearUserId();
|
||||
})
|
||||
.catch(e => dispatch(logoutError(e)));
|
||||
.catch(e => dispatch(logoutError(storableError(e))));
|
||||
};
|
||||
|
||||
export const signup = params => (dispatch, getState, sdk) => {
|
||||
|
|
@ -175,7 +176,7 @@ export const signup = params => (dispatch, getState, sdk) => {
|
|||
.then(() => dispatch(signupSuccess()))
|
||||
.then(() => dispatch(login(email, password)))
|
||||
.catch(e => {
|
||||
dispatch(signupError(e));
|
||||
dispatch(signupError(storableError(e)));
|
||||
log.error(e, 'signup-failed', {
|
||||
email: params.email,
|
||||
firstName: params.firstName,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { storableError } from '../util/errors';
|
||||
import { clearCurrentUser, currentUserShowRequest, currentUserShowSuccess } from './user.duck';
|
||||
import reducer, {
|
||||
authenticationInProgress,
|
||||
|
|
@ -222,7 +223,7 @@ describe('Auth duck', () => {
|
|||
|
||||
return login(username, password)(dispatch, getState, sdk).then(() => {
|
||||
expect(sdk.login.mock.calls).toEqual([[{ username, password }]]);
|
||||
expect(dispatch.mock.calls).toEqual([[loginRequest()], [loginError(error)]]);
|
||||
expect(dispatch.mock.calls).toEqual([[loginRequest()], [loginError(storableError(error))]]);
|
||||
});
|
||||
});
|
||||
it('should reject if another login is in progress', () => {
|
||||
|
|
@ -293,7 +294,10 @@ describe('Auth duck', () => {
|
|||
|
||||
return logout()(dispatch, getState, sdk).then(() => {
|
||||
expect(sdk.logout.mock.calls.length).toEqual(1);
|
||||
expect(dispatch.mock.calls).toEqual([[logoutRequest()], [logoutError(error)]]);
|
||||
expect(dispatch.mock.calls).toEqual([
|
||||
[logoutRequest()],
|
||||
[logoutError(storableError(error))],
|
||||
]);
|
||||
});
|
||||
});
|
||||
it('should reject if another logout is in progress', () => {
|
||||
|
|
@ -384,7 +388,10 @@ describe('Auth duck', () => {
|
|||
|
||||
return signup(params)(dispatch, getState, sdk).then(() => {
|
||||
expect(sdk.currentUser.create.mock.calls).toEqual([[params]]);
|
||||
expect(dispatchedActions(dispatch)).toEqual([signupRequest(), signupError(error)]);
|
||||
expect(dispatchedActions(dispatch)).toEqual([
|
||||
signupRequest(),
|
||||
signupError(storableError(error)),
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { storableError } from '../util/errors';
|
||||
import { fetchCurrentUser } from './user.duck';
|
||||
|
||||
// ================ Action types ================ //
|
||||
|
|
@ -64,5 +65,5 @@ export const verify = verificationToken => (dispatch, getState, sdk) => {
|
|||
.verifyEmail({ verificationToken })
|
||||
.then(() => dispatch(verificationSuccess()))
|
||||
.then(() => dispatch(fetchCurrentUser()))
|
||||
.catch(e => dispatch(verificationError(e)));
|
||||
.catch(e => dispatch(verificationError(storableError(e))));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { authInfo } from './Auth.duck';
|
||||
import { updatedEntities, denormalisedEntities } from '../util/data';
|
||||
import { storableError } from '../util/errors';
|
||||
import { TX_TRANSITION_PREAUTHORIZE } from '../util/propTypes';
|
||||
import * as log from '../util/log';
|
||||
import { authInfo } from './Auth.duck';
|
||||
|
||||
// ================ Action types ================ //
|
||||
|
||||
|
|
@ -268,7 +269,7 @@ export const fetchCurrentUserHasListings = () => (dispatch, getState, sdk) => {
|
|||
})
|
||||
.catch(e => {
|
||||
// TODO: dispatch flash message: "Something went wrong while retrieving user info"
|
||||
dispatch(fetchCurrentUserHasListingsError(e));
|
||||
dispatch(fetchCurrentUserHasListingsError(storableError(e)));
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -294,7 +295,7 @@ export const fetchCurrentUserHasOrders = () => (dispatch, getState, sdk) => {
|
|||
})
|
||||
.catch(e => {
|
||||
// TODO: dispatch flash message: "Something went wrong while retrieving user info"
|
||||
dispatch(fetchCurrentUserHasOrdersError(e));
|
||||
dispatch(fetchCurrentUserHasOrdersError(storableError(e)));
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -319,7 +320,7 @@ export const fetchCurrentUserNotifications = () => (dispatch, getState, sdk) =>
|
|||
})
|
||||
.catch(e => {
|
||||
// TODO: dispatch flash message: "Something went wrong while retrieving user info"
|
||||
dispatch(fetchCurrentUserNotificationsError(e));
|
||||
dispatch(fetchCurrentUserNotificationsError(storableError(e)));
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
|
@ -362,7 +363,7 @@ export const fetchCurrentUser = () => (dispatch, getState, sdk) => {
|
|||
dispatch(authInfo());
|
||||
|
||||
// TODO: dispatch flash message: "Something went wrong while retrieving user info"
|
||||
dispatch(currentUserShowError(e));
|
||||
dispatch(currentUserShowError(storableError(e)));
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -381,7 +382,7 @@ export const createStripeAccount = payoutDetails => (dispatch, getState, sdk) =>
|
|||
dispatch(stripeAccountCreateSuccess(accountResponse));
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(stripeAccountCreateError(e));
|
||||
dispatch(stripeAccountCreateError(storableError(e)));
|
||||
log.error(e, 'create-stripe-account-failed');
|
||||
throw e;
|
||||
});
|
||||
|
|
@ -395,5 +396,5 @@ export const sendVerificationEmail = () => (dispatch, getState, sdk) => {
|
|||
return sdk.currentUser
|
||||
.sendVerificationEmail()
|
||||
.then(() => dispatch(sendVerificationEmailSuccess()))
|
||||
.catch(e => dispatch(sendVerificationEmailError(e)));
|
||||
.catch(e => dispatch(sendVerificationEmailError(storableError(e))));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,35 +9,42 @@
|
|||
* name and the docstring of the function to ensure correct usage.
|
||||
*/
|
||||
|
||||
const ERROR_CODE_TRANSITION_PARAMETER_VALIDATION_FAILED = 'transition-parameter-validation-failed';
|
||||
const ERROR_CODE_PAYMENT_FAILED = 'transaction-payment-failed';
|
||||
const ERROR_CODE_EMAIL_TAKEN = 'email-taken';
|
||||
const ERROR_CODE_TOO_MANY_VERIFICATION_REQUESTS = 'email-too-many-verification-requests';
|
||||
const ERROR_CODE_UPLOAD_OVER_LIMIT = 'request-upload-over-limit';
|
||||
import {
|
||||
ERROR_CODE_TRANSITION_PARAMETER_VALIDATION_FAILED,
|
||||
ERROR_CODE_PAYMENT_FAILED,
|
||||
ERROR_CODE_EMAIL_TAKEN,
|
||||
ERROR_CODE_TOO_MANY_VERIFICATION_REQUESTS,
|
||||
ERROR_CODE_UPLOAD_OVER_LIMIT,
|
||||
} from './propTypes';
|
||||
|
||||
const responseErrors = apiError => {
|
||||
return apiError && apiError.data && apiError.data.errors ? apiError.data.errors : [];
|
||||
const errorAPIErrors = error => {
|
||||
return error && error.apiErrors ? error.apiErrors : [];
|
||||
};
|
||||
|
||||
const hasErrorWithCode = (apiError, code) => {
|
||||
return responseErrors(apiError).some(error => {
|
||||
return error.code === code;
|
||||
const hasErrorWithCode = (error, code) => {
|
||||
return errorAPIErrors(error).some(apiError => {
|
||||
return apiError.code === code;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* return apiErrors from error response
|
||||
*/
|
||||
const responseAPIErrors = error => {
|
||||
return error && error.data && error.data.errors ? error.data.errors : [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the given API error (from `sdk.currentuser.create()`) is
|
||||
* due to the email address already being in use.
|
||||
*/
|
||||
export const isSignupEmailTakenError = apiError =>
|
||||
hasErrorWithCode(apiError, ERROR_CODE_EMAIL_TAKEN);
|
||||
export const isSignupEmailTakenError = error => hasErrorWithCode(error, ERROR_CODE_EMAIL_TAKEN);
|
||||
|
||||
/**
|
||||
* Check if the given API error (from `sdk.currentuser.changeEmail()`) is
|
||||
* due to the email address already being in use.
|
||||
*/
|
||||
export const isChangeEmailTakenError = apiError =>
|
||||
hasErrorWithCode(apiError, ERROR_CODE_EMAIL_TAKEN);
|
||||
export const isChangeEmailTakenError = error => hasErrorWithCode(error, ERROR_CODE_EMAIL_TAKEN);
|
||||
|
||||
/**
|
||||
* Check if the given API error (from
|
||||
|
|
@ -48,45 +55,44 @@ export const isChangeEmailTakenError = apiError =>
|
|||
* allowed, and the user has to wait for them to expire to be able to
|
||||
* request sending new verification emails.
|
||||
*/
|
||||
export const isTooManyEmailVerificationRequestsError = apiError =>
|
||||
hasErrorWithCode(apiError, ERROR_CODE_TOO_MANY_VERIFICATION_REQUESTS);
|
||||
export const isTooManyEmailVerificationRequestsError = error =>
|
||||
hasErrorWithCode(error, ERROR_CODE_TOO_MANY_VERIFICATION_REQUESTS);
|
||||
|
||||
/**
|
||||
* Check if the given API error (from
|
||||
* `sdk.images.uploadListingImage()`) is due to the image being over
|
||||
* the size limit.
|
||||
*/
|
||||
export const isUploadListingImageOverLimitError = apiError =>
|
||||
hasErrorWithCode(apiError, ERROR_CODE_UPLOAD_OVER_LIMIT);
|
||||
export const isUploadListingImageOverLimitError = error =>
|
||||
hasErrorWithCode(error, ERROR_CODE_UPLOAD_OVER_LIMIT);
|
||||
|
||||
/**
|
||||
* Check if the given API error (from
|
||||
* `sdk.images.uploadProfileImage()`) is due to the image being over
|
||||
* the size limit.
|
||||
*/
|
||||
export const isUploadProfileImageOverLimitError = apiError =>
|
||||
hasErrorWithCode(apiError, ERROR_CODE_UPLOAD_OVER_LIMIT);
|
||||
export const isUploadProfileImageOverLimitError = error =>
|
||||
hasErrorWithCode(error, ERROR_CODE_UPLOAD_OVER_LIMIT);
|
||||
|
||||
/**
|
||||
* Check if the given API error (from `sdk.passwordReset.request()`)
|
||||
* is due to no user having the given email address.
|
||||
*/
|
||||
export const isPasswordRecoveryEmailNotFoundError = apiError => apiError && apiError.status === 404;
|
||||
export const isPasswordRecoveryEmailNotFoundError = error => error && error.status === 404;
|
||||
|
||||
/**
|
||||
* Check if the given API error (from `sdk.passwordReset.request()`)
|
||||
* is due to the email not being verified, preventing the reset.
|
||||
*/
|
||||
export const isPasswordRecoveryEmailNotVerifiedError = apiError =>
|
||||
apiError && apiError.status === 409;
|
||||
export const isPasswordRecoveryEmailNotVerifiedError = error => error && error.status === 409;
|
||||
|
||||
/**
|
||||
* Check if the given API error (from `sdk.transaction.initiate()` or
|
||||
* `sdk.transaction.initiateSpeculative()`) is due to the listing
|
||||
* being closed or deleted.
|
||||
*/
|
||||
export const isTransactionInitiateListingNotFoundError = apiError => {
|
||||
return responseErrors(apiError).some(error => {
|
||||
export const isTransactionInitiateListingNotFoundError = error => {
|
||||
return responseAPIErrors(error).some(apiError => {
|
||||
let notfound = false;
|
||||
|
||||
try {
|
||||
|
|
@ -94,12 +100,12 @@ export const isTransactionInitiateListingNotFoundError = apiError => {
|
|||
// the deleted information from the error and should be changed
|
||||
// to a proper error code when the API supports a specific code
|
||||
// for this.
|
||||
notfound = error.details.data.rep[0][1].reason === 'listing-not-found';
|
||||
notfound = apiError.details.data.rep[0][1].reason === 'listing-not-found';
|
||||
} catch (e) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
return error.code === ERROR_CODE_TRANSITION_PARAMETER_VALIDATION_FAILED && notfound;
|
||||
return apiError.code === ERROR_CODE_TRANSITION_PARAMETER_VALIDATION_FAILED && notfound;
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -107,15 +113,16 @@ export const isTransactionInitiateListingNotFoundError = apiError => {
|
|||
* Check if the given API error (from `sdk.transaction.initiate()`) is
|
||||
* due to the transaction total amount being too low for Stripe.
|
||||
*/
|
||||
export const isTransactionInitiateAmountTooLowError = apiError => {
|
||||
return responseErrors(apiError).some(error => {
|
||||
const isPaymentFailedError = error.status === 402 && error.code === ERROR_CODE_PAYMENT_FAILED;
|
||||
export const isTransactionInitiateAmountTooLowError = error => {
|
||||
return responseAPIErrors(error).some(apiError => {
|
||||
const isPaymentFailedError =
|
||||
apiError.status === 402 && apiError.code === ERROR_CODE_PAYMENT_FAILED;
|
||||
let isAmountTooLow = false;
|
||||
|
||||
try {
|
||||
// TODO: This is a temporary solution until a proper error code
|
||||
// for this specific error is received in the response.
|
||||
const msg = error.details.msg;
|
||||
const msg = apiError.details.msg;
|
||||
isAmountTooLow = msg.startsWith('Amount must be at least');
|
||||
} catch (e) {
|
||||
// Ignore
|
||||
|
|
@ -129,10 +136,26 @@ export const isTransactionInitiateAmountTooLowError = apiError => {
|
|||
* Check if the given API error (from `sdk.currentUser.changeEmail(params)`)
|
||||
* is due to giving wrong password.
|
||||
*/
|
||||
export const isChangeEmailWrongPassword = apiError => apiError && apiError.status === 403;
|
||||
export const isChangeEmailWrongPassword = error => error && error.status === 403;
|
||||
|
||||
/**
|
||||
* Check if the given API error (from `sdk.currentUser.changePassword(params)`)
|
||||
* is due to giving wrong password.
|
||||
*/
|
||||
export const isChangePasswordWrongPassword = apiError => apiError && apiError.status === 403;
|
||||
export const isChangePasswordWrongPassword = error => error && error.status === 403;
|
||||
|
||||
export const storableError = error => {
|
||||
const { name, message, status, statusText } = error;
|
||||
// Status, statusText, and data.errors are (possibly) added to the error object by SDK
|
||||
const apiErrors = responseAPIErrors(error);
|
||||
|
||||
// Returned object is the same as prop type check in util/proptypes -> error
|
||||
return {
|
||||
type: 'error',
|
||||
name,
|
||||
message,
|
||||
status,
|
||||
statusText,
|
||||
apiErrors,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import { types as sdkTypes } from './sdkLoader';
|
|||
import { ensureTransaction } from './data';
|
||||
|
||||
const { UUID, LatLng, LatLngBounds, Money } = sdkTypes;
|
||||
const { arrayOf, bool, func, instanceOf, number, oneOf, shape, string } = PropTypes;
|
||||
const { arrayOf, bool, func, instanceOf, number, object, oneOf, shape, string } = PropTypes;
|
||||
|
||||
// Fixed value
|
||||
export const value = val => oneOf([val]);
|
||||
|
|
@ -217,3 +217,40 @@ export const pagination = shape({
|
|||
totalItems: number.isRequired,
|
||||
totalPages: number.isRequired,
|
||||
});
|
||||
|
||||
export const ERROR_CODE_TRANSITION_PARAMETER_VALIDATION_FAILED =
|
||||
'transition-parameter-validation-failed';
|
||||
export const ERROR_CODE_PAYMENT_FAILED = 'transaction-payment-failed';
|
||||
export const ERROR_CODE_EMAIL_TAKEN = 'email-taken';
|
||||
export const ERROR_CODE_TOO_MANY_VERIFICATION_REQUESTS = 'email-too-many-verification-requests';
|
||||
export const ERROR_CODE_UPLOAD_OVER_LIMIT = 'request-upload-over-limit';
|
||||
const ERROR_CODES = [
|
||||
ERROR_CODE_TRANSITION_PARAMETER_VALIDATION_FAILED,
|
||||
ERROR_CODE_PAYMENT_FAILED,
|
||||
ERROR_CODE_EMAIL_TAKEN,
|
||||
ERROR_CODE_TOO_MANY_VERIFICATION_REQUESTS,
|
||||
ERROR_CODE_UPLOAD_OVER_LIMIT,
|
||||
];
|
||||
|
||||
// API error
|
||||
// TODO this is likely to change soonish
|
||||
export const apiError = shape({
|
||||
id: uuid.isRequired,
|
||||
status: number.isRequired,
|
||||
code: oneOf(ERROR_CODES).isRequired,
|
||||
title: string.isRequired,
|
||||
details: shape({
|
||||
data: object,
|
||||
msg: string,
|
||||
}),
|
||||
});
|
||||
|
||||
// Storable error prop type. (Error object should not be stored as it is.)
|
||||
export const error = shape({
|
||||
type: value('error').isRequired,
|
||||
name: string.isRequired,
|
||||
message: string,
|
||||
status: number,
|
||||
statusText: string,
|
||||
apiErrors: arrayOf(apiError),
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue