Skip to content

Commit

Permalink
Added ErrorMessage to UserPage
Browse files Browse the repository at this point in the history
  • Loading branch information
alicewriteswrongs committed Jul 1, 2016
1 parent 917b5b3 commit ed19858
Show file tree
Hide file tree
Showing 16 changed files with 581 additions and 529 deletions.
853 changes: 385 additions & 468 deletions npm-shrinkwrap.json

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,26 @@
"dependencies": {
"ajaxchimp": "^1.3.0",
"babel": "6.5.2",
"babel-core": "6.8.0",
"babel-eslint": "6.0.4",
"babel-core": "^6.10.4",
"babel-eslint": "^6.1.0",
"babel-loader": "6.2.4",
"babel-plugin-jsx": "1.2.0",
"babel-plugin-transform-flow-strip-types": "^6.8.0",
"babel-plugin-transform-react-jsx": "6.8.0",
"babel-polyfill": "^6.9.1",
"babel-preset-es2015": "6.6.0",
"babel-preset-react": "6.5.0",
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.11.1",
"babel-preset-stage-1": "6.5.0",
"babel-register": "6.8.0",
"babel-register": "^6.9.0",
"bootstrap": "3.3.6",
"chai": "^3.5.0",
"chai-as-promised": "^5.3.0",
"css-loader": "0.23.1",
"eslint": "2.9.0",
"eslint": "^2.13.1",
"eslint-config-defaults": "9.0.0",
"eslint-plugin-babel": "3.2.0",
"eslint-plugin-babel": "^3.3.0",
"eslint-plugin-flow-vars": "^0.4.0",
"eslint-plugin-flowtype": "^2.2.7",
"eslint-plugin-flowtype": "^2.3.0",
"eslint-plugin-react": "5.0.1",
"fetch-mock": "4.4.0",
"file-loader": "0.8.5",
Expand Down
8 changes: 4 additions & 4 deletions static/js/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,18 @@ const receivePatchUserProfileSuccess = (username, profile) => ({
payload: { profile, username }
});

const receivePatchUserProfileFailure = username => ({
const receivePatchUserProfileFailure = (username, errorInfo) => ({
type: RECEIVE_PATCH_USER_PROFILE_FAILURE,
payload: { username }
payload: { username, errorInfo }
});

export const saveProfile = (username, profile) => {
return dispatch => {
dispatch(requestPatchUserProfile(username));
return api.patchUserProfile(username, profile).
then(newProfile => dispatch(receivePatchUserProfileSuccess(username, newProfile))).
catch(() => {
dispatch(receivePatchUserProfileFailure(username));
catch(error => {
dispatch(receivePatchUserProfileFailure(username, error));
// the exception is assumed handled and will not be propagated
});
};
Expand Down
45 changes: 32 additions & 13 deletions static/js/components/ErrorMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,49 @@
import React from 'react';
import Alert from 'react-bootstrap/lib/Alert';

import type { APIErrorInfo } from '../flow/profileTypes';

export default class ErrorMessage extends React.Component {
static propTypes = {
errorInfo: React.PropTypes.object.isRequired,
props: {
errorInfo: APIErrorInfo,
};

render() {
const { errorInfo: {error_code: errorCode, user_message: userMessage} } = this.props;
const {
errorInfo: {
error_code: errorCode,
user_message: userMessage,
detail,
errorStatusCode,
}
} = this.props;

let errorCodeStr = '';
let userMessageStr = '';
if (errorCode !== undefined) {
errorCodeStr = `${errorCode}: `;
}
if (userMessage !== undefined) {
userMessageStr = `Additional info: ${userMessage}`;
}
let errorCodeStr = () => {
if ( errorCode !== undefined ) {
return `${errorCode} `;
}
if ( errorStatusCode !== undefined ) {
return `${errorStatusCode} `;
}
return '';
};

let userMessageStr = () => {
if ( userMessage !== undefined ) {
return `Additional info: ${userMessage}`;
}
if ( detail !== undefined ) {
return `Additional info: ${detail}`;
}
return '';
};

return (
<div className="alert-message">
<Alert bsStyle="danger">
<p>{ errorCodeStr }Sorry, we were unable to load the data necessary to
<p>{ errorCodeStr() }Sorry, we were unable to load the data necessary to
process your request. Please reload the page.</p>
<p>{ userMessageStr }</p>
<p>{ userMessageStr() }</p>
<p>
If the error persists, please contact <a href="mailto:[email protected]">
[email protected]</a> specifying
Expand Down
8 changes: 6 additions & 2 deletions static/js/components/PersonalForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ import CountrySelectField from './inputs/CountrySelectField';
import StateSelectField from './inputs/StateSelectField';

import ProfileFormFields from '../util/ProfileFormFields';
import type { Profile, ValidationErrors } from '../flow/profileTypes';
import type {
Profile,
BoundSaveProfile,
ValidationErrors
} from '../flow/profileTypes';

export default class PersonalForm extends ProfileFormFields {
props: {
profile: Profile,
errors: ValidationErrors,
saveProfile: () => void,
saveProfile: BoundSaveProfile,
updateProfile: () => void,
};

Expand Down
4 changes: 2 additions & 2 deletions static/js/components/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import EmploymentForm from './EmploymentForm';
import EducationDisplay from './EducationDisplay';
import UserPagePersonalDialog from './UserPagePersonalDialog.js';
import { userPrivilegeCheck } from '../util/util';
import type { Profile } from '../flow/profileTypes';
import type { Profile, BoundSaveProfile } from '../flow/profileTypes';
import type { UIState } from '../reducers/ui';

export default class User extends React.Component {
Expand All @@ -19,7 +19,7 @@ export default class User extends React.Component {
setUserPageDialogVisibility: () => void,
ui: UIState,
clearProfileEdit: () => void,
saveProfile: () => Promise,
saveProfile: BoundSaveProfile,
};

toggleShowPersonalDialog: Function = (): void => {
Expand Down
5 changes: 3 additions & 2 deletions static/js/components/UserPagePersonalDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import Button from 'react-mdl/lib/Button';

import { personalValidation } from '../util/validation';
import PersonalForm from './PersonalForm';
import type { Profile } from '../flow/profileTypes';
import type { Profile, BoundSaveProfile } from '../flow/profileTypes';
import type { UIState } from '../reducers/ui';

export default class UserPagePersonalDialog extends React.Component {
props: {
setUserPageDialogVisibility: () => void,
ui: UIState,
profile: Profile,
saveProfile: () => Promise,
saveProfile: BoundSaveProfile,
clearProfileEdit: () => void,
};

Expand Down Expand Up @@ -51,6 +51,7 @@ export default class UserPagePersonalDialog extends React.Component {

return (
<Dialog
className="personal-dialog"
open={userPageDialogVisibility}
onRequestClose={this.closePersonalDialog}
actions={actions}
Expand Down
10 changes: 5 additions & 5 deletions static/js/containers/ProfileFormContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,17 @@ import {
setProfileStep,
} from '../actions/ui';
import type { Validator, UIValidator } from '../util/validation';
import type { Profile } from '../flow/profileTypes';
import type { Profile, Profiles, ProfileGetResult } from '../flow/profileTypes';
import type { UIState } from '../reducers/ui';

class ProfileFormContainer extends React.Component {
props: {
profiles: {[k: string]: {profile: Profile}},
profiles: Profiles,
children: React$Element[],
dispatch: Dispatch,
history: Object,
ui: UIState,
params: Object,
params: {[k: string]: string},
};

static contextTypes = {
Expand Down Expand Up @@ -164,7 +164,7 @@ class ProfileFormContainer extends React.Component {
}
}

profileProps: Function = (profileFromStore: {profile: Profile}) => {
profileProps: Function = (profileFromStore: ProfileGetResult) => {
let { ui } = this.props;
let errors, isEdit, profile;

Expand Down Expand Up @@ -208,7 +208,7 @@ class ProfileFormContainer extends React.Component {
});
};

childrenWithProps: Function = (profileFromStore: {profile: Profile}) => {
childrenWithProps: Function = (profileFromStore: ProfileGetResult) => {
return React.Children.map(this.props.children, (child) => (
React.cloneElement(child, this.profileProps(profileFromStore))
));
Expand Down
5 changes: 3 additions & 2 deletions static/js/containers/ProfilePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
EMPLOYMENT_STEP,
PRIVACY_STEP,
} from '../constants';
import type { Profile } from '../flow/profileTypes';

class ProfilePage extends ProfileFormContainer {
currentStep: Function = (): string => {
Expand Down Expand Up @@ -62,13 +63,13 @@ class ProfilePage extends ProfileFormContainer {
render() {
const { profiles } = this.props;
const profileInfo = profiles[SETTINGS.username];
let props, text, profile;
let props, text;
let [prev, next] = this.stepTransitions();
props = Object.assign({}, this.profileProps(profileInfo), {
prevStep: prev,
nextStep: next
});
profile = props.profile;
let profile: Profile = props.profile;
text = `Welcome ${getPreferredName(profile)}, let's
complete your enrollment to MIT MicroMasters.`;

Expand Down
37 changes: 25 additions & 12 deletions static/js/containers/ProfilePage_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,23 +73,25 @@ describe("ProfilePage", function() {
helper.cleanup();
});

let confirmSaveButtonBehavior = (updatedProfile, pageElements, validationFailure=false) => {
let confirmSaveButtonBehavior = (updatedProfile, pageElements, validationFailure=false, actions = []) => {
let { div, button } = pageElements;
button = button || div.querySelector(nextButtonSelector);
patchUserProfileStub.throws("Invalid arguments");
patchUserProfileStub.withArgs(SETTINGS.username, updatedProfile).returns(Promise.resolve(updatedProfile));

let actions = [];
if (!validationFailure) {
if ( actions.length === 0 ) {
if (!validationFailure) {
actions.push(
REQUEST_PATCH_USER_PROFILE,
RECEIVE_PATCH_USER_PROFILE_SUCCESS,
);
}
actions.push(
REQUEST_PATCH_USER_PROFILE,
RECEIVE_PATCH_USER_PROFILE_SUCCESS,
START_PROFILE_EDIT,
UPDATE_PROFILE_VALIDATION
);
}
actions.push(
START_PROFILE_EDIT,
UPDATE_PROFILE_VALIDATION
);

return listenForActions(actions, () => {
TestUtils.Simulate.click(button);
});
Expand Down Expand Up @@ -301,7 +303,10 @@ describe("ProfilePage", function() {
helper.store.dispatch(receiveGetUserProfileSuccess(SETTINGS.username, noEducation));

let toggle = div.querySelector(selector);
return listenForActions([SET_EDUCATION_DEGREE_INCLUSIONS], () => {
return listenForActions([
SET_EDUCATION_DEGREE_INCLUSIONS,
SET_EDUCATION_DEGREE_INCLUSIONS,
], () => {
TestUtils.Simulate.change(toggle);
assert.equal(openDialog(), undefined);
TestUtils.Simulate.change(toggle);
Expand Down Expand Up @@ -428,8 +433,16 @@ describe("ProfilePage", function() {
filled_out: true
});

return confirmSaveButtonBehavior(updatedProfile, {button: button}, true).then(state => {
assert.deepEqual(state.profiles[SETTINGS.username].edit.errors, {});
let actions = [
START_PROFILE_EDIT,
UPDATE_PROFILE_VALIDATION,
REQUEST_PATCH_USER_PROFILE,
RECEIVE_PATCH_USER_PROFILE_SUCCESS,
CLEAR_PROFILE_EDIT,
];

return confirmSaveButtonBehavior(updatedProfile, {button: button}, true, actions).then(state => {
assert.deepEqual(state.profiles[SETTINGS.username].profile.edit, undefined);
});
});
});
Expand Down
6 changes: 3 additions & 3 deletions static/js/containers/UserPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Loader from 'react-loader';

import { FETCH_PROCESSING, clearProfile } from '../actions';
import ProfileFormContainer from './ProfileFormContainer';
import ErrorMessage from '../components/ErrorMessage';

class UserPage extends ProfileFormContainer {
componentDidMount() {
Expand Down Expand Up @@ -35,10 +36,9 @@ class UserPage extends ProfileFormContainer {
profile = profiles[username];
loaded = profiles[username].getStatus !== FETCH_PROCESSING;
}

let childrenWithProps = this.childrenWithProps(profile);
const { errorInfo } = profile;
return <Loader loaded={loaded}>
{ childrenWithProps }
{errorInfo && loaded ? <ErrorMessage errorInfo={errorInfo} /> : this.childrenWithProps(profile)}
</Loader>;
}
}
Expand Down
Loading

0 comments on commit ed19858

Please sign in to comment.