diff --git a/app/scripts/App.js b/app/scripts/App.js index a3fdd68..0cf2415 100644 --- a/app/scripts/App.js +++ b/app/scripts/App.js @@ -105,13 +105,28 @@ export default class App extends Component {
- + - + - +
diff --git a/app/scripts/views/animated_number.js b/app/scripts/views/animated_number.js index 294ebc8..03269b6 100644 --- a/app/scripts/views/animated_number.js +++ b/app/scripts/views/animated_number.js @@ -1,10 +1,11 @@ import React, { Component } from "react"; +import PropTypes from "prop-types"; import { Motion, spring } from "react-motion"; export default class AnimatedNumber extends Component { static propTypes = { - formatter: React.PropTypes.func, - number: React.PropTypes.number + formatter: PropTypes.func, + number: PropTypes.number }; render() { const formatter = this.props.formatter; diff --git a/app/scripts/views/beat_visualization.js b/app/scripts/views/beat_visualization.js index ce31ea2..bcb39c1 100644 --- a/app/scripts/views/beat_visualization.js +++ b/app/scripts/views/beat_visualization.js @@ -1,4 +1,5 @@ import React, { Component } from "react"; +import PropTypes from "prop-types"; import classNames from "classnames"; import _ from "lodash"; @@ -6,11 +7,11 @@ import RhythmChecker from "../services/rhythm_checker.js"; export default class BeatVisualization extends Component { static propTypes = { - settings: React.PropTypes.object.isRequired, - barDuration: React.PropTypes.number.isRequired, - currentRhythm: React.PropTypes.object.isRequired, - beatHistory: React.PropTypes.object.isRequired, - result: React.PropTypes.object.isRequired + settings: PropTypes.object.isRequired, + barDuration: PropTypes.number.isRequired, + currentRhythm: PropTypes.object.isRequired, + beatHistory: PropTypes.object.isRequired, + result: PropTypes.object.isRequired }; convertTicksToBeatNames(tickTime, tickLength) { diff --git a/app/scripts/views/claviature_view.js b/app/scripts/views/claviature_view.js index f101a46..16eb8c7 100644 --- a/app/scripts/views/claviature_view.js +++ b/app/scripts/views/claviature_view.js @@ -1,14 +1,15 @@ import React, { Component } from "react"; +import PropTypes from "prop-types"; import KeyConverter from "../services/key_converter.js"; import classNames from "classnames"; export default class ClaviatureView extends Component { static propTypes = { - desiredKeys: React.PropTypes.array, - keySignature: React.PropTypes.string, - successCallback: React.PropTypes.func, - failureCallback: React.PropTypes.func, - disabled: React.PropTypes.bool + desiredKeys: PropTypes.array, + keySignature: PropTypes.string, + successCallback: PropTypes.func, + failureCallback: PropTypes.func, + disabled: PropTypes.bool }; constructor(props, context) { @@ -20,7 +21,7 @@ export default class ClaviatureView extends Component { } static contextTypes = { - isInActiveView: React.PropTypes.bool + isInActiveView: PropTypes.bool }; isNoteCorrect(noteName) { diff --git a/app/scripts/views/collapsable_container.js b/app/scripts/views/collapsable_container.js index 5b022e1..ac4d9da 100644 --- a/app/scripts/views/collapsable_container.js +++ b/app/scripts/views/collapsable_container.js @@ -1,14 +1,15 @@ import React, { Component } from "react"; +import PropTypes from "prop-types"; import classNames from "classnames"; import _ from "lodash"; export default class BeatVisualization extends Component { static propTypes = { - children: React.PropTypes.node, - collapsed: React.PropTypes.bool.isRequired, - maxHeight: React.PropTypes.number, - freeze: React.PropTypes.bool, - className: React.PropTypes.string + children: PropTypes.node, + collapsed: PropTypes.bool.isRequired, + maxHeight: PropTypes.number, + freeze: PropTypes.bool, + className: PropTypes.string }; componentWillReceiveProps(nextProps) { diff --git a/app/scripts/views/game_button.js b/app/scripts/views/game_button.js index b41bb44..bf69246 100644 --- a/app/scripts/views/game_button.js +++ b/app/scripts/views/game_button.js @@ -1,16 +1,17 @@ import React, { Component } from "react"; +import PropTypes from "prop-types"; import { Button } from "react-bootstrap"; export default class GameButton extends Component { static propTypes = { - label: React.PropTypes.string.isRequired, - onClick: React.PropTypes.func.isRequired, - primary: React.PropTypes.bool, - shortcutLetter: React.PropTypes.string + label: PropTypes.string.isRequired, + onClick: PropTypes.func.isRequired, + primary: PropTypes.bool, + shortcutLetter: PropTypes.string }; static contextTypes = { - isInActiveView: React.PropTypes.bool + isInActiveView: PropTypes.bool }; componentDidMount() { @@ -41,7 +42,7 @@ export default class GameButton extends Component { const subtext = this.props.shortcutLetter ?
- Or press '{this.props.shortcutLetter}' + Or press ‘{this.props.shortcutLetter}’
: null; diff --git a/app/scripts/views/level_view.js b/app/scripts/views/level_view.js index b13eed3..7dd7555 100644 --- a/app/scripts/views/level_view.js +++ b/app/scripts/views/level_view.js @@ -1,11 +1,12 @@ import _ from "lodash"; import React, { Component } from "react"; +import PropTypes from "prop-types"; import LevelService from "../services/level_service.js"; import PieChart from "../views/pie_chart.js"; export default class LevelView extends Component { static propTypes = { - statisticService: React.PropTypes.object.isRequired + statisticService: PropTypes.object.isRequired }; render() { diff --git a/app/scripts/views/metronome_view.js b/app/scripts/views/metronome_view.js index 3adbf8b..4a06ab6 100644 --- a/app/scripts/views/metronome_view.js +++ b/app/scripts/views/metronome_view.js @@ -1,4 +1,5 @@ import React, { Component } from "react"; +import PropTypes from "prop-types"; import classNames from "classnames"; import _ from "lodash"; @@ -7,9 +8,9 @@ import CollapsableContainer from "./collapsable_container.js"; export default class MetronomeView extends Component { static propTypes = { - onMetronomeEnded: React.PropTypes.func, - settings: React.PropTypes.object.isRequired, - statisticService: React.PropTypes.object.isRequired + onMetronomeEnded: PropTypes.func, + settings: PropTypes.object.isRequired, + statisticService: PropTypes.object.isRequired }; constructor(props, context) { diff --git a/app/scripts/views/newsletter_form.js b/app/scripts/views/newsletter_form.js index b741216..cb976a2 100644 --- a/app/scripts/views/newsletter_form.js +++ b/app/scripts/views/newsletter_form.js @@ -5,7 +5,7 @@ export default class NewsLetterForm extends Component { // This avoids that global keyhandlers for keyboard navigation are triggered // when email input is used. const dontPropagate = evt => evt.stopPropagation(); - const email = this.refs.email; + const email = this.email; email.addEventListener("keypress", dontPropagate); email.addEventListener("keyup", dontPropagate); email.addEventListener("keydown", dontPropagate); @@ -32,7 +32,9 @@ export default class NewsLetterForm extends Component { name="EMAIL" id="mce-EMAIL" placeholder="your@email.com" - ref="email" + ref={c => { + this.email = c; + }} className="form-control" groupClassName="group-class" labelClassName="label-class" diff --git a/app/scripts/views/pie_chart.js b/app/scripts/views/pie_chart.js index fa06d0f..8c67f23 100644 --- a/app/scripts/views/pie_chart.js +++ b/app/scripts/views/pie_chart.js @@ -1,9 +1,10 @@ import Chartist from "Chartist"; +import PropTypes from "prop-types"; import React, { PureComponent } from "react"; export default class LevelView extends PureComponent { static propTypes = { - pieParts: React.PropTypes.array.isRequired + pieParts: PropTypes.array.isRequired }; constructor(props, context) { @@ -11,12 +12,19 @@ export default class LevelView extends PureComponent { } render() { - return
; + return ( +
{ + this.chart = c; + }} + className="semi-transparent ct-chart ct-major-eleventh" + /> + ); } componentDidUpdate() { new Chartist.Pie( - this.refs.chart, + this.chart, { series: this.props.pieParts }, diff --git a/app/scripts/views/pitch_reading_view.js b/app/scripts/views/pitch_reading_view.js index e5f145e..29f9e75 100644 --- a/app/scripts/views/pitch_reading_view.js +++ b/app/scripts/views/pitch_reading_view.js @@ -1,4 +1,5 @@ import React, { Component } from "react"; +import PropTypes from "prop-types"; import classNames from "classnames"; import _ from "lodash"; @@ -17,13 +18,13 @@ const successMp3Url = require("file!../../resources/success.mp3"); export default class PitchReadingView extends Component { static propTypes = { - statisticService: React.PropTypes.object.isRequired, - settings: React.PropTypes.object.isRequired, - isActive: React.PropTypes.bool.isRequired + statisticService: PropTypes.object.isRequired, + settings: PropTypes.object.isRequired, + isActive: PropTypes.bool.isRequired }; static childContextTypes = { - isInActiveView: React.PropTypes.bool + isInActiveView: PropTypes.bool }; getChildContext() { @@ -237,7 +238,16 @@ export default class PitchReadingView extends Component {
-
); @@ -297,7 +307,7 @@ export default class PitchReadingView extends Component { } playSuccessSound() { - this.refs.successPlayer.play(); + this.successPlayer.play(); } onFailure() { diff --git a/app/scripts/views/pitch_settings_view.js b/app/scripts/views/pitch_settings_view.js index 3043eb7..f8e809b 100644 --- a/app/scripts/views/pitch_settings_view.js +++ b/app/scripts/views/pitch_settings_view.js @@ -1,4 +1,5 @@ import React, { Component } from "react"; +import PropTypes from "prop-types"; import RangeSettingComponent from "./range_setting_component"; import SettingLine from "./setting_line"; import KeyConverter from "../services/key_converter"; @@ -8,7 +9,7 @@ import AnalyticsService from "../services/analytics_service.js"; export default class PitchSettingsView extends Component { static propTypes = { - settings: React.PropTypes.object + settings: PropTypes.object }; constructor(props, context) { @@ -42,7 +43,7 @@ export default class PitchSettingsView extends Component { } onMidiSelectChange() { - AppFreezer.trigger("input:changed", parseInt(this.refs.midiSelect.value, 10)); + AppFreezer.trigger("input:changed", parseInt(this.midiSelect.value, 10)); } render() { @@ -56,7 +57,9 @@ export default class PitchSettingsView extends Component { name="select" onChange={this.onMidiSelectChange.bind(this)} defaultValue={midiSettings.currentInput} - ref="midiSelect" + ref={c => { + this.midiSelect = c; + }} > {midiInputs.map((el, index) => { return ( diff --git a/app/scripts/views/pitch_statistic_view.js b/app/scripts/views/pitch_statistic_view.js index 3d9618e..e120342 100644 --- a/app/scripts/views/pitch_statistic_view.js +++ b/app/scripts/views/pitch_statistic_view.js @@ -1,5 +1,6 @@ import Chartist from "Chartist"; import React, { Component } from "react"; +import PropTypes from "prop-types"; import { Tooltip, OverlayTrigger } from "react-bootstrap"; import LevelView from "./level_view.js"; import CollapsableContainer from "./collapsable_container.js"; @@ -9,8 +10,8 @@ import StarAnimation from "./star_animation.js"; export default class PitchStatisticView extends Component { static propTypes = { - statisticService: React.PropTypes.object.isRequired, - settings: React.PropTypes.object.isRequired + statisticService: PropTypes.object.isRequired, + settings: PropTypes.object.isRequired }; render() { @@ -21,7 +22,12 @@ export default class PitchStatisticView extends Component { return (
-
+
{ + this.chart = c; + }} + className="semi-transparent ct-chart ct-major-eleventh" + />
@@ -90,8 +96,8 @@ export default class PitchStatisticView extends Component { } }; - if (statistics.getSuccessCount() > 1) { - Chartist.Line(this.refs.chart, data, options); + if (this.chart && statistics.getSuccessCount() > 1) { + Chartist.Line(this.chart, data, options); } } } diff --git a/app/scripts/views/privacy_policy_modal.js b/app/scripts/views/privacy_policy_modal.js index 6bb551e..586589d 100644 --- a/app/scripts/views/privacy_policy_modal.js +++ b/app/scripts/views/privacy_policy_modal.js @@ -1,9 +1,10 @@ import React, { Component } from "react"; +import PropTypes from "prop-types"; import { Modal, Button } from "react-bootstrap"; export default class PrivacyPolicyModal extends Component { static propTypes = { - onHide: React.PropTypes.func.isRequired + onHide: PropTypes.func.isRequired }; render() { diff --git a/app/scripts/views/range_setting_component.js b/app/scripts/views/range_setting_component.js index 48794d7..627ce22 100644 --- a/app/scripts/views/range_setting_component.js +++ b/app/scripts/views/range_setting_component.js @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from "react"; +import React, { Component } from "react"; +import PropTypes from "prop-types"; import RangeSlider from "react-range-slider-bem"; import SettingLine from "./setting_line"; import _ from "lodash"; @@ -23,18 +24,20 @@ export default class SettingsView extends Component { constructor(props, context) { super(props, context); - this.receiveValueAsProps(this.props); + this.state = { + values: this.valuesFromProps(this.props) + }; } - receiveValueAsProps(props) { + valuesFromProps(props) { let values = _.isArray(props.values) ? props.values : [props.values]; - this.state = { - values: values.map(el => el * multiplier) - }; + return values.map(el => el * multiplier); } componentWillReceiveProps(newProps) { - this.receiveValueAsProps(newProps); + this.setState = { + values: this.valuesFromProps(newProps) + }; } onChange(event, index, values) { diff --git a/app/scripts/views/rhythm_reading_view.js b/app/scripts/views/rhythm_reading_view.js index 536ba5b..1bf9b0b 100644 --- a/app/scripts/views/rhythm_reading_view.js +++ b/app/scripts/views/rhythm_reading_view.js @@ -1,4 +1,5 @@ import React, { Component } from "react"; +import PropTypes from "prop-types"; import classNames from "classnames"; import BarGenerator from "../services/bar_generator.js"; @@ -24,9 +25,9 @@ const Phases = { export default class RhythmReadingView extends Component { static propTypes = { - settings: React.PropTypes.object.isRequired, - statisticService: React.PropTypes.object.isRequired, - isActive: React.PropTypes.bool.isRequired + settings: PropTypes.object.isRequired, + statisticService: PropTypes.object.isRequired, + isActive: PropTypes.bool.isRequired }; constructor(props, context) { @@ -42,7 +43,7 @@ export default class RhythmReadingView extends Component { } static childContextTypes = { - isInActiveView: React.PropTypes.bool + isInActiveView: PropTypes.bool }; getChildContext() { @@ -53,7 +54,7 @@ export default class RhythmReadingView extends Component { componentDidUpdate(prevProps, prevState) { if (this.state.phase === Phases.running && prevState.phase !== Phases.running) { - this.refs.metronome.playMetronome(); + this.metronome.playMetronome(); } else { console.log("not running"); } @@ -98,7 +99,7 @@ export default class RhythmReadingView extends Component { // we will add the up event to the beatHistory const lastBeat = this.beatHistory.slice(-1)[0]; if (lastBeat.length === 1) { - const firstBarBeatTime = this.refs.metronome.getFirstBarBeatTime(); + const firstBarBeatTime = this.metronome.getFirstBarBeatTime(); lastBeat.push(performance.now() - firstBarBeatTime); } } @@ -124,7 +125,7 @@ export default class RhythmReadingView extends Component { return; } // protocol beat - const firstBarBeatTime = this.refs.metronome.getFirstBarBeatTime(); + const firstBarBeatTime = this.metronome.getFirstBarBeatTime(); const newBeatTime = performance.now() - firstBarBeatTime; lastSpaceEvent = eventType; @@ -207,8 +208,8 @@ export default class RhythmReadingView extends Component {

Welcome to this rhythm training!

When you start the training, we will count in for 4 beats and afterwards you can tap the given rhythm (either - use your 'space' button or your touchscreen). Make sure your speakers are on so that you can hear the - metronome. + use your ‘space’ button or your touchscreen). Make sure your speakers are on so that you can hear + the metronome.

); @@ -253,7 +254,9 @@ export default class RhythmReadingView extends Component { const metronomeBeat = ( { + this.metronome = c; + }} onMetronomeEnded={this.onMetronomeEnded.bind(this)} /> ); diff --git a/app/scripts/views/rhythm_settings_view.js b/app/scripts/views/rhythm_settings_view.js index 6b8ee28..ed2f163 100644 --- a/app/scripts/views/rhythm_settings_view.js +++ b/app/scripts/views/rhythm_settings_view.js @@ -1,4 +1,5 @@ import React, { Component } from "react"; +import PropTypes from "prop-types"; import RangeSettingComponent from "./range_setting_component"; import SettingLine from "./setting_line"; import AnalyticsService from "../services/analytics_service.js"; @@ -6,7 +7,7 @@ import _ from "lodash"; export default class PitchSettingsView extends Component { static propTypes = { - settings: React.PropTypes.object + settings: PropTypes.object }; constructor(props, context) { diff --git a/app/scripts/views/rhythm_statistic_view.js b/app/scripts/views/rhythm_statistic_view.js index d7c6d04..23ce513 100644 --- a/app/scripts/views/rhythm_statistic_view.js +++ b/app/scripts/views/rhythm_statistic_view.js @@ -1,5 +1,6 @@ import Chartist from "Chartist"; import React, { Component } from "react"; +import PropTypes from "prop-types"; import { Tooltip, OverlayTrigger } from "react-bootstrap"; import _ from "lodash"; @@ -8,7 +9,7 @@ import StarAnimation from "./star_animation.js"; export default class RhythmStatisticView extends Component { static propTypes = { - statisticService: React.PropTypes.object.isRequired + statisticService: PropTypes.object.isRequired }; constructor(props) { @@ -66,7 +67,12 @@ export default class RhythmStatisticView extends Component { return (
-
+
{ + this.chart = c; + }} + className="semi-transparent ct-chart ct-major-eleventh" + />
Your current score}> @@ -142,8 +148,8 @@ export default class RhythmStatisticView extends Component { } }; - if (scoreDevelopmentValues.length > 1) { - Chartist.Line(this.refs.chart, data, options); + if (this.chart && scoreDevelopmentValues.length > 1) { + Chartist.Line(this.chart, data, options); } } } diff --git a/app/scripts/views/setting_line.js b/app/scripts/views/setting_line.js index 16fc93c..f6545e6 100644 --- a/app/scripts/views/setting_line.js +++ b/app/scripts/views/setting_line.js @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from "react"; +import React, { Component } from "react"; +import PropTypes from "prop-types"; export default class SettingLine extends Component { static defaultProps = { diff --git a/app/scripts/views/star_animation.js b/app/scripts/views/star_animation.js index 2f678f4..8b49f5a 100644 --- a/app/scripts/views/star_animation.js +++ b/app/scripts/views/star_animation.js @@ -1,8 +1,9 @@ import React, { Component } from "react"; +import PropTypes from "prop-types"; export default class StarAnimation extends Component { static propTypes = { - number: React.PropTypes.number + number: PropTypes.number }; constructor() { diff --git a/app/scripts/views/stave_renderer.js b/app/scripts/views/stave_renderer.js index 187f3ff..0d81318 100644 --- a/app/scripts/views/stave_renderer.js +++ b/app/scripts/views/stave_renderer.js @@ -1,5 +1,6 @@ import Vex from "vexflow"; import React, { PureComponent } from "react"; +import PropTypes from "prop-types"; import _ from "lodash"; class StaveRenderer extends PureComponent { @@ -8,10 +9,10 @@ class StaveRenderer extends PureComponent { }; static propTypes = { - keys: React.PropTypes.objectOf(React.PropTypes.array), - chordIndex: React.PropTypes.number, - keySignature: React.PropTypes.string, - staveCount: React.PropTypes.number + keys: PropTypes.objectOf(PropTypes.array), + chordIndex: PropTypes.number, + keySignature: PropTypes.string, + staveCount: PropTypes.number }; constructor(props) { @@ -19,7 +20,14 @@ class StaveRenderer extends PureComponent { } render() { - return ; + return ( + { + this.canvas = c; + }} + id="canvas" + /> + ); } componentDidUpdate() { @@ -58,7 +66,7 @@ class StaveRenderer extends PureComponent { } draw() { - const canvas = this.refs.canvas; + const canvas = this.canvas; this.renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS); this.ctx = this.renderer.getContext(); diff --git a/package.json b/package.json index 5115b8b..bd2ca33 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,11 @@ "freezer-js": "git+https://github.com/philippotto/freezer.git#native-object-handling-build", "html-loader": "^0.4.3", "lodash": "^4.5.1", + "prop-types": "^15.5.10", "react": "^15.6.1", "react-bootstrap": "^0.28.3", "react-dom": "^15.6.1", - "react-motion": "^0.4.2", + "react-motion": "^0.5.0", "react-range-slider-bem": "^0.2.11", "vexflow": "^1.2.41" }, @@ -40,7 +41,7 @@ "css-loader": "^0.23.1", "eslint": "^3.14.1", "eslint-plugin-prettier": "^2.1.2", - "eslint-plugin-react": "^4.1.0", + "eslint-plugin-react": "^7.1.0", "font-awesome-webpack": "0.0.4", "jasmine-core": "^2.4.1", "karma": "^0.13.21",