calendar.js.coffee 5.29 KB
Newer Older
1
class @Calendar
Phil Hughes's avatar
Phil Hughes committed
2 3 4 5 6 7 8
  constructor: (timestamps, @calendar_activities_path) ->
    @currentSelectedDate = ''
    @daySpace = 1
    @daySize = 15
    @daySizeWithSpace = @daySize + (@daySpace * 2)
    @monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
    @months = []
9

10 11
    # Loop through the timestamps to create a group of objects
    # The group of objects will be grouped based on the day of the week they are
Phil Hughes's avatar
Phil Hughes committed
12
    @timestampsTmp = []
13 14
    i = 0
    group = 0
Phil Hughes's avatar
Phil Hughes committed
15
    _.each timestamps, (count, date) =>
16 17 18 19 20 21
      newDate = new Date parseInt(date) * 1000
      day = newDate.getDay()

      # Create a new group array if this is the first day of the week
      # or if is first object
      if (day is 0 and i isnt 0) or i is 0
Phil Hughes's avatar
Phil Hughes committed
22
        @timestampsTmp.push []
23 24
        group++

Phil Hughes's avatar
Phil Hughes committed
25
      innerArray = @timestampsTmp[group-1]
26 27 28 29 30 31 32 33 34

      # Push to the inner array the values that will be used to render map
      innerArray.push
        count: count
        date: newDate
        day: day

      i++

Phil Hughes's avatar
Phil Hughes committed
35 36
    # Init color functions
    @colorKey = @initColorKey()
37
    @color = @initColor()
38

Phil Hughes's avatar
Phil Hughes committed
39 40 41 42 43 44 45 46
    # Init the svg element
    @renderSvg(group)
    @renderDays()
    @renderMonths()
    @renderDayTitles()
    @renderKey()

    @initTooltips()
47

Phil Hughes's avatar
Phil Hughes committed
48 49
  renderSvg: (group) ->
    @svg = d3.select '.js-contrib-calendar'
50
      .append 'svg'
Phil Hughes's avatar
Phil Hughes committed
51
      .attr 'width', (group + 1) * @daySizeWithSpace
52 53
      .attr 'height', 167
      .attr 'class', 'contrib-calendar'
54

Phil Hughes's avatar
Phil Hughes committed
55 56 57
  renderDays: ->
    @svg.selectAll 'g'
      .data @timestampsTmp
58 59
      .enter()
      .append 'g'
Phil Hughes's avatar
Phil Hughes committed
60 61
      .attr 'transform', (group, i) =>
        _.each group, (stamp, a) =>
62 63
          if a is 0 and stamp.day is 0
            month = stamp.date.getMonth()
Phil Hughes's avatar
Phil Hughes committed
64 65
            x = (@daySizeWithSpace * i + 1) + @daySizeWithSpace
            lastMonth = _.last(@months)
66 67
            if lastMonth?
              lastMonthX = lastMonth.x
68

69
            if !lastMonth?
Phil Hughes's avatar
Phil Hughes committed
70
              @months.push
71 72
                month: month
                x: x
Phil Hughes's avatar
Phil Hughes committed
73 74
            else if month isnt lastMonth.month and x - @daySizeWithSpace isnt lastMonthX
              @months.push
75 76 77
                month: month
                x: x

Phil Hughes's avatar
Phil Hughes committed
78
        "translate(#{(@daySizeWithSpace * i + 1) + @daySizeWithSpace}, 18)"
79 80 81 82 83 84
      .selectAll 'rect'
      .data (stamp) ->
        stamp
      .enter()
      .append 'rect'
      .attr 'x', '0'
Phil Hughes's avatar
Phil Hughes committed
85 86 87 88 89
      .attr 'y', (stamp, i) =>
        (@daySizeWithSpace * stamp.day)
      .attr 'width', @daySize
      .attr 'height', @daySize
      .attr 'title', (stamp) =>
90
        date = new Date(stamp.date)
91 92 93 94 95
        contribText = 'No contributions'

        if stamp.count > 0
          contribText = "#{stamp.count} contribution#{if stamp.count > 1 then 's' else ''}"

