Skip to content

Commit

Permalink
Removed routing from profile flow
Browse files Browse the repository at this point in the history
This removes routing from the initial profile flow, so that instead of
guiding the user through a series of components which each live at a
different url (`/profile/education` and so on) everything happens at a
single url (`/profile`).

We're now managing the `profileStep` with a redux action. This entails a
pretty big set of changes to `ProfilePage` and `ProfileFormContainer`,
and a smaller set of changes to `SettingsPage` and some other files.

This also changes `validateProfileComplete`, since after determining the
profile is incomplete we now want to dispatch a particular action and
redirect to `/profile`, instead of redirecting to
`/profile/professional`.

`ProfileProgressControls` now accepts two callbacks (or `void`) to
attach to `onClick` on it's buttons, instead of URLs to push onto
`this.context.router`.

Various other changes are necessary to deal with breaking tests and so
on.
  • Loading branch information
alicewriteswrongs committed Jun 29, 2016
1 parent 080fdeb commit e4b9c2c
Show file tree
Hide file tree
Showing 28 changed files with 361 additions and 236 deletions.
2 changes: 2 additions & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
./static/js/flow/declarations.js
node_modules/iflow-lodash/index.js.flow
node_modules/iflow-moment/index.js.flow
node_modules/iflow-react-router/index.js.flow
node_modules/iflow-redux/index.js.flow

[options]
esproposal.class_static_fields=enable
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
"history": "2.1.1",
"iflow-lodash": "^1.1.16",
"iflow-moment": "^1.1.13",
"iflow-react-router": "^1.1.16",
"iflow-redux": "^1.0.37",
"imports-loader": "^0.6.5",
"iso-3166-2": "0.4.0",
"isomorphic-fetch": "2.2.1",
Expand Down
5 changes: 5 additions & 0 deletions static/js/actions/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,8 @@ export const SET_SHOW_EDUCATION_DELETE_ALL_DIALOG = 'SET_SHOW_EDUCATION_DELETE_A
export const setShowEducationDeleteAllDialog = (bool: boolean): Action => (
{ type: SET_SHOW_EDUCATION_DELETE_ALL_DIALOG, payload: bool }
);

export const SET_PROFILE_STEP = 'SET_PROFILE_STEP';
export const setProfileStep = (step: string): Action => (
{ type: SET_PROFILE_STEP, payload: step }
);
3 changes: 2 additions & 1 deletion static/js/components/EducationForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import type {
EducationEntry,
Profile,
ValidationErrors,
BoundSaveProfile,
} from '../flow/profileTypes';
import type { UIState } from '../reducers/ui';

