All files / src/containers/ErrorPageHandler index.jsx

85.42% Statements 41/48
92.31% Branches 24/26
80% Functions 12/15
86.96% Lines 40/46
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151                              10x 10x 10x 10x 10x 10x       2x 2x 1x         22x   22x 12x     10x 10x       1x   1x       1x         1x 1x                     1x 2x       12x   12x 10x     2x       12x   12x 1x     11x 1x           10x           12x             1x                                           6x 6x 6x               6x       6x 3x     3x        
import styles from './style.postcss';
 
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import is from 'is_js';
import ErrorPage from 'components/ErrorPage';
import connect from 'domain/connect';
import ApiCall from 'containers/ApiCalls';
import ErrorPageConfig from 'domain/ErrorPageConfig';
import AlertDialog from 'components/AlertDialog';
import ErrorMessage from 'domain/ErrorMessage';
import Config from 'domain/Config';
 
export class ErrorPageHandler extends PureComponent {
  constructor(props) {
    super(props);
    this._shouldShowPopUp = this._shouldShowPopUp.bind(this);
    this._buildMessage = this._buildMessage.bind(this);
    this._cleanErrors = this._cleanErrors.bind(this);
    this._renderChildren = this._renderChildren.bind(this);
    this._renderError = this._renderError.bind(this);
  }
 
  componentWillUpdate({ location: { pathname: nextPath } }) {
    const { location: { pathname } } = this.props;
    if (pathname !== nextPath) {  // page changed, clear errors
      this._cleanErrors();
    }
  }
 
  _shouldShowPopUp() {
    const { erroredApi } = this.props;
 
    if (Config.get('errorHandlerRendersPopUps') !== true || ! erroredApi) {
      return false;
    }
 
    const { response, status } = erroredApi.error;
    return is.object(response) && status !== 500;
  }
 
  _buildMessage() {
    const { erroredApi: { error: { response } } } = this.props;
 
    let message = ErrorMessage.for(response.errorCode) || response.message;
 
    // To handle the pattern of exception response from the end point of identity server
    // which return { error: string }
    Iif (! message && response.error) {
      message = response.error;
      return message;
    }
 
    Eif (is.not.array(response.args)) {
      return message;
    }
 
    response.args.forEach((arg) => {
      message = message.replace(/{".*"}/i, arg);
    });
 
    return message;
  }
 
  _cleanErrors() {
    const { erroredApis, clean } = this.props;
    erroredApis.forEach((api) => clean(api.id));
  }
 
  _renderChildren() {
    const { erroredApi, children } = this.props;
 
    if (erroredApi && ! this._shouldShowPopUp()) {
      return null; // Because the error page will be rendered.
    }
 
    return children;
  }
 
  _renderError() {
    const { erroredApi, config } = this.props;
 
    if (! erroredApi) {
      return null;
    }
 
    if (this._shouldShowPopUp()) {
      return <AlertDialog isWarning
          content1={this._buildMessage()}
          okButtonContent="OK"
          onButtonClick={this._cleanErrors} />;
    }
 
    return <ErrorPage erroredApi={erroredApi}
        config={config}
        {...this.props} />;
  }
 
  render() {
    return <div className={styles.ErrorPageHandler}>
      {this._renderError()}
      {this._renderChildren()}
    </div>;
  }
}
 
ErrorPageHandler.propTypes = {
  config: PropTypes.object,
  erroredApis: PropTypes.shape({
    size: PropTypes.string.func,
    first: PropTypes.string.func,
    forEach: PropTypes.string.func,
  }),
  erroredApi: PropTypes.shape({
    error: PropTypes.shape({
      status: PropTypes.number,
      response: PropTypes.any,
    }),
  }),
  location: PropTypes.shape({
    pathname: PropTypes.string.isRequired,
  }).isRequired,
  clean: PropTypes.func.isRequired,
  replace: PropTypes.func.isRequired,
  children: PropTypes.node,
};
 
export function mapStateToProps(state, { routes }) {
  const erroredApis = getApiErrors(state);
  const erroredApi = getApiError(erroredApis);
  return { erroredApis, erroredApi, config: ErrorPageConfig.get(routes) };
}
 
function mapDispatchToProps(dispatch) {
  return { clean: (key) => dispatch(ApiCall.clean(key)) };
}
 
function getApiErrors(state) {
  return ApiCall.getErrors(state).toList();
}
 
function getApiError(erroredApis) {
  if (erroredApis.size <= 0) {
    return undefined;
  }
 
  return erroredApis.first();
}
 
export default connect(mapStateToProps, mapDispatchToProps)(ErrorPageHandler);