diff --git a/.travis.yml b/.travis.yml index 762841e..d21c482 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - 4.4.0 + - lts/* - stable install: - npm install 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/services/pitch_statistic_service.js b/app/scripts/services/pitch_statistic_service.js index f9ac113..24dc694 100644 --- a/app/scripts/services/pitch_statistic_service.js +++ b/app/scripts/services/pitch_statistic_service.js @@ -28,7 +28,9 @@ class PitchStatisticService { this.stats = localStorage.getItem(localStoragePitchStatsKey); if (this.stats) { - this.stats = JSON.parse(this.stats).map(this.transformDate).map(StatEvolver.evolveToLatestSchema); + this.stats = JSON.parse(this.stats) + .map(this.transformDate) + .map(StatEvolver.evolveToLatestSchema); } else { this.stats = []; } @@ -45,7 +47,9 @@ class PitchStatisticService { } getSuccessCount() { - return _(this.stats).filter(el => el.success).value().length; + return _(this.stats) + .filter(el => el.success) + .value().length; } rateEvent(event) { @@ -67,7 +71,10 @@ class PitchStatisticService { } getLastTimes(n = 10) { - return this.stats.filter(el => el.success).map(el => el.time).slice(-n); + return this.stats + .filter(el => el.success) + .map(el => el.time) + .slice(-n); } computeAverage(array) { @@ -83,11 +90,18 @@ class PitchStatisticService { } getTotalAmountOfChords() { - return _(this.stats).filter(el => el.success).map(el => el.keys).size(); + return _(this.stats) + .filter(el => el.success) + .map(el => el.keys) + .size(); } getTotalAmountOfKeys() { - return _(this.stats).filter(el => el.success).map(el => el.keys).flatten().size(); + return _(this.stats) + .filter(el => el.success) + .map(el => el.keys) + .flatten() + .size(); } getSuccessRate() { diff --git a/app/scripts/services/rhythm_statistic_service.js b/app/scripts/services/rhythm_statistic_service.js index bdf829b..f798f63 100644 --- a/app/scripts/services/rhythm_statistic_service.js +++ b/app/scripts/services/rhythm_statistic_service.js @@ -64,7 +64,9 @@ class RhythmStatisticService { } getSuccessCount() { - return _(this.stats).filter(el => el.success).value().length; + return _(this.stats) + .filter(el => el.success) + .value().length; } getLastScores(n) { @@ -72,7 +74,10 @@ class RhythmStatisticService { } getLastTimes(n = 10) { - return this.stats.filter(el => el.success).map(el => el.time).slice(-n); + return this.stats + .filter(el => el.success) + .map(el => el.time) + .slice(-n); } computeAverage(array) { @@ -88,7 +93,10 @@ class RhythmStatisticService { } getTotalAmountOfBeats() { - return _(this.stats).map(el => el.durations).flatten().size(); + return _(this.stats) + .map(el => el.durations) + .flatten() + .size(); } getTotalRhythmTime() { diff --git a/app/scripts/views/animated_number.js b/app/scripts/views/animated_number.js index 294ebc8..6c7cf22 100644 --- a/app/scripts/views/animated_number.js +++ b/app/scripts/views/animated_number.js @@ -1,20 +1,18 @@ 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; const number = this.props.number; return ( - {value => - - {formatter ? formatter(value.x) : Math.round(value.x)} - } + {value => {formatter ? formatter(value.x) : Math.round(value.x)}} ); } diff --git a/app/scripts/views/beat_visualization.js b/app/scripts/views/beat_visualization.js index ce31ea2..252181b 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.array.isRequired, + result: PropTypes.object }; convertTicksToBeatNames(tickTime, tickLength) { @@ -26,11 +27,11 @@ export default class BeatVisualization extends Component { const ticks = necessaryBeatNames.slice(tickIndex, tickIndex + tickStepCount); return (
- {ticks.map((beatName, index) => + {ticks.map((beatName, index) => (
{beatName}
- )} + ))}
); } @@ -52,11 +53,11 @@ export default class BeatVisualization extends Component { currentX = x + width; return [ - marginLeft > 0 - ?
- {beatNamesRest} -
- : null, + marginLeft > 0 ? ( +
+ {beatNamesRest} +
+ ) : null,
{beatNames}
@@ -98,12 +99,8 @@ export default class BeatVisualization extends Component { // uniqueId avoids that different beat bars are animated into each other return (
-
- {expectedBeats} -
-
- {actualBeats} -
+
{expectedBeats}
+
{actualBeats}
); } diff --git a/app/scripts/views/claviature_view.js b/app/scripts/views/claviature_view.js index f101a46..db928c6 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) { @@ -110,9 +111,7 @@ export default class ClaviatureView extends Component { ].map(args => this.renderKey.apply(this, args)); return (
-
    - {keys} -
+
    {keys}
); } diff --git a/app/scripts/views/collapsable_container.js b/app/scripts/views/collapsable_container.js index 5b022e1..fc1e6ba 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 { +export default class CollapsableContainer 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..6bd5b67 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() { @@ -38,22 +39,16 @@ export default class GameButton extends Component { } render() { - const subtext = this.props.shortcutLetter - ?
- - Or press '{this.props.shortcutLetter}' - -
- : null; + const subtext = this.props.shortcutLetter ? ( +
+ Or press ‘{this.props.shortcutLetter}’ +
+ ) : null; return ( ); } diff --git a/app/scripts/views/level_view.js b/app/scripts/views/level_view.js index b13eed3..81d4773 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() { @@ -64,9 +65,7 @@ export default class LevelView extends Component { return (
{content} -
- Current level: {levelIndex + 2} -
+
Current level: {levelIndex + 2}
); } diff --git a/app/scripts/views/metronome_view.js b/app/scripts/views/metronome_view.js index 3adbf8b..cd242d0 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,8 @@ 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 }; constructor(props, context) { @@ -65,9 +65,7 @@ export default class MetronomeView extends Component { opacityOut: (this.state.currentMetronomeBeat + 1) % 4 === 0 })} > -

- {this.state.currentMetronomeBeat + 1} -

+

{this.state.currentMetronomeBeat + 1}

); } diff --git a/app/scripts/views/newsletter_form.js b/app/scripts/views/newsletter_form.js index b741216..002178d 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,10 +32,10 @@ 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 5f24d3e..5650e82 100644 --- a/app/scripts/views/pie_chart.js +++ b/app/scripts/views/pie_chart.js @@ -1,24 +1,30 @@ import Chartist from "Chartist"; -import React, { Component } from "react"; -import PureRenderMixin from "react-addons-pure-render-mixin"; +import PropTypes from "prop-types"; +import React, { PureComponent } from "react"; -export default class LevelView extends Component { +export default class PieChart extends PureComponent { static propTypes = { - pieParts: React.PropTypes.array.isRequired + pieParts: PropTypes.array.isRequired }; constructor(props, context) { super(props, context); - this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this); } 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..0cee583 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() { @@ -140,15 +141,15 @@ export default class PitchReadingView extends Component { const isMidiAvailable = this.props.settings.midi.inputs.get().length > 0; const noErrors = this.state.errorMessage !== null; const miniClaviature = - isMidiAvailable && noErrors - ? null - : ; + isMidiAvailable && noErrors ? null : ( + + ); const startStopButton = ( -

- {this.state.errorMessage} -

+

{this.state.errorMessage}

@@ -237,7 +236,15 @@ export default class PitchReadingView extends Component { -