Expand All @@ -32,7 +33,7 @@ class EducationForm extends ProfileFormFields {
profile: Profile,
ui: UIState;
updateProfile: () => void,
saveProfile: () => void,
saveProfile: BoundSaveProfile,
clearProfileEdit: () => void,
errors: ValidationErrors,
setEducationDialogVisibility: () => void,
Expand Down
22 changes: 11 additions & 11 deletions static/js/components/EducationTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,19 @@ import {
educationValidation,
combineValidators,
} from '../util/validation';
import type { Profile, BoundSaveProfile } from '../flow/profileTypes';
import type { UIState } from '../reducers/ui';

class EducationTab extends React.Component {
static propTypes = {
saveProfile: React.PropTypes.func,
profile: React.PropTypes.object,
ui: React.PropTypes.object
props: {
nextStep: () => void,
prevStep: () => void,
profile: Profile,
ui: UIState,
saveProfile: BoundSaveProfile,
};

render() {
const { saveProfile, profile, ui } = this.props;
return <div>
<Grid className="profile-splash">
<Cell col={12}>
Expand All @@ -34,12 +37,9 @@ class EducationTab extends React.Component {
<Cell col={1} />
<Cell col={10}>
<ProfileProgressControls
{...this.props}
nextBtnLabel="Save and Continue"
prevUrl="/profile/personal"
nextUrl="/profile/professional"
saveProfile={saveProfile}
profile={profile}
ui={ui}
isLastTab={false}
validator={combineValidators(educationValidation, educationUiValidation)}
/>
</Cell>
Expand Down
14 changes: 6 additions & 8 deletions static/js/components/EmploymentTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@ import {
employmentUiValidation,
combineValidators,
} from '../util/validation';
import type { Profile } from '../flow/profileTypes';
import type { Profile, BoundSaveProfile } from '../flow/profileTypes';
import type { UIState } from '../reducers/ui';

class EmploymentTab extends React.Component {
props: {
saveProfile: Function,
saveProfile: BoundSaveProfile,
profile: Profile,
ui: UIState,
nextStep: () => void,
prevStep: () => void,
};

render () {
const { saveProfile, profile, ui } = this.props;
return (
<div>
<Grid className="profile-splash">
Expand All @@ -37,12 +38,9 @@ class EmploymentTab extends React.Component {
<Cell col={1}></Cell>
<Cell col={10}>
<ProfileProgressControls
{...this.props}
nextBtnLabel="Save and Continue"
prevUrl="/profile/education"
nextUrl="/profile/privacy"
saveProfile={saveProfile}
profile={profile}
ui={ui}
isLastTab={false}
validator={combineValidators(employmentValidation, employmentUiValidation)}
/>
</Cell>
Expand Down
2 changes: 1 addition & 1 deletion static/js/components/Jumbotron.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Jumbotron extends React.Component {
props: {
profile: Profile,
text: string,
children?: React$Element[],
children?: React$Element[],
};

render() {
Expand Down
13 changes: 6 additions & 7 deletions static/js/components/PersonalTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,21 @@ import Grid, { Cell } from 'react-mdl/lib/Grid';
import PersonalForm from './PersonalForm';
import ProfileProgressControls from './ProfileProgressControls';
import { personalValidation } from '../util/validation';
import type { Profile, ValidationErrors } from '../flow/profileTypes';
import type { Profile, BoundSaveProfile, ValidationErrors } from '../flow/profileTypes';
import type { UIState } from '../reducers/ui';

class PersonalTab extends React.Component {
props: {
profile: Profile,
errors: ValidationErrors,
saveProfile: () => void,
saveProfile: BoundSaveProfile,
updateProfile: () => void,
ui: UIState,
nextStep: () => void,
prevStep: () => void,
};

render() {
const { saveProfile, profile, ui } = this.props;
return <div>
<Grid className="profile-splash">
<Cell col={12}>
Expand All @@ -35,11 +36,9 @@ class PersonalTab extends React.Component {
<Cell col={1} />
<Cell col={10}>
<ProfileProgressControls
{...this.props}
nextBtnLabel="Save and Continue"
nextUrl="/profile/education"
profile={profile}
saveProfile={saveProfile}
ui={ui}
isLastTab={false}
validator={personalValidation}
/>
</Cell>
Expand Down
3 changes: 2 additions & 1 deletion static/js/components/PrivacyForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
import React from 'react';

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

class PrivacyForm extends ProfileFormFields {
props: {
profile: Profile,
ui: UIState,
updateProfile: Function,
errors: ValidationErrors,
};

render() {
Expand Down
13 changes: 5 additions & 8 deletions static/js/components/PrivacyTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,20 @@ import {
employmentValidation,
privacyValidation,
} from '../util/validation';
import type { Profile } from '../flow/profileTypes';
import type { Profile, BoundSaveProfile } from '../flow/profileTypes';
import type { UIState } from '../reducers/ui';

class PrivacyTab extends ProfileFormFields {
props: {
profile: Profile,
saveProfile: () => void,
saveProfile: BoundSaveProfile,
updateProfile: () => void,
ui: UIState,
nextStep: () => void,
prevStep: () => void,
};

render() {
const { saveProfile, profile, ui } = this.props;
return (
<div>
<Grid className="profile-splash">
Expand All @@ -38,13 +39,9 @@ class PrivacyTab extends ProfileFormFields {
</Cell>
<Cell col={12}>
<ProfileProgressControls
{...this.props}
nextBtnLabel="I'm Done!"
prevUrl="/profile/professional"
nextUrl="/dashboard"
isLastTab={true}
saveProfile={saveProfile}
profile={profile}
ui={ui}
validator={
combineValidators(
personalValidation,
Expand Down
37 changes: 17 additions & 20 deletions static/js/components/ProfileProgressControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,41 @@ import React from 'react';
import Button from 'react-mdl/lib/Button';

import { saveProfileStep } from '../util/profile_edit';
import type { Profile, BoundSaveProfile } from '../flow/profileTypes';
import type { UIState } from '../reducers/ui';

export default class ProfileProgressControls extends React.Component {
static propTypes = {
nextBtnLabel: React.PropTypes.string,
nextUrl: React.PropTypes.string,
prevUrl: React.PropTypes.string,
isLastTab: React.PropTypes.bool,
saveProfile: React.PropTypes.func.isRequired,
profile: React.PropTypes.object,
ui: React.PropTypes.object.isRequired,
validator: React.PropTypes.func.isRequired
};

stepBack: Function = (): void => {
const { prevUrl } = this.props;
this.context.router.push(prevUrl);
props: {
nextStep: () => void,
prevStep: () => void,
nextBtnLabel: string,
isLastTab: boolean,
validator: Function,
profile: Profile,
ui: UIState,
saveProfile: BoundSaveProfile,
};

saveAndContinue: Function = (): void => {
const { nextUrl, isLastTab, validator } = this.props;
const { nextStep, isLastTab, validator } = this.props;
saveProfileStep.call(this, validator, isLastTab).then(() => {
this.context.router.push(nextUrl);
nextStep();
});
};

render() {
const { prevUrl, nextUrl, nextBtnLabel } = this.props;
const { nextStep, prevStep, nextBtnLabel } = this.props;

let prevButton, nextButton;
if(prevUrl) {
if(prevStep) {
prevButton = <Button
raised
className="progress-button previous"
onClick={this.stepBack}>
onClick={prevStep}>
<span>Previous</span>
</Button>;
}
if(nextUrl) {
if(nextStep) {
nextButton = <Button
raised
colored
Expand Down
12 changes: 12 additions & 0 deletions static/js/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -372,3 +372,15 @@ export const EDUCATION_LEVELS = [
{value: MASTERS, label: "Master's or professional degree"},
{value: DOCTORATE, label: "Doctorate"}
];

export const PERSONAL_STEP = 'personal';
export const EMPLOYMENT_STEP = 'employment';
export const EDUCATION_STEP = 'education';
export const PRIVACY_STEP = 'privacy';

export const PROFILE_STEP_LABELS = new Map([
[PERSONAL_STEP, "Personal"],
[EDUCATION_STEP, "Education"],
[EMPLOYMENT_STEP, "Professional"],
[PRIVACY_STEP, "Profile Privacy"],
]);
29 changes: 18 additions & 11 deletions static/js/containers/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/* global SETTINGS: false */
import React from 'react';
import { connect } from 'react-redux';
import type { Dispatch } from 'redux';

import Header from '../components/Header';
import Footer from '../components/Footer';
Expand All @@ -14,20 +15,23 @@ import {
startProfileEdit,
updateProfileValidation,
} from '../actions/index';
import { clearUI } from '../actions/ui';
import { clearUI, setProfileStep } from '../actions/ui';
import { validateProfileComplete } from '../util/validation';
import type { Profile } from '../flow/profileTypes';
import type { UIState } from '../reducers/ui';

const TERMS_OF_SERVICE_REGEX = /\/terms_of_service\/?/;
const PROFILE_REGEX = /^\/profile\/?[a-z]?/;

class App extends React.Component {
static propTypes = {
children: React.PropTypes.object.isRequired,
userProfile: React.PropTypes.object.isRequired,
dashboard: React.PropTypes.object.isRequired,
dispatch: React.PropTypes.func.isRequired,
history: React.PropTypes.object.isRequired,
ui: React.PropTypes.object.isRequired,
props: {
children: React$Element[],
userProfile: {profile: Profile, getStatus: string},
location: Object,
dispatch: Dispatch,
dashboard: Object,
history: Object,
ui: UIState,
};

static contextTypes = {
Expand Down Expand Up @@ -101,7 +105,7 @@ class App extends React.Component {
location: { pathname },
dispatch,
} = this.props;
const [ complete, url, errors] = validateProfileComplete(profile);
const [ complete, step, errors] = validateProfileComplete(profile);
if (
userProfile.getStatus === FETCH_SUCCESS &&
profile.agreed_to_terms_of_service &&
Expand All @@ -110,10 +114,13 @@ class App extends React.Component {
) {
dispatch(startProfileEdit(SETTINGS.username));
dispatch(updateProfileValidation(SETTINGS.username, errors));
this.context.router.push(url);
if ( step !== null ) {
dispatch(setProfileStep(step));
}
this.context.router.push('/profile');
}
}

render() {
const { children, location: { pathname } } = this.props;

Expand Down
Loading

0 comments on commit e4b9c2c

Please sign in to comment.