diff --git a/.eslintrc b/.eslintrc
index b6eccc73a4..1bad008c04 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -189,6 +189,7 @@
"react/prop-types": 2,
"react/react-in-jsx-scope": 2,
"react/self-closing-comp": 2,
+ "react/sort-prop-types": 2,
"import/default": 2,
"import/export": 2,
diff --git a/common/app/App.jsx b/common/app/App.jsx
index 23300a77e5..72e4f7790c 100644
--- a/common/app/App.jsx
+++ b/common/app/App.jsx
@@ -56,23 +56,23 @@ const mapStateToProps = createSelector(
const propTypes = {
children: PropTypes.node,
- username: PropTypes.string,
- isSignedIn: PropTypes.bool,
- points: PropTypes.number,
- picture: PropTypes.string,
- toast: PropTypes.object,
- updateNavHeight: PropTypes.func,
- initWindowHeight: PropTypes.func,
- submitChallenge: PropTypes.func,
+ closeDropdown: PropTypes.func.isRequired,
fetchUser: PropTypes.func,
- showLoading: PropTypes.bool,
- params: PropTypes.object,
- updateAppLang: PropTypes.func.isRequired,
- trackEvent: PropTypes.func.isRequired,
+ initWindowHeight: PropTypes.func,
+ isNavDropdownOpen: PropTypes.bool,
+ isSignedIn: PropTypes.bool,
loadCurrentChallenge: PropTypes.func.isRequired,
openDropdown: PropTypes.func.isRequired,
- closeDropdown: PropTypes.func.isRequired,
- isNavDropdownOpen: PropTypes.bool
+ params: PropTypes.object,
+ picture: PropTypes.string,
+ points: PropTypes.number,
+ showLoading: PropTypes.bool,
+ submitChallenge: PropTypes.func,
+ toast: PropTypes.object,
+ trackEvent: PropTypes.func.isRequired,
+ updateAppLang: PropTypes.func.isRequired,
+ updateNavHeight: PropTypes.func,
+ username: PropTypes.string
};
// export plain class for testing
diff --git a/common/app/components/Nav/Avatar-Points-Nav-Item.jsx b/common/app/components/Nav/Avatar-Points-Nav-Item.jsx
index f2483ef2df..d8907f2b1b 100644
--- a/common/app/components/Nav/Avatar-Points-Nav-Item.jsx
+++ b/common/app/components/Nav/Avatar-Points-Nav-Item.jsx
@@ -3,6 +3,13 @@ import { Link } from 'react-router';
// this is separated out to prevent react bootstrap's
// NavBar from injecting unknown props to the li component
+
+const propTypes = {
+ picture: PropTypes.string,
+ points: PropTypes.number,
+ username: PropTypes.string
+};
+
export default function AvatarPointsNavItem({ picture, points, username }) {
return (
({ isOpen: state.challengesApp.isBugOpen });
const actions = { createIssue, openIssueSearch, closeBugModal };
const bugLink = 'http://forum.freecodecamp.com/t/how-to-report-a-bug/19543';
+const propTypes = {
+ closeBugModal: PropTypes.func,
+ createIssue: PropTypes.func,
+ isOpen: PropTypes.bool,
+ openIssueSearch: PropTypes.func
+};
+
export class BugModal extends PureComponent {
- static propTypes = {
- isOpen: PropTypes.bool,
- closeBugModal: PropTypes.func,
- openIssueSearch: PropTypes.func,
- createIssue: PropTypes.func
- };
render() {
const {
@@ -81,4 +82,7 @@ export class BugModal extends PureComponent {
}
}
+BugModal.displayName = 'BugModal';
+BugModal.propTypes = propTypes;
+
export default connect(mapStateToProps, actions)(BugModal);
diff --git a/common/app/routes/challenges/components/Output.jsx b/common/app/routes/challenges/components/Output.jsx
index 1969f6d3ee..476c4324d4 100644
--- a/common/app/routes/challenges/components/Output.jsx
+++ b/common/app/routes/challenges/components/Output.jsx
@@ -12,6 +12,11 @@ const defaultOptions = {
lineWrapping: true
};
+const propTypes = {
+ defaultOutput: PropTypes.string,
+ output: PropTypes.string
+};
+
export default class Output extends PureComponent {
render() {
const { output, defaultOutput } = this.props;
@@ -29,7 +34,4 @@ export default class Output extends PureComponent {
}
Output.displayName = 'Output';
-Output.propTypes = {
- output: PropTypes.string,
- defaultOutput: PropTypes.string
-};
+Output.propTypes = propTypes;
diff --git a/common/app/routes/challenges/components/Show.jsx b/common/app/routes/challenges/components/Show.jsx
index 66925b068a..c5b79922e7 100644
--- a/common/app/routes/challenges/components/Show.jsx
+++ b/common/app/routes/challenges/components/Show.jsx
@@ -77,23 +77,22 @@ const link = 'http://forum.freecodecamp.com/t/' +
'guidelines-for-translating-free-code-camp' +
'-to-any-language/19111';
-export class Challenges extends PureComponent {
- static displayName = 'Challenges';
+const propTypes = {
+ areChallengesLoaded: PropTypes.bool,
+ fetchChallenges: PropTypes.func.isRequired,
+ isStep: PropTypes.bool,
+ isTranslated: PropTypes.bool,
+ lang: PropTypes.string.isRequired,
+ makeToast: PropTypes.func.isRequired,
+ params: PropTypes.object.isRequired,
+ replaceChallenge: PropTypes.func.isRequired,
+ resetUi: PropTypes.func.isRequired,
+ title: PropTypes.string,
+ updateTitle: PropTypes.func.isRequired,
+ viewType: PropTypes.string
+ };
- static propTypes = {
- title: PropTypes.string,
- viewType: PropTypes.string,
- isStep: PropTypes.bool,
- fetchChallenges: PropTypes.func.isRequired,
- replaceChallenge: PropTypes.func.isRequired,
- params: PropTypes.object.isRequired,
- areChallengesLoaded: PropTypes.bool,
- resetUi: PropTypes.func.isRequired,
- updateTitle: PropTypes.func.isRequired,
- makeToast: PropTypes.func.isRequired,
- lang: PropTypes.string.isRequired,
- isTranslated: PropTypes.bool
- };
+export class Challenges extends PureComponent {
componentWillMount() {
const { lang, isTranslated, makeToast } = this.props;
@@ -153,6 +152,9 @@ export class Challenges extends PureComponent {
}
}
+Challenges.displayName = 'Challenges';
+Challenges.propTypes = propTypes;
+
export default compose(
connect(mapStateToProps, bindableActions),
contain(fetchOptions)
diff --git a/common/app/routes/challenges/components/Solution-Input.jsx b/common/app/routes/challenges/components/Solution-Input.jsx
index 2fb518e37b..afbf2cdc23 100644
--- a/common/app/routes/challenges/components/Solution-Input.jsx
+++ b/common/app/routes/challenges/components/Solution-Input.jsx
@@ -2,6 +2,11 @@ import React, { PropTypes } from 'react';
import { HelpBlock, FormGroup, FormControl } from 'react-bootstrap';
import { getValidationState, DOMOnlyProps } from '../../../utils/form';
+const propTypes = {
+ placeholder: PropTypes.string,
+ solution: PropTypes.object
+};
+
export default function SolutionInput({ solution, placeholder }) {
const validationState = getValidationState(solution);
return (
@@ -24,7 +29,5 @@ export default function SolutionInput({ solution, placeholder }) {
);
}
-SolutionInput.propTypes = {
- solution: PropTypes.object,
- placeholder: PropTypes.string
-};
+SolutionInput.displayName = 'SolutionInput';
+SolutionInput.propTypes = propTypes;
diff --git a/common/app/routes/challenges/components/backend/Back-End.jsx b/common/app/routes/challenges/components/backend/Back-End.jsx
index 327f022cf8..6ebf301168 100644
--- a/common/app/routes/challenges/components/backend/Back-End.jsx
+++ b/common/app/routes/challenges/components/backend/Back-End.jsx
@@ -19,19 +19,23 @@ import {
createFormValidator
} from '../../../../utils/form.js';
-const propTypes = {
- id: PropTypes.string,
- title: PropTypes.string,
- description: PropTypes.arrayOf(PropTypes.string),
- tests: PropTypes.array,
- output: PropTypes.string,
- executeChallenge: PropTypes.func.isRequired,
- submitChallenge: PropTypes.func.isRequired,
- // provided by redux form
- submitting: PropTypes.bool,
+// provided by redux form
+const reduxFormPropTypes = {
fields: PropTypes.object,
+ handleSubmit: PropTypes.func.isRequired,
resetForm: PropTypes.func.isRequired,
- handleSubmit: PropTypes.func.isRequired
+ submitting: PropTypes.bool
+};
+
+const propTypes = {
+ description: PropTypes.arrayOf(PropTypes.string),
+ executeChallenge: PropTypes.func.isRequired,
+ id: PropTypes.string,
+ output: PropTypes.string,
+ submitChallenge: PropTypes.func.isRequired,
+ tests: PropTypes.array,
+ title: PropTypes.string,
+ ...reduxFormPropTypes
};
const fields = [ 'solution' ];
diff --git a/common/app/routes/challenges/components/classic/Classic.jsx b/common/app/routes/challenges/components/classic/Classic.jsx
index 01b78f94d0..aaaae44a22 100644
--- a/common/app/routes/challenges/components/classic/Classic.jsx
+++ b/common/app/routes/challenges/components/classic/Classic.jsx
@@ -57,24 +57,23 @@ const bindableActions = {
updateSuccessMessage
};
-export class Challenge extends PureComponent {
- static displayName = 'Challenge';
+const propTypes = {
+ closeChallengeModal: PropTypes.func,
+ content: PropTypes.string,
+ executeChallenge: PropTypes.func,
+ file: PropTypes.object,
+ id: PropTypes.string,
+ isChallengeModalOpen: PropTypes.bool,
+ loadCode: PropTypes.func,
+ mode: PropTypes.string,
+ showPreview: PropTypes.bool,
+ submitChallenge: PropTypes.func,
+ successMessage: PropTypes.string,
+ updateFile: PropTypes.func,
+ updateSuccessMessage: PropTypes.func
+};
- static propTypes = {
- id: PropTypes.string,
- showPreview: PropTypes.bool,
- content: PropTypes.string,
- mode: PropTypes.string,
- file: PropTypes.object,
- updateFile: PropTypes.func,
- executeChallenge: PropTypes.func,
- loadCode: PropTypes.func,
- submitChallenge: PropTypes.func,
- isChallengeModalOpen: PropTypes.bool,
- closeChallengeModal: PropTypes.func,
- successMessage: PropTypes.string,
- updateSuccessMessage: PropTypes.func
- };
+export class Challenge extends PureComponent {
componentDidMount() {
this.props.loadCode();
@@ -148,4 +147,7 @@ export class Challenge extends PureComponent {
}
}
+Challenge.displayName = 'Challenge';
+Challenge.propTypes = propTypes;
+
export default connect(mapStateToProps, bindableActions)(Challenge);
diff --git a/common/app/routes/challenges/components/classic/Editor.jsx b/common/app/routes/challenges/components/classic/Editor.jsx
index ec4841077d..f35eb37cde 100644
--- a/common/app/routes/challenges/components/classic/Editor.jsx
+++ b/common/app/routes/challenges/components/classic/Editor.jsx
@@ -32,25 +32,25 @@ const options = {
gutters: ['CodeMirror-lint-markers']
};
+const defaultProps = {
+ content: '// Happy Coding!',
+ mode: 'javascript'
+};
+
+const propTypes = {
+ content: PropTypes.string,
+ executeChallenge: PropTypes.func,
+ height: PropTypes.number,
+ mode: PropTypes.string,
+ updateFile: PropTypes.func
+};
+
export class Editor extends PureComponent {
constructor(...args) {
super(...args);
this._editorContent$ = new Subject();
this.handleChange = this.handleChange.bind(this);
}
- static displayName = 'Editor';
- static propTypes = {
- executeChallenge: PropTypes.func,
- height: PropTypes.number,
- content: PropTypes.string,
- mode: PropTypes.string,
- updateFile: PropTypes.func
- };
-
- static defaultProps = {
- content: '// Happy Coding!',
- mode: 'javascript'
- };
createOptions = createSelector(
state => state.options,
@@ -148,4 +148,9 @@ export class Editor extends PureComponent {
}
}
+Editor.defaultProps = defaultProps;
+Editor.displayName = 'Editor';
+Editor.propTypes = propTypes;
+
+
export default connect(mapStateToProps)(Editor);
diff --git a/common/app/routes/challenges/components/classic/Preview.jsx b/common/app/routes/challenges/components/classic/Preview.jsx
index 21f42aa846..ce0fdb1e13 100644
--- a/common/app/routes/challenges/components/classic/Preview.jsx
+++ b/common/app/routes/challenges/components/classic/Preview.jsx
@@ -2,9 +2,8 @@ import React from 'react';
import PureComponent from 'react-pure-render/component';
const mainId = 'fcc-main-frame';
-export default class extends PureComponent {
- static displayName = 'Preview';
+export default class Preview extends PureComponent {
render() {
return (
{
@@ -174,6 +171,9 @@ export class SidePanel extends PureComponent {
}
}
+SidePanel.displayName = 'SidePanel';
+SidePanel.propTypes = propTypes;
+
export default connect(
mapStateToProps,
mapDispatchToProps
diff --git a/common/app/routes/challenges/components/map/Block.jsx b/common/app/routes/challenges/components/map/Block.jsx
index 57f6ea2d50..e07e185013 100644
--- a/common/app/routes/challenges/components/map/Block.jsx
+++ b/common/app/routes/challenges/components/map/Block.jsx
@@ -29,22 +29,21 @@ const makeMapStateToProps = () => createSelector(
};
}
);
+const propTypes = {
+ challenges: PropTypes.array,
+ dashedName: PropTypes.string,
+ isHidden: PropTypes.bool,
+ isOpen: PropTypes.bool,
+ time: PropTypes.string,
+ title: PropTypes.string,
+ toggleThisPanel: PropTypes.func
+};
+
export class Block extends PureComponent {
constructor(...props) {
super(...props);
this.handleSelect = this.handleSelect.bind(this);
}
- static displayName = 'Block';
- static propTypes = {
- title: PropTypes.string,
- dashedName: PropTypes.string,
- time: PropTypes.string,
- isOpen: PropTypes.bool,
- isHidden: PropTypes.bool,
- challenges: PropTypes.array,
- toggleThisPanel: PropTypes.func
- };
-
handleSelect(eventKey, e) {
e.preventDefault();
this.props.toggleThisPanel(eventKey);
@@ -108,4 +107,7 @@ export class Block extends PureComponent {
}
}
+Block.displayName = 'Block';
+Block.propTypes = propTypes;
+
export default connect(makeMapStateToProps, dispatchActions)(Block);
diff --git a/common/app/routes/challenges/components/map/Header.jsx b/common/app/routes/challenges/components/map/Header.jsx
index 935d81d7e8..1a2af91e78 100644
--- a/common/app/routes/challenges/components/map/Header.jsx
+++ b/common/app/routes/challenges/components/map/Header.jsx
@@ -23,21 +23,21 @@ const mapStateToProps = state => ({
isAllCollapsed: state.challengesApp.mapUi.isAllCollapsed,
filter: state.challengesApp.filter
});
+const propTypes = {
+ clearFilter: PropTypes.func,
+ collapseAll: PropTypes.func,
+ expandAll: PropTypes.func,
+ filter: PropTypes.string,
+ isAllCollapsed: PropTypes.bool,
+ updateFilter: PropTypes.func
+};
+
export class Header extends PureComponent {
constructor(...props) {
super(...props);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleClearButton = this.handleClearButton.bind(this);
}
- static displayName = 'MapHeader';
- static propTypes = {
- isAllCollapsed: PropTypes.bool,
- filter: PropTypes.string,
- clearFilter: PropTypes.func,
- updateFilter: PropTypes.func,
- collapseAll: PropTypes.func,
- expandAll: PropTypes.func
- };
handleKeyDown(e) {
if (e.keyCode === ESC) {
@@ -116,4 +116,8 @@ export class Header extends PureComponent {
);
}
}
+
+Header.displayName = 'MapHeader';
+Header.propTypes = propTypes;
+
export default connect(mapStateToProps, bindableActions)(Header);
diff --git a/common/app/routes/challenges/components/map/Map.jsx b/common/app/routes/challenges/components/map/Map.jsx
index e340b96696..cb3f39919a 100644
--- a/common/app/routes/challenges/components/map/Map.jsx
+++ b/common/app/routes/challenges/components/map/Map.jsx
@@ -27,16 +27,15 @@ const fetchOptions = {
return Array.isArray(superBlocks) && superBlocks.length > 1;
}
};
-export class ShowMap extends PureComponent {
- static displayName = 'Map';
- static propTypes = {
- superBlocks: PropTypes.array,
- height: PropTypes.number,
- updateTitle: PropTypes.func.isRequired,
- params: PropTypes.object,
- fetchChallenges: PropTypes.func.isRequired
- };
+const propTypes = {
+ fetchChallenges: PropTypes.func.isRequired,
+ height: PropTypes.number,
+ params: PropTypes.object,
+ superBlocks: PropTypes.array,
+ updateTitle: PropTypes.func.isRequired
+};
+export class ShowMap extends PureComponent {
componentWillMount() {
// if no params then map is open in drawer
// do not update title
@@ -81,6 +80,9 @@ export class ShowMap extends PureComponent {
}
}
+ShowMap.displayName = 'Map';
+ShowMap.propTypes = propTypes;
+
export default compose(
connect(mapStateToProps, bindableActions),
contain(fetchOptions)
diff --git a/common/app/routes/challenges/components/map/Super-Block.jsx b/common/app/routes/challenges/components/map/Super-Block.jsx
index 986c42534f..8f6e4e439e 100644
--- a/common/app/routes/challenges/components/map/Super-Block.jsx
+++ b/common/app/routes/challenges/components/map/Super-Block.jsx
@@ -36,22 +36,21 @@ const makeMapStateToProps = () => {
);
};
+const propTypes = {
+ blocks: PropTypes.array,
+ dashedName: PropTypes.string,
+ isHidden: PropTypes.bool,
+ isOpen: PropTypes.bool,
+ message: PropTypes.string,
+ title: PropTypes.string,
+ toggleThisPanel: PropTypes.func
+};
+
export class SuperBlock extends PureComponent {
constructor(...props) {
super(...props);
this.handleSelect = this.handleSelect.bind(this);
}
- static displayName = 'SuperBlock';
- static propTypes = {
- title: PropTypes.string,
- dashedName: PropTypes.string,
- blocks: PropTypes.array,
- isOpen: PropTypes.bool,
- isHidden: PropTypes.bool,
- message: PropTypes.string,
- toggleThisPanel: PropTypes.func
- };
-
handleSelect(eventKey, e) {
e.preventDefault();
this.props.toggleThisPanel(eventKey);
@@ -126,6 +125,9 @@ export class SuperBlock extends PureComponent {
}
}
+SuperBlock.displayName = 'SuperBlock';
+SuperBlock.propTypes = propTypes;
+
export default connect(
makeMapStateToProps,
dispatchActions
diff --git a/common/app/routes/challenges/components/project/Forms.jsx b/common/app/routes/challenges/components/project/Forms.jsx
index bbaf3265ac..d1a7c6b825 100644
--- a/common/app/routes/challenges/components/project/Forms.jsx
+++ b/common/app/routes/challenges/components/project/Forms.jsx
@@ -16,13 +16,13 @@ import {
import { submitChallenge, showProjectSubmit } from '../../redux/actions';
const propTypes = {
- isSignedIn: PropTypes.bool,
- isSubmitting: PropTypes.bool,
- showProjectSubmit: PropTypes.func,
fields: PropTypes.object,
handleSubmit: PropTypes.func,
- submitChallenge: PropTypes.func,
- resetForm: PropTypes.func
+ isSignedIn: PropTypes.bool,
+ isSubmitting: PropTypes.bool,
+ resetForm: PropTypes.func,
+ showProjectSubmit: PropTypes.func,
+ submitChallenge: PropTypes.func
};
const bindableActions = {
diff --git a/common/app/routes/challenges/components/project/Project.jsx b/common/app/routes/challenges/components/project/Project.jsx
index bd40394d05..cf14b84022 100644
--- a/common/app/routes/challenges/components/project/Project.jsx
+++ b/common/app/routes/challenges/components/project/Project.jsx
@@ -29,17 +29,15 @@ const mapStateToProps = createSelector(
description
})
);
+const propTypes = {
+ description: PropTypes.arrayOf(PropTypes.string),
+ id: PropTypes.string,
+ isCompleted: PropTypes.bool,
+ title: PropTypes.string,
+ videoId: PropTypes.string
+};
export class Project extends PureComponent {
- static displayName = 'Project';
- static propTypes = {
- id: PropTypes.string,
- videoId: PropTypes.string,
- title: PropTypes.string,
- description: PropTypes.arrayOf(PropTypes.string),
- isCompleted: PropTypes.bool
- };
-
render() {
const {
id,
@@ -78,6 +76,9 @@ export class Project extends PureComponent {
}
}
+Project.displayName = 'Project';
+Project.propTypes = propTypes;
+
export default connect(
mapStateToProps
)(Project);
diff --git a/common/app/routes/challenges/components/project/Side-Panel.jsx b/common/app/routes/challenges/components/project/Side-Panel.jsx
index e4ecdd6d25..014231b60c 100644
--- a/common/app/routes/challenges/components/project/Side-Panel.jsx
+++ b/common/app/routes/challenges/components/project/Side-Panel.jsx
@@ -2,14 +2,14 @@ import React, { PropTypes } from 'react';
import PureComponent from 'react-pure-render/component';
-export default class SidePanel extends PureComponent {
- static propTypes = {
- title: PropTypes.string,
- description: PropTypes.arrayOf(PropTypes.string),
- isCompleted: PropTypes.bool,
- isSignedIn: PropTypes.bool
- };
+const propTypes = {
+ description: PropTypes.arrayOf(PropTypes.string),
+ isCompleted: PropTypes.bool,
+ isSignedIn: PropTypes.bool,
+ title: PropTypes.string
+};
+export default class SidePanel extends PureComponent {
renderIcon(isCompleted) {
if (!isCompleted) {
return null;
@@ -48,3 +48,6 @@ export default class SidePanel extends PureComponent {
);
}
}
+
+SidePanel.displayName = 'ProjectSidePanel';
+SidePanel.propTypes = propTypes;
diff --git a/common/app/routes/challenges/components/project/Tool-Panel.jsx b/common/app/routes/challenges/components/project/Tool-Panel.jsx
index 19bb93f2eb..cf0c941a15 100644
--- a/common/app/routes/challenges/components/project/Tool-Panel.jsx
+++ b/common/app/routes/challenges/components/project/Tool-Panel.jsx
@@ -17,11 +17,11 @@ import {
} from '../../../../utils/challengeTypes';
const propTypes = {
+ helpChatRoom: PropTypes.string.isRequired,
+ isFrontEnd: PropTypes.bool,
isSignedIn: PropTypes.bool,
isSimple: PropTypes.bool,
- isFrontEnd: PropTypes.bool,
isSubmitting: PropTypes.bool,
- helpChatRoom: PropTypes.string.isRequired,
openBugModal: PropTypes.func.isRequired,
submitChallenge: PropTypes.func.isRequired
};
@@ -109,8 +109,8 @@ export class ToolPanel extends PureComponent {
}
}
+ToolPanel.displayName = 'ProjectToolPanel';
ToolPanel.propTypes = propTypes;
-ToolPanel.displayName = 'ToolPanel';
export default connect(
mapStateToProps,
diff --git a/common/app/routes/challenges/components/step/Step.jsx b/common/app/routes/challenges/components/step/Step.jsx
index 194cca73a2..22693501ab 100644
--- a/common/app/routes/challenges/components/step/Step.jsx
+++ b/common/app/routes/challenges/components/step/Step.jsx
@@ -62,9 +62,9 @@ const propTypes = {
numOfSteps: PropTypes.number,
openLightBoxImage: PropTypes.func.isRequired,
step: PropTypes.array,
- steps: PropTypes.array,
stepBackward: PropTypes.func,
stepForward: PropTypes.func,
+ steps: PropTypes.array,
submitChallenge: PropTypes.func.isRequired,
updateUnlockedSteps: PropTypes.func.isRequired
};
diff --git a/common/app/routes/challenges/components/video/Lecture.jsx b/common/app/routes/challenges/components/video/Lecture.jsx
index d3bac55694..fbe9284326 100644
--- a/common/app/routes/challenges/components/video/Lecture.jsx
+++ b/common/app/routes/challenges/components/video/Lecture.jsx
@@ -31,20 +31,15 @@ const embedOpts = {
width: '853',
height: '480'
};
+const propTypes = {
+ dashedName: PropTypes.string,
+ description: PropTypes.array,
+ id: PropTypes.string,
+ toggleQuestionView: PropTypes.func,
+ videoId: PropTypes.string
+};
export class Lecture extends React.Component {
- static displayName = 'Lecture';
-
- static propTypes = {
- // actions
- toggleQuestionView: PropTypes.func,
- // ui
- id: PropTypes.string,
- videoId: PropTypes.string,
- description: PropTypes.array,
- dashedName: PropTypes.string
- };
-
shouldComponentUpdate(nextProps) {
const { props } = this;
return nextProps.id !== props.id;
@@ -111,6 +106,9 @@ export class Lecture extends React.Component {
}
}
+Lecture.displayName = 'Lecture';
+Lecture.propTypes = propTypes;
+
export default connect(
mapStateToProps,
{ toggleQuestionView }
diff --git a/common/app/routes/challenges/components/video/Questions.jsx b/common/app/routes/challenges/components/video/Questions.jsx
index e753b7fbe1..3062095426 100644
--- a/common/app/routes/challenges/components/video/Questions.jsx
+++ b/common/app/routes/challenges/components/video/Questions.jsx
@@ -47,27 +47,22 @@ const mapStateToProps = createSelector(
isSignedIn
})
);
+const propTypes = {
+ answerQuestion: PropTypes.func,
+ currentQuestion: PropTypes.number,
+ delta: PropTypes.array,
+ grabQuestion: PropTypes.func,
+ isCorrect: PropTypes.bool,
+ isPressed: PropTypes.bool,
+ isSignedIn: PropTypes.bool,
+ mouse: PropTypes.array,
+ moveQuestion: PropTypes.func,
+ releaseQuestion: PropTypes.func,
+ shouldShakeQuestion: PropTypes.bool,
+ tests: PropTypes.array
+};
class Question extends React.Component {
- static displayName = 'Questions';
-
- static propTypes = {
- // actions
- answerQuestion: PropTypes.func,
- releaseQuestion: PropTypes.func,
- moveQuestion: PropTypes.func,
- grabQuestion: PropTypes.func,
- // ui state
- tests: PropTypes.array,
- mouse: PropTypes.array,
- delta: PropTypes.array,
- isCorrect: PropTypes.bool,
- isPressed: PropTypes.bool,
- isSignedIn: PropTypes.bool,
- currentQuestion: PropTypes.number,
- shouldShakeQuestion: PropTypes.bool
- };
-
handleMouseUp(e, answer, info) {
e.stopPropagation();
if (!this.props.isPressed) {
@@ -191,4 +186,7 @@ class Question extends React.Component {
}
}
+Question.displayName = 'Question';
+Question.propTypes = propTypes;
+
export default connect(mapStateToProps, actionsToBind)(Question);
diff --git a/common/app/routes/challenges/components/video/Video.jsx b/common/app/routes/challenges/components/video/Video.jsx
index 2bb00cf0fc..b9785f2f26 100644
--- a/common/app/routes/challenges/components/video/Video.jsx
+++ b/common/app/routes/challenges/components/video/Video.jsx
@@ -18,21 +18,15 @@ const mapStateToProps = createSelector(
shouldShowQuestions
})
);
+const propTypes = {
+ params: PropTypes.object,
+ resetUi: PropTypes.func,
+ shouldShowQuestions: PropTypes.bool,
+ title: PropTypes.string,
+ updateTitle: PropTypes.func
+};
-// export plain component for testing
export class Video extends React.Component {
- static displayName = 'Video';
-
- static propTypes = {
- // actions
- resetUi: PropTypes.func,
- // ui
- title: PropTypes.string,
- params: PropTypes.object,
- shouldShowQuestions: PropTypes.bool,
- updateTitle: PropTypes.func
- };
-
componentWillMount() {
const { updateTitle, title } = this.props;
updateTitle(title);
@@ -78,7 +72,9 @@ export class Video extends React.Component {
}
}
-// export redux aware component
+Video.displayName = 'Video';
+Video.propTypes = propTypes;
+
export default connect(
mapStateToProps,
bindableActions
diff --git a/common/app/routes/settings/components/Email-Setting.jsx b/common/app/routes/settings/components/Email-Setting.jsx
index 76b940bb70..e83a847103 100644
--- a/common/app/routes/settings/components/Email-Setting.jsx
+++ b/common/app/routes/settings/components/Email-Setting.jsx
@@ -4,6 +4,16 @@ import { Button, Row, Col } from 'react-bootstrap';
import FA from 'react-fontawesome';
import classnames from 'classnames';
+const propTypes = {
+ email: PropTypes.string,
+ sendMonthlyEmail: PropTypes.bool,
+ sendNotificationEmail: PropTypes.bool,
+ sendQuincyEmail: PropTypes.bool,
+ toggleMonthlyEmail: PropTypes.func.isRequired,
+ toggleNotificationEmail: PropTypes.func.isRequired,
+ toggleQuincyEmail: PropTypes.func.isRequired
+};
+
export function UpdateEmailButton() {
return (
{ buttons }
);
}
-SocialSettings.propTypes = {
- isGithubCool: PropTypes.bool,
- isTwitter: PropTypes.bool,
- isLinkedIn: PropTypes.bool
-};
+SocialSettings.displayName = 'SocialSettings';
+SocialSettings.propTypes = propTypes;
diff --git a/common/app/routes/settings/routes/update-email/Update-Email.jsx b/common/app/routes/settings/routes/update-email/Update-Email.jsx
index 04d82f803d..b6c5cf87da 100644
--- a/common/app/routes/settings/routes/update-email/Update-Email.jsx
+++ b/common/app/routes/settings/routes/update-email/Update-Email.jsx
@@ -35,22 +35,20 @@ const mapStateToProps = state => {
isVerified: !!emailVerified
};
};
+const propTypes = {
+ fields: PropTypes.object.isRequired,
+ handleSubmit: PropTypes.func.isRequired,
+ isEmailThere: PropTypes.bool,
+ isVerified: PropTypes.bool,
+ submitting: PropTypes.bool,
+ updateMyEmail: PropTypes.func.isRequired
+};
export class UpdateEmail extends React.Component {
constructor(...props) {
super(...props);
this.handleSubmit = this.handleSubmit.bind(this);
}
- static displayName = 'UpdateEmail';
- static propTypes = {
- isEmailThere: PropTypes.bool,
- isVerified: PropTypes.bool,
- fields: PropTypes.object.isRequired,
- submitting: PropTypes.bool,
- handleSubmit: PropTypes.func.isRequired,
- updateMyEmail: PropTypes.func.isRequired
- };
-
handleSubmit(e) {
e.preventDefault();
this.props.handleSubmit(({ email }) => this.props.updateMyEmail(email))(e);
@@ -133,6 +131,9 @@ export class UpdateEmail extends React.Component {
}
}
+UpdateEmail.displayName = 'UpdateEmail';
+UpdateEmail.propTypes = propTypes;
+
export default reduxForm(
{
form: 'update-email',
diff --git a/common/app/toasts/Toasts.jsx b/common/app/toasts/Toasts.jsx
index 3f82df82d4..035bc4b466 100644
--- a/common/app/toasts/Toasts.jsx
+++ b/common/app/toasts/Toasts.jsx
@@ -58,18 +58,16 @@ const addDispatchableActionsToToast = createSelector(
};
})
);
+const propTypes = {
+ dispatch: PropTypes.func,
+ toasts: PropTypes.arrayOf(PropTypes.object)
+};
export class Toasts extends React.Component {
constructor(...props) {
super(...props);
this.handleDismiss = this.handleDismiss.bind(this);
}
- static displayName = 'Toasts';
- static propTypes = {
- toasts: PropTypes.arrayOf(PropTypes.object),
- dispatch: PropTypes.func
- };
-
styleFactory(index, style) {
return { ...style, bottom: `${4 + index * 8}rem` };
}
@@ -93,4 +91,7 @@ export class Toasts extends React.Component {
}
}
+Toasts.displayName = 'Toasts';
+Toasts.propTypes = propTypes;
+
export default connect(mapStateToProps)(Toasts);
diff --git a/package.json b/package.json
index 33fd31eea9..035d647ea1 100644
--- a/package.json
+++ b/package.json
@@ -133,7 +133,7 @@
"eslint": "^3.1.0",
"eslint-plugin-import": "^2.0.1",
"eslint-plugin-prefer-object-spread": "^1.1.0",
- "eslint-plugin-react": "^6.2.0",
+ "eslint-plugin-react": "^6.9.0",
"gulp": "^3.9.0",
"gulp-babel": "^6.1.1",
"gulp-concat": "^2.6.0",