levent/agileista

View on GitHub
app/assets/javascripts/agileista_graphs.js

Summary

Maintainability
F
5 days
Test Coverage
var AgileistaGraphs = (function(){
  "use strict";

  var self = this ,

    drawBurndown = function(startDate, endDate, spRemaining, spComplete, spHours) {
      $('#chart').html('');
      var margin = {top: 20, right: 50, bottom: 30, left: 50},
          width = 900 - margin.left - margin.right,
          height = 350 - margin.top - margin.bottom,
          padding = 10,
          numTickDays = 1;

      var iso = d3.time.format("%Y-%m-%d");
      var parseDate = iso.parse;
      var parsedStartDate = parseDate(startDate);
      var parsedEndDate = parseDate(endDate);

      if (((parsedEndDate - parsedStartDate) / (24*60*60*1000)) > 20 ) {
        numTickDays = 2;
      }

      var x = d3.time.scale()
                .range([padding, width - padding]);

      var y = d3.scale.linear()
                .range([height - padding, 0]);

      var y2 = d3.scale.linear()
                .range([height - padding, 0]);

      var xAxis = d3.svg.axis()
                    .scale(x)
                    .ticks(d3.time.days, numTickDays)
                    .tickFormat(d3.time.format('%a %e'))
                    .orient("bottom");

      var yAxis = d3.svg.axis()
                    .scale(y)
                    .orient("left");

      var y2Axis = d3.svg.axis()
                    .scale(y2)
                    .ticks(5)
                    .orient("right");

      var xExtent = [parsedStartDate, parsedEndDate];

      spComplete.forEach(function(d) {
        d.date = parseDate(d.date);
        d.story_points = +d.story_points;
      });

      spRemaining.forEach(function(d) {
        d.date = parseDate(d.date);
        d.story_points = +d.story_points;
      });

      spHours.forEach(function(d) {
        d.date = parseDate(d.date);
        d.hours_left = +d.hours_left;
      });

      var line = d3.svg.line()
                  .x(function(d) { return x(d.date); })
                  .y(function(d) { return y(d.story_points); });
      var line2 = d3.svg.line()
                  .x(function(d) { return x(d.date); })
                  .y(function(d) { return y2(d.hours_left); });

      var mySVG = d3.select("#chart")
                    .append("svg")
                      .attr("width", "100%")
                      .attr("height", height)
                      .attr("viewBox", "0 0 900 350")
                      .attr("preserveAspectRatio", "xMinYMax meet")
                    .append("g")
                      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

      var allData = spRemaining.concat(spComplete);
      x.domain(d3.extent(xExtent, function(d) { return d; }));
      y.domain([0].concat(d3.max(allData, function(d) { return d.story_points; })));
      y2.domain([0].concat(d3.max(spHours, function(d) { return d.hours_left; })));

      mySVG.append("g")
          .attr("class", "x axis")
          .attr("transform", "translate(0," + height + ")")
          .call(xAxis);

      mySVG.append("g")
          .attr("class", "y axis")
          .call(yAxis)
        .append("text")
          .attr("transform", "rotate(-90)")
          .attr("class", "velocity-text")
          .attr("y", 6)
          .attr("dy", ".61em")
          .style("text-anchor", "end")
          .text("Velocity");

      mySVG.append("g")
          .attr("class", "y axis")
          .attr("transform", "translate(" + width + " ,0)")
          .call(y2Axis)
        .append("text")
          .attr("transform", "rotate(-90) translate(0, -20)")
          .attr("class", "tasks-text")
          .attr("y", 6)
          .attr("dy", ".61em")
          .style("text-anchor", "end")
          .text("Tasks left");

      mySVG.append("path")
          .datum(spRemaining)
          .attr("class", "line-remaining")
          .attr("d", line);

      mySVG.append("path")
          .datum(spComplete)
          .attr("class", "line-complete")
          .attr("d", line);

      mySVG.append("path")
          .datum(spHours)
          .attr("class", "line-tasks")
          .attr("d", line2);
    },

    drawVelocity = function(data, average) {
      var margin = {top: 20, right: 20, bottom: 30, left: 50},
          width = 1200 - margin.left - margin.right,
          height = 300 - margin.top - margin.bottom;

      var x = d3.time.scale()
                .range([0, width]);

      var y = d3.scale.linear()
                .range([height, 0]);


      var xAxis = d3.svg.axis()
                    .scale(x)
                    .orient("bottom");

      var yAxis = d3.svg.axis()
                    .scale(y)
                    .orient("left");

      var iso = d3.time.format.utc("%Y-%m-%dT%H:%M:%SZ");
      var parseDate = iso.parse;

      data.forEach(function(d) {
        d.end_at = parseDate(d.end_at);
        d.velocity = +d.velocity;
      });
      average.forEach(function(d) {
        d.end_at = parseDate(d.end_at);
        d.velocity = +d.velocity;
      });

      var line = d3.svg.line()
                  .x(function(d) { return x(d.end_at); })
                  .y(function(d) { return y(d.velocity); });

      var mySVG = d3.select("#chart")
                    .append("svg")
                      .attr("width", "100%")
                      .attr("height", "320")
                      .attr("viewBox", "0 0 1200 320")
                      .attr("preserveAspectRatio", "xMinYMax meet")
                    .append("g")
                      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

      var yExtent = [0, d3.max(data, function(d) { return d.velocity; })];

      x.domain(d3.extent(data, function(d) { return d.end_at; }));
      y.domain(d3.extent(yExtent, function(d) { return d; }));

      mySVG.append("g")
          .attr("class", "x axis")
          .attr("transform", "translate(0," + height + ")")
          .call(xAxis);

      mySVG.append("g")
          .attr("class", "y axis")
          .call(yAxis)
        .append("text")
          .attr("transform", "rotate(-90)")
          .attr("y", 6)
          .attr("dy", ".71em")
          .style("text-anchor", "end")
          .text("Velocity");

      mySVG.append("path")
          .datum(data)
          .attr("class", "line-velocity")
          .attr("d", line);

      mySVG.append("path")
          .datum(average)
          .attr("class", "line-avg")
          .attr("d", line);
    },

    init = function() {

      $(".close-bar").click(function() {
        $($(this).attr('data-target')).hide();
      });

      $('.add_nested_criterium').click(function() {
        addNewItem('ol#acceptance-criteria li:last');
      });

      $('.add_nested_task').click(function() {
        addNewItem('ol#tasks li:last');
      });

      $('.js-acceptance-criteria-done').click(function(e) {
        $(this).closest('form').submit();
      });

      $('.ctrl-show-stories').click(function() {
        var whichCheckBox = $(this).val();
        var whatState = $(this).is(':checked');
        toggleStoriesByStatus(whichCheckBox, whatState);
      });

      $('.js-backlog-filter').click(function(e) {
        e.preventDefault();
        var el = $(this);
        $('.release-marker').removeClass('release-marker');
        $('dd.active').removeClass('active');
        el.parent().addClass('active');
        if (el.attr('data-filter') === 'all') {
          $('div.backlog-item').show();
          var vel = $('#backlog-items').attr('data-velocity');
          setupVelocityMarkers(vel);
        } else {
          $('div.backlog-item').hide();
          $('div.backlog-item[data-status="' + el.attr('data-filter') + '"]').show();
        }
        return false;
      });
    };

    init();

    return {
            drawBurndown : drawBurndown,
            drawVelocity : drawVelocity
    };

})();