From 9ad17224df26ff582a8781a46ca27a56d16ca449 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 18:51:03 +0300 Subject: [PATCH 01/29] Ensure that server doesn't try to stringify Error --- server/renderer.js | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/server/renderer.js b/server/renderer.js index 10ebdb29..dc3e0349 100644 --- a/server/renderer.js +++ b/server/renderer.js @@ -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(/ Date: Tue, 17 Oct 2017 18:58:43 +0300 Subject: [PATCH 02/29] Rename error parameter on funtions inside util/errors --- src/util/errors.js | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/util/errors.js b/src/util/errors.js index df96d914..affa18dc 100644 --- a/src/util/errors.js +++ b/src/util/errors.js @@ -29,15 +29,13 @@ const hasErrorWithCode = (apiError, code) => { * 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 +46,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 responseErrors(error).some(apiError => { let notfound = false; try { @@ -94,12 +91,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 +104,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 responseErrors(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 +127,10 @@ 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; From fb782cebcfe957cc7b2e0642b4ea9d8c3d995930 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:01:57 +0300 Subject: [PATCH 03/29] storableError function added --- src/util/errors.js | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/util/errors.js b/src/util/errors.js index affa18dc..3b9981ad 100644 --- a/src/util/errors.js +++ b/src/util/errors.js @@ -15,16 +15,23 @@ 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'; -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. @@ -83,7 +90,7 @@ export const isPasswordRecoveryEmailNotVerifiedError = error => error && error.s * being closed or deleted. */ export const isTransactionInitiateListingNotFoundError = error => { - return responseErrors(error).some(apiError => { + return responseAPIErrors(error).some(apiError => { let notfound = false; try { @@ -105,7 +112,7 @@ export const isTransactionInitiateListingNotFoundError = error => { * due to the transaction total amount being too low for Stripe. */ export const isTransactionInitiateAmountTooLowError = error => { - return responseErrors(error).some(apiError => { + return responseAPIErrors(error).some(apiError => { const isPaymentFailedError = apiError.status === 402 && apiError.code === ERROR_CODE_PAYMENT_FAILED; let isAmountTooLow = false; @@ -134,3 +141,19 @@ export const isChangeEmailWrongPassword = error => error && error.status === 403 * is due to giving wrong password. */ 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, + }; +}; From fbe247318d439f0e8e84161289ec7d5b637a7348 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:09:03 +0300 Subject: [PATCH 04/29] Storable error object available in propTypes.js --- src/util/errors.js | 12 +++++++----- src/util/propTypes.js | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/util/errors.js b/src/util/errors.js index 3b9981ad..49e641e2 100644 --- a/src/util/errors.js +++ b/src/util/errors.js @@ -9,11 +9,13 @@ * 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 errorAPIErrors = error => { return error && error.apiErrors ? error.apiErrors : []; diff --git a/src/util/propTypes.js b/src/util/propTypes.js index e71c5f0b..8830a21c 100644 --- a/src/util/propTypes.js +++ b/src/util/propTypes.js @@ -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), +}); From 13df1c3abb9cf23dcfc8382312234a030acabc9a Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:10:00 +0300 Subject: [PATCH 05/29] Auth.duck uses storableError --- src/ducks/Auth.duck.js | 9 +++++---- src/ducks/Auth.test.js | 13 ++++++++++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/ducks/Auth.duck.js b/src/ducks/Auth.duck.js index e6ed3ac5..5705062d 100644 --- a/src/ducks/Auth.duck.js +++ b/src/ducks/Auth.duck.js @@ -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, diff --git a/src/ducks/Auth.test.js b/src/ducks/Auth.test.js index 907a2dfb..9865290a 100644 --- a/src/ducks/Auth.test.js +++ b/src/ducks/Auth.test.js @@ -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)), + ]); }); }); }); From 171c86d6eb0e5f5d715df5a82817c8410c529f52 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:10:42 +0300 Subject: [PATCH 06/29] EmailVerification.duck uses storableError --- src/ducks/EmailVerification.duck.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ducks/EmailVerification.duck.js b/src/ducks/EmailVerification.duck.js index d7162a74..c9166fce 100644 --- a/src/ducks/EmailVerification.duck.js +++ b/src/ducks/EmailVerification.duck.js @@ -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)))); }; From f29854a4d856fb0b8281cafbce7a7822e8d68e79 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:11:22 +0300 Subject: [PATCH 07/29] user.duck uses storableError --- src/ducks/user.duck.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/ducks/user.duck.js b/src/ducks/user.duck.js index 22797e67..37885ce7 100644 --- a/src/ducks/user.duck.js +++ b/src/ducks/user.duck.js @@ -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)))); }; From b9399bcf6ff0d305b7e40aca21c614e16a28c9a1 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:12:55 +0300 Subject: [PATCH 08/29] AuthenticationPage uses correct proptype validation --- .../AuthenticationPage/AuthenticationPage.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/containers/AuthenticationPage/AuthenticationPage.js b/src/containers/AuthenticationPage/AuthenticationPage.js index 7d262b1f..7776c4ee 100644 --- a/src/containers/AuthenticationPage/AuthenticationPage.js +++ b/src/containers/AuthenticationPage/AuthenticationPage.js @@ -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 From c1d111d11af3c881d7766e4c8ebf5f8c8cc6a500 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:14:21 +0300 Subject: [PATCH 09/29] CheckoutPage uses storableError func and correct proptype validation. --- src/containers/CheckoutPage/CheckoutPage.duck.js | 5 +++-- src/containers/CheckoutPage/CheckoutPage.js | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/containers/CheckoutPage/CheckoutPage.duck.js b/src/containers/CheckoutPage/CheckoutPage.duck.js index 028c8b3d..12f6c6bb 100644 --- a/src/containers/CheckoutPage/CheckoutPage.duck.js +++ b/src/containers/CheckoutPage/CheckoutPage.duck.js @@ -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))); }); }; diff --git a/src/containers/CheckoutPage/CheckoutPage.js b/src/containers/CheckoutPage/CheckoutPage.js index be24793e..a47ac369 100644 --- a/src/containers/CheckoutPage/CheckoutPage.js +++ b/src/containers/CheckoutPage/CheckoutPage.js @@ -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, From 2c6fd5a73e8203d3bf8434a85ac55dfae5d0fda8 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:36:37 +0300 Subject: [PATCH 10/29] ContactDetailsPage and form use storableError func and correct proptype validation. --- .../ContactDetailsForm/ContactDetailsForm.js | 7 ++++--- .../ContactDetailsPage/ContactDetailsPage.duck.js | 3 ++- .../ContactDetailsPage/ContactDetailsPage.js | 10 +++++----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/containers/ContactDetailsForm/ContactDetailsForm.js b/src/containers/ContactDetailsForm/ContactDetailsForm.js index d4a30b4c..135cfd30 100644 --- a/src/containers/ContactDetailsForm/ContactDetailsForm.js +++ b/src/containers/ContactDetailsForm/ContactDetailsForm.js @@ -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, }; diff --git a/src/containers/ContactDetailsPage/ContactDetailsPage.duck.js b/src/containers/ContactDetailsPage/ContactDetailsPage.duck.js index 6930929a..9f8221d6 100644 --- a/src/containers/ContactDetailsPage/ContactDetailsPage.duck.js +++ b/src/containers/ContactDetailsPage/ContactDetailsPage.duck.js @@ -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)))); }; diff --git a/src/containers/ContactDetailsPage/ContactDetailsPage.js b/src/containers/ContactDetailsPage/ContactDetailsPage.js index 146aecca..dd7b8241 100644 --- a/src/containers/ContactDetailsPage/ContactDetailsPage.js +++ b/src/containers/ContactDetailsPage/ContactDetailsPage.js @@ -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, }; From ff69b999083945fac7ff92f0d6fe9708e029a3bb Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:37:46 +0300 Subject: [PATCH 11/29] EditListingPage and forms use storableError func and correct proptype validation. --- .../EditListingDescriptionForm.js | 5 +++-- .../EditListingLocationForm/EditListingLocationForm.js | 4 ++-- src/containers/EditListingPage/EditListingPage.duck.js | 9 +++++---- src/containers/EditListingPage/EditListingPage.js | 8 ++++---- .../EditListingPhotosForm/EditListingPhotosForm.js | 5 +++-- .../EditListingPricingForm/EditListingPricingForm.js | 5 +++-- 6 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/containers/EditListingDescriptionForm/EditListingDescriptionForm.js b/src/containers/EditListingDescriptionForm/EditListingDescriptionForm.js index fd8909d0..7faa7837 100644 --- a/src/containers/EditListingDescriptionForm/EditListingDescriptionForm.js +++ b/src/containers/EditListingDescriptionForm/EditListingDescriptionForm.js @@ -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, }; diff --git a/src/containers/EditListingLocationForm/EditListingLocationForm.js b/src/containers/EditListingLocationForm/EditListingLocationForm.js index e2c8c853..6ddeb34f 100644 --- a/src/containers/EditListingLocationForm/EditListingLocationForm.js +++ b/src/containers/EditListingLocationForm/EditListingLocationForm.js @@ -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, }; diff --git a/src/containers/EditListingPage/EditListingPage.duck.js b/src/containers/EditListingPage/EditListingPage.duck.js index 4da180e3..c5366da6 100644 --- a/src/containers/EditListingPage/EditListingPage.duck.js +++ b/src/containers/EditListingPage/EditListingPage.duck.js @@ -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))); }); }; } diff --git a/src/containers/EditListingPage/EditListingPage.js b/src/containers/EditListingPage/EditListingPage.js index d98e11c4..c66e9806 100644 --- a/src/containers/EditListingPage/EditListingPage.js +++ b/src/containers/EditListingPage/EditListingPage.js @@ -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, diff --git a/src/containers/EditListingPhotosForm/EditListingPhotosForm.js b/src/containers/EditListingPhotosForm/EditListingPhotosForm.js index edb1522f..94627d2e 100644 --- a/src/containers/EditListingPhotosForm/EditListingPhotosForm.js +++ b/src/containers/EditListingPhotosForm/EditListingPhotosForm.js @@ -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, }; diff --git a/src/containers/EditListingPricingForm/EditListingPricingForm.js b/src/containers/EditListingPricingForm/EditListingPricingForm.js index c29b6b5e..e61689a0 100644 --- a/src/containers/EditListingPricingForm/EditListingPricingForm.js +++ b/src/containers/EditListingPricingForm/EditListingPricingForm.js @@ -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, }; From 4d9aaf17584d749f6b96e6b02d6d6b284716d10e Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:39:00 +0300 Subject: [PATCH 12/29] EmailVerificationPage and form use correct proptype validation (global duck) --- .../EmailVerificationForm/EmailVerificationForm.js | 4 ++-- .../EmailVerificationPage/EmailVerificationPage.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/containers/EmailVerificationForm/EmailVerificationForm.js b/src/containers/EmailVerificationForm/EmailVerificationForm.js index b46bc818..935b37fc 100644 --- a/src/containers/EmailVerificationForm/EmailVerificationForm.js +++ b/src/containers/EmailVerificationForm/EmailVerificationForm.js @@ -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'; diff --git a/src/containers/EmailVerificationPage/EmailVerificationPage.js b/src/containers/EmailVerificationPage/EmailVerificationPage.js index 90490929..0f8fec4a 100644 --- a/src/containers/EmailVerificationPage/EmailVerificationPage.js +++ b/src/containers/EmailVerificationPage/EmailVerificationPage.js @@ -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({ From a2dc53902284a6fa8ecbf1bb3f81f27af4c08242 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:39:50 +0300 Subject: [PATCH 13/29] InboxPage uses storableError func and correct proptype validation. --- src/containers/InboxPage/InboxPage.duck.js | 3 ++- src/containers/InboxPage/InboxPage.js | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/containers/InboxPage/InboxPage.duck.js b/src/containers/InboxPage/InboxPage.duck.js index 73ef5777..1c9a8f08 100644 --- a/src/containers/InboxPage/InboxPage.duck.js +++ b/src/containers/InboxPage/InboxPage.duck.js @@ -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; }); }; diff --git a/src/containers/InboxPage/InboxPage.js b/src/containers/InboxPage/InboxPage.js index 93da1416..5b7ad86c 100644 --- a/src/containers/InboxPage/InboxPage.js +++ b/src/containers/InboxPage/InboxPage.js @@ -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, From d0a1cafc1bd9b253a5f451d5e3524ad8da215142 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:40:30 +0300 Subject: [PATCH 14/29] LandingPage uses correct proptype validation (global duck) --- src/containers/LandingPage/LandingPage.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/containers/LandingPage/LandingPage.js b/src/containers/LandingPage/LandingPage.js index 7c08ac99..7ed5101f 100644 --- a/src/containers/LandingPage/LandingPage.js +++ b/src/containers/LandingPage/LandingPage.js @@ -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 From ee051c510aaf4424f4ea1b969acaeca3ff946c07 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:41:34 +0300 Subject: [PATCH 15/29] ListingPage uses storableError func and correct proptype validation. --- src/containers/ListingPage/ListingPage.duck.js | 3 ++- src/containers/ListingPage/ListingPage.js | 8 ++++---- src/containers/ListingPage/ListingPage.test.js | 3 ++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/containers/ListingPage/ListingPage.duck.js b/src/containers/ListingPage/ListingPage.duck.js index f41607d7..e55f9322 100644 --- a/src/containers/ListingPage/ListingPage.duck.js +++ b/src/containers/ListingPage/ListingPage.duck.js @@ -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))); }); }; diff --git a/src/containers/ListingPage/ListingPage.js b/src/containers/ListingPage/ListingPage.js index ecb8027a..b241e63b 100644 --- a/src/containers/ListingPage/ListingPage.js +++ b/src/containers/ListingPage/ListingPage.js @@ -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, }; diff --git a/src/containers/ListingPage/ListingPage.test.js b/src/containers/ListingPage/ListingPage.test.js index 1df487f6..df9f497b 100644 --- a/src/containers/ListingPage/ListingPage.test.js +++ b/src/containers/ListingPage/ListingPage.test.js @@ -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))], ]); }); }); From 7ce6043c0bf95eac1189b7f23599a2367a92857f Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:41:55 +0300 Subject: [PATCH 16/29] ManageListingPage uses storableError func and correct proptype validation. --- .../ManageListingsPage/ManageListingsPage.duck.js | 7 ++++--- .../ManageListingsPage/ManageListingsPage.js | 12 ++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/containers/ManageListingsPage/ManageListingsPage.duck.js b/src/containers/ManageListingsPage/ManageListingsPage.duck.js index 5840470c..9aaff7f1 100644 --- a/src/containers/ManageListingsPage/ManageListingsPage.duck.js +++ b/src/containers/ManageListingsPage/ManageListingsPage.duck.js @@ -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))); }); }; diff --git a/src/containers/ManageListingsPage/ManageListingsPage.js b/src/containers/ManageListingsPage/ManageListingsPage.js index 4861a5fb..fdd35232 100644 --- a/src/containers/ManageListingsPage/ManageListingsPage.js +++ b/src/containers/ManageListingsPage/ManageListingsPage.js @@ -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, }; From 061237dec6bd35d64d6755754890d850ea370ac6 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:42:17 +0300 Subject: [PATCH 17/29] NotFoundPage uses correct proptype validation (global duck) --- src/containers/NotFoundPage/NotFoundPage.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/containers/NotFoundPage/NotFoundPage.js b/src/containers/NotFoundPage/NotFoundPage.js index e30b6824..b1ff111c 100644 --- a/src/containers/NotFoundPage/NotFoundPage.js +++ b/src/containers/NotFoundPage/NotFoundPage.js @@ -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 From 5edb24420ffa9dd9aeaf07cfb118a91fbbf2c760 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:42:39 +0300 Subject: [PATCH 18/29] OrderPage uses storableError func and correct proptype validation. --- src/containers/OrderPage/OrderPage.duck.js | 3 ++- src/containers/OrderPage/OrderPage.js | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/containers/OrderPage/OrderPage.duck.js b/src/containers/OrderPage/OrderPage.duck.js index dbb905d0..d15c6027 100644 --- a/src/containers/OrderPage/OrderPage.duck.js +++ b/src/containers/OrderPage/OrderPage.duck.js @@ -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; }); }; diff --git a/src/containers/OrderPage/OrderPage.js b/src/containers/OrderPage/OrderPage.js index 22c55c91..15412e9d 100644 --- a/src/containers/OrderPage/OrderPage.js +++ b/src/containers/OrderPage/OrderPage.js @@ -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, From 690635076ff82ffe665d66fb0bf04a354682bccd Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:43:27 +0300 Subject: [PATCH 19/29] PasswordChangePage and form use storableError func and correct proptype validation. --- src/containers/PasswordChangeForm/PasswordChangeForm.js | 5 +++-- .../PasswordChangePage/PasswordChangePage.duck.js | 4 +++- src/containers/PasswordChangePage/PasswordChangePage.js | 8 ++++---- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/containers/PasswordChangeForm/PasswordChangeForm.js b/src/containers/PasswordChangeForm/PasswordChangeForm.js index 27508c43..8755add9 100644 --- a/src/containers/PasswordChangeForm/PasswordChangeForm.js +++ b/src/containers/PasswordChangeForm/PasswordChangeForm.js @@ -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, diff --git a/src/containers/PasswordChangePage/PasswordChangePage.duck.js b/src/containers/PasswordChangePage/PasswordChangePage.duck.js index a93b9384..669495a7 100644 --- a/src/containers/PasswordChangePage/PasswordChangePage.duck.js +++ b/src/containers/PasswordChangePage/PasswordChangePage.duck.js @@ -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; diff --git a/src/containers/PasswordChangePage/PasswordChangePage.js b/src/containers/PasswordChangePage/PasswordChangePage.js index 728d6783..1fa4f3e4 100644 --- a/src/containers/PasswordChangePage/PasswordChangePage.js +++ b/src/containers/PasswordChangePage/PasswordChangePage.js @@ -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, From 49ca6ea1327841bf64e912abc60a7943799168d0 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:43:49 +0300 Subject: [PATCH 20/29] PasswordRecoveryPage and form use storableError func and correct proptype validation. --- .../PasswordRecoveryForm/PasswordRecoveryForm.js | 7 ++++--- .../PasswordRecoveryPage.duck.js | 4 +++- .../PasswordRecoveryPage/PasswordRecoveryPage.js | 15 ++++++++------- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/containers/PasswordRecoveryForm/PasswordRecoveryForm.js b/src/containers/PasswordRecoveryForm/PasswordRecoveryForm.js index 5ddf917b..adc6b1d4 100644 --- a/src/containers/PasswordRecoveryForm/PasswordRecoveryForm.js +++ b/src/containers/PasswordRecoveryForm/PasswordRecoveryForm.js @@ -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, diff --git a/src/containers/PasswordRecoveryPage/PasswordRecoveryPage.duck.js b/src/containers/PasswordRecoveryPage/PasswordRecoveryPage.duck.js index 59e6ad59..4c00b60c 100644 --- a/src/containers/PasswordRecoveryPage/PasswordRecoveryPage.duck.js +++ b/src/containers/PasswordRecoveryPage/PasswordRecoveryPage.duck.js @@ -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))); }; diff --git a/src/containers/PasswordRecoveryPage/PasswordRecoveryPage.js b/src/containers/PasswordRecoveryPage/PasswordRecoveryPage.js index 363c4d88..73c9f4c8 100644 --- a/src/containers/PasswordRecoveryPage/PasswordRecoveryPage.js +++ b/src/containers/PasswordRecoveryPage/PasswordRecoveryPage.js @@ -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, From 41ded2f4c8cce36d449d6e718ad1a0cb0dc3e1f8 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:44:38 +0300 Subject: [PATCH 21/29] PasswordResetPage uses storableError func and correct proptype validation. --- .../PasswordResetPage/PasswordResetPage.duck.js | 4 +++- src/containers/PasswordResetPage/PasswordResetPage.js | 11 ++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/containers/PasswordResetPage/PasswordResetPage.duck.js b/src/containers/PasswordResetPage/PasswordResetPage.duck.js index 46cb3ac0..15032a3a 100644 --- a/src/containers/PasswordResetPage/PasswordResetPage.duck.js +++ b/src/containers/PasswordResetPage/PasswordResetPage.duck.js @@ -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)))); }; diff --git a/src/containers/PasswordResetPage/PasswordResetPage.js b/src/containers/PasswordResetPage/PasswordResetPage.js index 586c0c61..1308c55f 100644 --- a/src/containers/PasswordResetPage/PasswordResetPage.js +++ b/src/containers/PasswordResetPage/PasswordResetPage.js @@ -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 From 1d0a928d2d5e93117ee54cd1b0b967e612ba3acb Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:45:08 +0300 Subject: [PATCH 22/29] PayoutPreferencesPage uses correct proptype validation (global duck) --- .../PayoutPreferencesPage/PayoutPreferencesPage.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/containers/PayoutPreferencesPage/PayoutPreferencesPage.js b/src/containers/PayoutPreferencesPage/PayoutPreferencesPage.js index 43e7a8e2..f3bb53c0 100644 --- a/src/containers/PayoutPreferencesPage/PayoutPreferencesPage.js +++ b/src/containers/PayoutPreferencesPage/PayoutPreferencesPage.js @@ -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, }; From 54e2a9a44ef62d158e8958641dc4638cc57066db Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:45:29 +0300 Subject: [PATCH 23/29] ProfilePage uses correct proptype validation (global duck) --- src/containers/ProfilePage/ProfilePage.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/containers/ProfilePage/ProfilePage.js b/src/containers/ProfilePage/ProfilePage.js index 2b669d51..b6255eac 100644 --- a/src/containers/ProfilePage/ProfilePage.js +++ b/src/containers/ProfilePage/ProfilePage.js @@ -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, }; From d8520f8e6dde55a3119dc05e69e44160e0aa4daf Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:45:54 +0300 Subject: [PATCH 24/29] ProfileSettingsPage and form use storableError func and correct proptype validation. --- .../ProfileSettingsForm/ProfileSettingsForm.js | 9 +++++---- .../ProfileSettingsPage/ProfileSettingsPage.duck.js | 5 +++-- .../ProfileSettingsPage/ProfileSettingsPage.js | 10 +++++----- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/containers/ProfileSettingsForm/ProfileSettingsForm.js b/src/containers/ProfileSettingsForm/ProfileSettingsForm.js index 1a71260f..1d15e5ea 100644 --- a/src/containers/ProfileSettingsForm/ProfileSettingsForm.js +++ b/src/containers/ProfileSettingsForm/ProfileSettingsForm.js @@ -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 diff --git a/src/containers/ProfileSettingsPage/ProfileSettingsPage.duck.js b/src/containers/ProfileSettingsPage/ProfileSettingsPage.duck.js index 1440460e..ff8c29c9 100644 --- a/src/containers/ProfileSettingsPage/ProfileSettingsPage.duck.js +++ b/src/containers/ProfileSettingsPage/ProfileSettingsPage.duck.js @@ -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)))); }; }; diff --git a/src/containers/ProfileSettingsPage/ProfileSettingsPage.js b/src/containers/ProfileSettingsPage/ProfileSettingsPage.js index 89b9a69f..43291b97 100644 --- a/src/containers/ProfileSettingsPage/ProfileSettingsPage.js +++ b/src/containers/ProfileSettingsPage/ProfileSettingsPage.js @@ -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, }; From f68cf153af31476ddd65fcaab3efba9bfe558c8f Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:46:26 +0300 Subject: [PATCH 25/29] SalePage and panel uses storableError func and correct proptype validation. --- src/components/SaleDetailsPanel/SaleDetailsPanel.js | 6 +++--- src/containers/SalePage/SalePage.duck.js | 7 ++++--- src/containers/SalePage/SalePage.js | 12 ++++++------ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/components/SaleDetailsPanel/SaleDetailsPanel.js b/src/components/SaleDetailsPanel/SaleDetailsPanel.js index 968c6096..6ff28774 100644 --- a/src/components/SaleDetailsPanel/SaleDetailsPanel.js +++ b/src/components/SaleDetailsPanel/SaleDetailsPanel.js @@ -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, diff --git a/src/containers/SalePage/SalePage.duck.js b/src/containers/SalePage/SalePage.duck.js index 09d1c28a..5283b157 100644 --- a/src/containers/SalePage/SalePage.duck.js +++ b/src/containers/SalePage/SalePage.duck.js @@ -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, diff --git a/src/containers/SalePage/SalePage.js b/src/containers/SalePage/SalePage.js index 250d8f46..66cc6916 100644 --- a/src/containers/SalePage/SalePage.js +++ b/src/containers/SalePage/SalePage.js @@ -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, From 347699de9153e0a8fbb1ab3be388593fef1a2c2c Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:47:54 +0300 Subject: [PATCH 26/29] SearchPage uses storableError func and correct proptype validation. --- src/containers/SearchPage/SearchPage.duck.js | 5 +++-- src/containers/SearchPage/SearchPage.js | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/containers/SearchPage/SearchPage.duck.js b/src/containers/SearchPage/SearchPage.duck.js index 25d8e03b..ced4889d 100644 --- a/src/containers/SearchPage/SearchPage.duck.js +++ b/src/containers/SearchPage/SearchPage.duck.js @@ -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; }); }; diff --git a/src/containers/SearchPage/SearchPage.js b/src/containers/SearchPage/SearchPage.js index 157c44bb..84ac3ad8 100644 --- a/src/containers/SearchPage/SearchPage.js +++ b/src/containers/SearchPage/SearchPage.js @@ -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, From 9288e37d861ff48792fb02bd2bf509d58dd6e8c5 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:48:18 +0300 Subject: [PATCH 27/29] SecurityPage uses correct proptype validation (global duck) --- src/containers/SecurityPage/SecurityPage.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/containers/SecurityPage/SecurityPage.js b/src/containers/SecurityPage/SecurityPage.js index d32b02d2..2b8e6bf7 100644 --- a/src/containers/SecurityPage/SecurityPage.js +++ b/src/containers/SecurityPage/SecurityPage.js @@ -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, }; From a9fcdd4875316a6f2146eca179c673da4cca91f1 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:48:55 +0300 Subject: [PATCH 28/29] TopbarContainer and Topbar use correct proptype validation (global duck) --- src/components/Topbar/Topbar.js | 4 ++-- src/containers/TopbarContainer/TopbarContainer.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Topbar/Topbar.js b/src/components/Topbar/Topbar.js index 07b84569..a1fabb8b 100644 --- a/src/components/Topbar/Topbar.js +++ b/src/components/Topbar/Topbar.js @@ -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({ diff --git a/src/containers/TopbarContainer/TopbarContainer.js b/src/containers/TopbarContainer/TopbarContainer.js index 033f6370..b7f738f9 100644 --- a/src/containers/TopbarContainer/TopbarContainer.js +++ b/src/containers/TopbarContainer/TopbarContainer.js @@ -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 From abc4cc7f3d4b881ceb7335397b9ae02fc2a163c9 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Tue, 17 Oct 2017 19:49:19 +0300 Subject: [PATCH 29/29] Page uses correct proptype validation (global duck) --- src/components/Page/Page.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/Page/Page.js b/src/components/Page/Page.js index 5799bb17..ed51674f 100644 --- a/src/components/Page/Page.js +++ b/src/components/Page/Page.js @@ -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