96
        dateText = dateFormat(date, 'mmm d, yyyy')
97

98
        "#{contribText}<br />#{gl.utils.getDayName(date)} #{dateText}"
99
      .attr 'class', 'user-contrib-cell js-tooltip'
Phil Hughes's avatar
Phil Hughes committed
100
      .attr 'fill', (stamp) =>
101
        if stamp.count isnt 0
102
          @color(Math.min(stamp.count, 40))
103 104
        else
          '#ededed'
105
      .attr 'data-container', 'body'
Phil Hughes's avatar
Phil Hughes committed
106
      .on 'click', @clickDay
107

Phil Hughes's avatar
Phil Hughes committed
108
  renderDayTitles: ->
109 110
    days = [{
      text: 'M'
Phil Hughes's avatar
Phil Hughes committed
111
      y: 29 + (@daySizeWithSpace * 1)
112 113
    }, {
      text: 'W'
Phil Hughes's avatar
Phil Hughes committed
114
      y: 29 + (@daySizeWithSpace * 3)
115 116
    }, {
      text: 'F'
Phil Hughes's avatar
Phil Hughes committed
117
      y: 29 + (@daySizeWithSpace * 5)
118
    }]
Phil Hughes's avatar
Phil Hughes committed
119
    @svg.append 'g'
120 121 122 123 124 125 126 127 128 129 130 131
      .selectAll 'text'
      .data days
      .enter()
      .append 'text'
      .attr 'text-anchor', 'middle'
      .attr 'x', 8
      .attr 'y', (day) ->
        day.y
      .text (day) ->
        day.text
      .attr 'class', 'user-contrib-text'

Phil Hughes's avatar
Phil Hughes committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
  renderMonths: ->
    @svg.append 'g'
      .selectAll 'text'
      .data @months
      .enter()
      .append 'text'
      .attr 'x', (date) ->
        date.x
      .attr 'y', 10
      .attr 'class', 'user-contrib-text'
      .text (date) =>
        @monthNames[date.month]

  renderKey: ->
    keyColors = ['#ededed', @colorKey(0), @colorKey(1), @colorKey(2), @colorKey(3)]
    @svg.append 'g'
      .attr 'transform', "translate(18, #{@daySizeWithSpace * 8 + 16})"
149 150 151 152
      .selectAll 'rect'
      .data keyColors
      .enter()
      .append 'rect'
Phil Hughes's avatar
Phil Hughes committed
153 154 155 156
      .attr 'width', @daySize
      .attr 'height', @daySize
      .attr 'x', (color, i) =>
        @daySizeWithSpace * i
157 158 159 160
      .attr 'y', 0
      .attr 'fill', (color) ->
        color

Phil Hughes's avatar
Phil Hughes committed
161
  initColor: ->
162
    colorRange = ['#ededed', @colorKey(0), @colorKey(1), @colorKey(2), @colorKey(3)]
Phil Hughes's avatar
Phil Hughes committed
163
    d3.scale
164 165 166
      .threshold()
      .domain([0, 10, 20, 30])
      .range(colorRange)
Phil Hughes's avatar
Phil Hughes committed
167 168 169 170 171 172 173

  initColorKey: ->
    d3.scale
      .linear()
      .range(['#acd5f2', '#254e77'])
      .domain([0, 3])

174
  clickDay: (stamp) =>
Phil Hughes's avatar
Phil Hughes committed
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
    if @currentSelectedDate isnt stamp.date
      @currentSelectedDate = stamp.date
      formatted_date = @currentSelectedDate.getFullYear() + "-" + (@currentSelectedDate.getMonth()+1) + "-" + @currentSelectedDate.getDate()

      $.ajax
        url: @calendar_activities_path
        data:
          date: formatted_date
        cache: false
        dataType: 'html'
        beforeSend: ->
          $('.user-calendar-activities').html '<div class="text-center"><i class="fa fa-spinner fa-spin user-calendar-activities-loading"></i></div>'
        success: (data) ->
          $('.user-calendar-activities').html data
    else
      $('.user-calendar-activities').html ''

  initTooltips: ->
193
    $('.js-contrib-calendar .js-tooltip').tooltip
194
      html: true