From 6e9fe7809360f9c657b25e8c7c1922f33bdefc56 Mon Sep 17 00:00:00 2001 From: Dan Wilt Date: Fri, 15 Jun 2018 09:11:40 -0400 Subject: [PATCH] wired up mailing list checkbox completely --- .eslintignore | 4 +- .flowconfig | 4 + .gitignore | 1 + flow-typed/npm/classnames_v2.x.x.js | 23 ++ flow-typed/npm/prop-types_v15.x.x.js | 35 ++ package.json | 3 +- src/components/ActionButton/ActionButton.js | 18 +- .../ActionButton/ActionButton.test.js | 10 +- src/components/ActionButton/index.js | 2 +- .../ActivityIndicator.component.js | 30 +- src/components/ActivityIndicator/index.js | 2 +- src/components/Answer/Answer.component.js | 44 +-- src/components/Answer/index.js | 2 +- src/components/App/App.component.js | 14 +- src/components/App/App.container.js | 6 +- src/components/App/App.test.js | 10 +- src/components/App/index.js | 2 +- src/components/Checkbox/Checkbox.component.js | 50 ++- src/components/Checkbox/Checkbox.css | 4 + src/components/Checkbox/index.js | 2 +- .../CodeFigure/CodeFigure.component.js | 12 +- src/components/CodeFigure/index.js | 2 +- .../Completed/Completed.component.js | 8 +- .../Completed/Completed.container.js | 6 +- src/components/Completed/Completed/index.js | 2 +- .../CompletedHeader.component.js | 36 +- .../CompletedHeader.container.js | 6 +- .../Completed/CompletedHeader/index.js | 2 +- .../CompletedResultsList.component.js | 52 +-- .../CompletedResultsList.container.js | 6 +- .../Completed/CompletedResultsList/index.js | 2 +- .../Completed/Results/Results.component.js | 8 +- src/components/Completed/Results/index.js | 2 +- .../EmailCapture/EmailCapture.component.js | 22 +- .../EmailCapture/EmailCapture.css | 4 + .../EmailCapture/EmailCapture/index.js | 2 +- .../EmailCaptureContinueButton.component.js | 8 +- .../EmailCaptureContinueButton.container.js | 6 +- .../EmailCaptureContinueButton/index.js | 2 +- .../EmailCaptureEmailInput.component.js | 12 +- .../EmailCaptureEmailInput.container.js | 8 +- .../EmailCaptureEmailInput/index.js | 2 +- .../NameCapture/NameCapture.component.js | 19 +- .../NameCapture/NameCapture/index.js | 2 +- .../NameCaptureContinueButton.component.js | 6 +- .../NameCaptureContinueButton.container.js | 8 +- .../NameCaptureContinueButton/index.js | 2 +- .../NameCaptureNameInput.component.js | 12 +- .../NameCaptureNameInput.container.js | 8 +- .../NameCapture/NameCaptureNameInput/index.js | 2 +- src/components/Question/Question.component.js | 10 +- src/components/Question/index.js | 2 +- .../QuestionAnswer.component.js | 8 +- .../QuestionAnswer.container.js | 8 +- src/components/QuestionAnswer/index.js | 2 +- src/components/Quiz/Quiz.component.js | 24 +- src/components/Quiz/Quiz.container.js | 8 +- src/components/Quiz/index.js | 2 +- .../QuizProgressIndicator.component.js | 22 +- .../QuizProgressIndicator.container.js | 8 +- src/components/QuizProgressIndicator/index.js | 2 +- .../QuizQuestion/QuizQuestion.component.js | 38 +- .../QuizQuestion/QuizQuestion.container.js | 8 +- src/components/QuizQuestion/index.js | 2 +- ...ubscribeToMailingListCheckbox.component.js | 10 +- ...ubscribeToMailingListCheckbox.container.js | 13 +- .../SubscribeToMailingListCheckbox/index.js | 4 +- .../TextInput/TextInput.component.js | 16 +- src/components/TextInput/index.js | 2 +- src/helpers/flowTypes.js | 0 src/helpers/index.js | 10 +- src/helpers/numbers.js | 2 +- src/helpers/propTypes.js | 4 +- src/helpers/redux.js | 2 +- src/index.js | 16 +- src/questions.js | 336 +++++++++--------- src/selectors/index.js | 4 +- src/selectors/quiz.selectors.js | 5 +- src/services/firebase.service.js | 4 +- src/store/index.js | 8 +- src/store/quiz/quiz.actions.js | 40 ++- src/store/quiz/quiz.reducer.js | 2 +- src/store/reducers.js | 6 +- src/store/sagas.js | 6 +- src/store/state/state.actions.js | 8 +- src/store/state/state.reducer.js | 6 +- yarn.lock | 8 + 87 files changed, 664 insertions(+), 527 deletions(-) create mode 100644 .flowconfig create mode 100644 flow-typed/npm/classnames_v2.x.x.js create mode 100644 flow-typed/npm/prop-types_v15.x.x.js create mode 100644 src/helpers/flowTypes.js diff --git a/.eslintignore b/.eslintignore index f052929..9b7740d 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,4 @@ -firebaseFunctions/node_modules +firebaseFunctions/node_modules/**/* +functions/node_modules/**/* +node_modules/**/* src/registerServiceWorker.js diff --git a/.flowconfig b/.flowconfig new file mode 100644 index 0000000..0b83415 --- /dev/null +++ b/.flowconfig @@ -0,0 +1,4 @@ +[ignore] +.*/firebaseFunctions/node_modules/.* +.*/functions/node_modules/.* +.*/node_modules/.* diff --git a/.gitignore b/.gitignore index 4b92af2..fcc8645 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ # dependencies node_modules +firebaseFunctions/node_modules # testing /coverage diff --git a/flow-typed/npm/classnames_v2.x.x.js b/flow-typed/npm/classnames_v2.x.x.js new file mode 100644 index 0000000..2307243 --- /dev/null +++ b/flow-typed/npm/classnames_v2.x.x.js @@ -0,0 +1,23 @@ +// flow-typed signature: cf86673cc32d185bdab1d2ea90578d37 +// flow-typed version: 614bf49aa8/classnames_v2.x.x/flow_>=v0.25.x + +type $npm$classnames$Classes = + | string + | { [className: string]: * } + | false + | void + | null; + +declare module "classnames" { + declare module.exports: ( + ...classes: Array<$npm$classnames$Classes | $npm$classnames$Classes[]> + ) => string; +} + +declare module "classnames/bind" { + declare module.exports: $Exports<"classnames">; +} + +declare module "classnames/dedupe" { + declare module.exports: $Exports<"classnames">; +} diff --git a/flow-typed/npm/prop-types_v15.x.x.js b/flow-typed/npm/prop-types_v15.x.x.js new file mode 100644 index 0000000..ba9478b --- /dev/null +++ b/flow-typed/npm/prop-types_v15.x.x.js @@ -0,0 +1,35 @@ +// flow-typed signature: d9a983bb1ac458a256c31c139047bdbb +// flow-typed version: 927687984d/prop-types_v15.x.x/flow_>=v0.41.x + +type $npm$propTypes$ReactPropsCheckType = ( + props: any, + propName: string, + componentName: string, + href?: string) => ?Error; + +declare module 'prop-types' { + declare var array: React$PropType$Primitive>; + declare var bool: React$PropType$Primitive; + declare var func: React$PropType$Primitive; + declare var number: React$PropType$Primitive; + declare var object: React$PropType$Primitive; + declare var string: React$PropType$Primitive; + declare var symbol: React$PropType$Primitive; + declare var any: React$PropType$Primitive; + declare var arrayOf: React$PropType$ArrayOf; + declare var element: React$PropType$Primitive; /* TODO */ + declare var instanceOf: React$PropType$InstanceOf; + declare var node: React$PropType$Primitive; /* TODO */ + declare var objectOf: React$PropType$ObjectOf; + declare var oneOf: React$PropType$OneOf; + declare var oneOfType: React$PropType$OneOfType; + declare var shape: React$PropType$Shape; + + declare function checkPropTypes( + propTypes: $Subtype<{[_: $Keys]: $npm$propTypes$ReactPropsCheckType}>, + values: V, + location: string, + componentName: string, + getStack: ?(() => ?string) + ) : void; +} diff --git a/package.json b/package.json index a834bd4..aa29511 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { - "classnames": "^2.2.5", + "classnames": "^2.2.6", "firebase": "^4.11.0", "firebase-admin": "^5.9.0", "firebase-functions": "^0.8.1", @@ -41,6 +41,7 @@ "dwilt-react-redux-generator": "^1.0.7", "eslint": "^4.18.2", "eslint-plugin-react": "^7.6.1", + "flow-bin": "^0.74.0", "prettier": "^1.11.1" } } diff --git a/src/components/ActionButton/ActionButton.js b/src/components/ActionButton/ActionButton.js index 076519a..1506ba2 100644 --- a/src/components/ActionButton/ActionButton.js +++ b/src/components/ActionButton/ActionButton.js @@ -1,39 +1,39 @@ -import React, { Component } from "react"; +import React, { Component } from 'react'; -import { ActivityIndicator } from "src/components"; +import { ActivityIndicator } from 'src/components'; -import PropTypes from "prop-types"; +import PropTypes from 'prop-types'; -import classNames from "classnames"; +import classNames from 'classnames'; class ActionButton extends Component { static propTypes = { disabled: PropTypes.bool.isRequired, isLoading: PropTypes.bool.isRequired, - type: PropTypes.oneOf([`button`, `submit`]).isRequired, + type: PropTypes.oneOf(['button', 'submit']).isRequired, onClick: PropTypes.func, children: PropTypes.string.isRequired, }; static defaultProps = { - type: `button`, + type: 'button', disabled: false, isLoading: false, - children: `Link Text`, + children: 'Link Text', }; render() { const { onClick, children, isLoading, disabled, type } = this.props; const innerContent = isLoading ? ( -
+
) : ( children ); - const buttonClasses = classNames(`btn`, { + const buttonClasses = classNames('btn', { disabled, }); diff --git a/src/components/ActionButton/ActionButton.test.js b/src/components/ActionButton/ActionButton.test.js index 8a33491..4596b5b 100644 --- a/src/components/ActionButton/ActionButton.test.js +++ b/src/components/ActionButton/ActionButton.test.js @@ -1,9 +1,9 @@ -import React from "react"; -import ReactDOM from "react-dom"; -import App from "./ActionButton.js"; +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './ActionButton.js'; -it(`renders without crashing`, () => { - const div = document.createElement(`div`); +it('renders without crashing', () => { + const div = document.createElement('div'); ReactDOM.render(, div); ReactDOM.unmountComponentAtNode(div); }); diff --git a/src/components/ActionButton/index.js b/src/components/ActionButton/index.js index 1e438d6..d5d8608 100644 --- a/src/components/ActionButton/index.js +++ b/src/components/ActionButton/index.js @@ -1 +1 @@ -export { default as ActionButton } from "./ActionButton"; +export { default as ActionButton } from './ActionButton'; diff --git a/src/components/ActivityIndicator/ActivityIndicator.component.js b/src/components/ActivityIndicator/ActivityIndicator.component.js index 300fee5..5b4373d 100644 --- a/src/components/ActivityIndicator/ActivityIndicator.component.js +++ b/src/components/ActivityIndicator/ActivityIndicator.component.js @@ -1,23 +1,23 @@ -import React, { PureComponent } from "react"; +import React, { PureComponent } from 'react'; -import "./ActivityIndicator.css"; +import './ActivityIndicator.css'; export default class ActivityIndicator extends PureComponent { render() { return ( -
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
); } diff --git a/src/components/ActivityIndicator/index.js b/src/components/ActivityIndicator/index.js index 3a0ff0c..ea2da23 100644 --- a/src/components/ActivityIndicator/index.js +++ b/src/components/ActivityIndicator/index.js @@ -1 +1 @@ -export { default as ActivityIndicator } from "./ActivityIndicator.component"; +export { default as ActivityIndicator } from './ActivityIndicator.component'; diff --git a/src/components/Answer/Answer.component.js b/src/components/Answer/Answer.component.js index 3633822..0c71d47 100644 --- a/src/components/Answer/Answer.component.js +++ b/src/components/Answer/Answer.component.js @@ -1,22 +1,22 @@ -import React, { PureComponent } from "react"; +import React, { PureComponent } from 'react'; -import Highlight from "react-highlight"; +import Highlight from 'react-highlight'; -import Markdown from "react-remarkable"; +import Markdown from 'react-remarkable'; -import "highlight.js/styles/github-gist.css"; +import 'highlight.js/styles/github-gist.css'; -import PropTypes from "prop-types"; +import PropTypes from 'prop-types'; -import "./Answer.css"; +import './Answer.css'; -import classNames from "classnames"; +import classNames from 'classnames'; const letterMap = { - 1: `a`, - 2: `b`, - 3: `c`, - 4: `d`, + 1: 'a', + 2: 'b', + 3: 'c', + 4: 'd', }; export default class Answer extends PureComponent { @@ -26,15 +26,15 @@ export default class Answer extends PureComponent { selectedAnswer: PropTypes.number, text: PropTypes.string.isRequired, answerType: PropTypes.string.isRequired, - theme: PropTypes.oneOf([`none`, `green`, `red`, `blue-outline`]) + theme: PropTypes.oneOf(['none', 'green', 'red', 'blue-outline']) .isRequired, onChange: PropTypes.func, onEnterPress: PropTypes.func, }; static defaultProps = { - theme: `none`, - answerType: `markdown`, + theme: 'none', + answerType: 'markdown', }; handleOnChange = () => { @@ -46,7 +46,7 @@ export default class Answer extends PureComponent { onKeyPress = ({ key }) => { const { onEnterPress } = this.props; - if (key === `Enter`) { + if (key === 'Enter') { onEnterPress(); } }; @@ -66,34 +66,34 @@ export default class Answer extends PureComponent { const answerIsSelected = answerNumber === selectedAnswer; const textEl = - answerType === `code` ? ( - {text} + answerType === 'code' ? ( + {text} ) : ( {text} ); const radioId = `${questionId}-${answerNumber}`; - const containerClasses = classNames(`Answer`, `--theme-${theme}`); + const containerClasses = classNames('Answer', `--theme-${theme}`); const content = (
- + {letterMap[answerNumber]} {onChange && ( )} -
{textEl}
+
{textEl}
); diff --git a/src/components/Answer/index.js b/src/components/Answer/index.js index 47c0bb2..2310200 100644 --- a/src/components/Answer/index.js +++ b/src/components/Answer/index.js @@ -1 +1 @@ -export { default as Answer } from "./Answer.component"; +export { default as Answer } from './Answer.component'; diff --git a/src/components/App/App.component.js b/src/components/App/App.component.js index 503ec42..e7f7f24 100644 --- a/src/components/App/App.component.js +++ b/src/components/App/App.component.js @@ -1,9 +1,9 @@ -import React, { Component } from "react"; -import "./App.css"; +import React, { Component } from 'react'; +import './App.css'; -import PropTypes from "prop-types"; +import PropTypes from 'prop-types'; -import { Quiz, Completed } from "src/components"; +import { Quiz, Completed } from 'src/components'; class App extends Component { static propTypes = { @@ -16,11 +16,11 @@ class App extends Component { let content =
; switch (state) { - case `completed`: + case 'completed': content = ; break; - case `quiz`: + case 'quiz': content = ; break; @@ -28,7 +28,7 @@ class App extends Component { content =
; } - return
{content}
; + return
{content}
; } } diff --git a/src/components/App/App.container.js b/src/components/App/App.container.js index 72cf7ac..2130b8a 100644 --- a/src/components/App/App.container.js +++ b/src/components/App/App.container.js @@ -1,8 +1,8 @@ -import { connect } from "react-redux"; +import { connect } from 'react-redux'; -import { stateSelector } from "src/selectors"; +import { stateSelector } from 'src/selectors'; -import App from "./App.component"; +import App from './App.component'; export default connect((st) => ({ state: stateSelector(st), diff --git a/src/components/App/App.test.js b/src/components/App/App.test.js index 5970097..4b64f4d 100644 --- a/src/components/App/App.test.js +++ b/src/components/App/App.test.js @@ -1,9 +1,9 @@ -import React from "react"; -import ReactDOM from "react-dom"; -import App from "./App.component"; +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App.component'; -it(`renders without crashing`, () => { - const div = document.createElement(`div`); +it('renders without crashing', () => { + const div = document.createElement('div'); ReactDOM.render(, div); ReactDOM.unmountComponentAtNode(div); }); diff --git a/src/components/App/index.js b/src/components/App/index.js index 69306ec..5a45ad9 100644 --- a/src/components/App/index.js +++ b/src/components/App/index.js @@ -1 +1 @@ -export { default as App } from "./App.container"; +export { default as App } from './App.container'; diff --git a/src/components/Checkbox/Checkbox.component.js b/src/components/Checkbox/Checkbox.component.js index a1f6296..75623e5 100644 --- a/src/components/Checkbox/Checkbox.component.js +++ b/src/components/Checkbox/Checkbox.component.js @@ -1,4 +1,7 @@ -import React, { PureComponent } from 'react'; +// @flow +import * as React from 'react'; + +import classnames from 'classnames'; import PropTypes from 'prop-types'; @@ -6,7 +9,21 @@ import './Checkbox.css'; const greenCheckmark = require('./check.svg'); -export default class Checkbox extends PureComponent { +type CheckboxProps = { + onChange: Function, + label: string, + id: string, + checked: boolean, +}; + +type CheckboxState = { + focused: boolean, +}; + +export default class Checkbox extends React.PureComponent< + CheckboxProps, + CheckboxState + > { static propTypes = { onChange: PropTypes.func.isRequired, label: PropTypes.string.isRequired, @@ -18,22 +35,47 @@ export default class Checkbox extends PureComponent { checked: false, }; - handleOnChange = ({ target: { checked } }) => { + state = { + focused: false, + }; + + handleOnChange = ({ + target: { checked }, + }: SyntheticInputEvent) => { const { onChange } = this.props; onChange(checked); }; + onFocus = () => { + this.setState({ + focused: true, + }); + }; + + onBlur = () => { + this.setState({ + focused: false, + }); + }; + render() { const { id, checked, label } = this.props; + const { focused } = this.state; + + const inputContainerStyles = classnames('Checkbox__input-container', { + focused, + }); return (