Code coverage report for components/estimator.js

Statements: 86.21% (25 / 29)      Branches: 78.57% (11 / 14)      Functions: 85.71% (6 / 7)      Lines: 86.21% (25 / 29)      Ignored: none     

All files » components/ » estimator.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 1231 1 1 1                 1                                           1             33                           3       3   3           2       2   2 1     1 1           42 42 42   42 4 20                 4                       42                     1
var React = window.React || require('react/addons');
var _ = require('lodash');
var ClickOff = require('react-onclickoutside');
var Styles = require('../styles/estimator');
 
/*
 * Estimator element displays item score that, when clicked, opens a menu
 * for editing the current score. Expects an estimate changer utility object
 * containing a changeScore method for handling score changing on the model
 * and syncing any changes with the backend.
 */
 
var Estimator = React.createClass({
  ALL_ESTIMATES: [0, 1, 3, 5, 8],
 
  ESTIMATE_HASH: {
    0: '?',
    1: 'S',
    3: 'M',
    5: 'L',
    8: 'XL'
  },
 
  propTypes: {
    modelId: React.PropTypes.arrayOf(React.PropTypes.number),
    readOnly: React.PropTypes.bool,
    itemType: React.PropTypes.string.isRequired,
    score: React.PropTypes.string.isRequired,
    estimateChanger: React.PropTypes.object.isRequired
  },
 
  mixins: [ClickOff, Styles],
 
  getDefaultProps: function() {
    return {
      modelId: null,
      readOnly: false
    };
  },
 
  getInitialState: function() {
    return {
      menuOpen: false
    };
  },
 
  handleClickOutside: function(ev) {
    ev.stopPropagation();
 
    this.setState({
      menuOpen: false
    });
  },
 
  onScoreClick: function() {
    Iif (this.props.readOnly) {
      return;
    }
 
    var openOrClose = this.state.menuOpen === false ? true : false;
 
    this.setState({
      menuOpen: openOrClose
    });
  },
 
  onScoreChange: function(ev) {
    Iif (this.props.readOnly) {
      return;
    }
 
    var newScore = parseInt(ev.target.getAttribute('data-score'), 10);
 
    if (this.props.score === this.ESTIMATE_HASH[newScore].toLowerCase()) {
      return;
    }
 
    this.props.estimateChanger.changeScore(this.props.modelId, newScore);
    this.setState({
      menuOpen: false
    });
  },
 
  render: function() {
    var currentScore = this.props.score === '~' ? '?' : this.props.score;
    var scoreStyle = Styles.score[this.props.itemType];
    var scoreMenu = null;
 
    if (this.state.menuOpen) {
      var scores = _.map(this.ALL_ESTIMATES, function(score) {
        return (
          <li key={score} style={Styles.score.wrapper}>
            <button style={scoreStyle} data-score={score} onClick={this.onScoreChange}>
              {this.ESTIMATE_HASH[score]}
            </button>
          </li>
        );
      }, this);
 
      scoreMenu = (
        <div>
          <div className="left-arrow" style={Styles.leftArrow} />
          <div className="estimator-menu" style={Styles.menu}>
            <ul style={Styles.list}>
              {scores}
            </ul>
          </div>
        </div>
      );
    }
 
    return (
      <div className="estimator-component">
        <button style={scoreStyle} onClick={this.onScoreClick}>
          {currentScore}
        </button>
        {scoreMenu}
      </div>
    );
  }
});
 
module.exports = Estimator;