198 lines
5.3 KiB
CoffeeScript
198 lines
5.3 KiB
CoffeeScript
class @Calendar
|
|
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 = []
|
|
@highestValue = 0
|
|
|
|
# Get the highest value from the timestampes
|
|
_.each timestamps, (count) =>
|
|
if count > @highestValue
|
|
@highestValue = count
|
|
|
|
# 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
|
|
@timestampsTmp = []
|
|
i = 0
|
|
group = 0
|
|
_.each timestamps, (count, date) =>
|
|
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
|
|
@timestampsTmp.push []
|
|
group++
|
|
|
|
innerArray = @timestampsTmp[group-1]
|
|
|
|
# Push to the inner array the values that will be used to render map
|
|
innerArray.push
|
|
count: count
|
|
date: newDate
|
|
day: day
|
|
|
|
i++
|
|
|
|
# Init color functions
|
|
@color = @initColor()
|
|
@colorKey = @initColorKey()
|
|
|
|
# Init the svg element
|
|
@renderSvg(group)
|
|
@renderDays()
|
|
@renderMonths()
|
|
@renderDayTitles()
|
|
@renderKey()
|
|
|
|
@initTooltips()
|
|
|
|
renderSvg: (group) ->
|
|
@svg = d3.select '.js-contrib-calendar'
|
|
.append 'svg'
|
|
.attr 'width', (group + 1) * @daySizeWithSpace
|
|
.attr 'height', 167
|
|
.attr 'class', 'contrib-calendar'
|
|
|
|
renderDays: ->
|
|
@svg.selectAll 'g'
|
|
.data @timestampsTmp
|
|
.enter()
|
|
.append 'g'
|
|
.attr 'transform', (group, i) =>
|
|
_.each group, (stamp, a) =>
|
|
if a is 0 and stamp.day is 0
|
|
month = stamp.date.getMonth()
|
|
x = (@daySizeWithSpace * i + 1) + @daySizeWithSpace
|
|
lastMonth = _.last(@months)
|
|
if lastMonth?
|
|
lastMonthX = lastMonth.x
|
|
|
|
if !lastMonth?
|
|
@months.push
|
|
month: month
|
|
x: x
|
|
else if month isnt lastMonth.month and x - @daySizeWithSpace isnt lastMonthX
|
|
@months.push
|
|
month: month
|
|
x: x
|
|
|
|
"translate(#{(@daySizeWithSpace * i + 1) + @daySizeWithSpace}, 18)"
|
|
.selectAll 'rect'
|
|
.data (stamp) ->
|
|
stamp
|
|
.enter()
|
|
.append 'rect'
|
|
.attr 'x', '0'
|
|
.attr 'y', (stamp, i) =>
|
|
(@daySizeWithSpace * stamp.day)
|
|
.attr 'width', @daySize
|
|
.attr 'height', @daySize
|
|
.attr 'title', (stamp) =>
|
|
contribText = 'No contributions'
|
|
|
|
if stamp.count > 0
|
|
contribText = "#{stamp.count} contribution#{if stamp.count > 1 then 's' else ''}"
|
|
|
|
date = dateFormat(stamp.date, 'mmm d, yyyy')
|
|
|
|
"#{contribText}<br />#{date}"
|
|
.attr 'class', 'user-contrib-cell js-tooltip'
|
|
.attr 'fill', (stamp) =>
|
|
if stamp.count isnt 0
|
|
@color(stamp.count)
|
|
else
|
|
'#ededed'
|
|
.attr 'data-container', 'body'
|
|
.on 'click', @clickDay
|
|
|
|
renderDayTitles: ->
|
|
days = [{
|
|
text: 'M'
|
|
y: 29 + (@daySizeWithSpace * 1)
|
|
}, {
|
|
text: 'W'
|
|
y: 29 + (@daySizeWithSpace * 3)
|
|
}, {
|
|
text: 'F'
|
|
y: 29 + (@daySizeWithSpace * 5)
|
|
}]
|
|
@svg.append 'g'
|
|
.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'
|
|
|
|
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})"
|
|
.selectAll 'rect'
|
|
.data keyColors
|
|
.enter()
|
|
.append 'rect'
|
|
.attr 'width', @daySize
|
|
.attr 'height', @daySize
|
|
.attr 'x', (color, i) =>
|
|
@daySizeWithSpace * i
|
|
.attr 'y', 0
|
|
.attr 'fill', (color) ->
|
|
color
|
|
|
|
initColor: ->
|
|
d3.scale
|
|
.linear()
|
|
.range(['#acd5f2', '#254e77'])
|
|
.domain([0, @highestValue])
|
|
|
|
initColorKey: ->
|
|
d3.scale
|
|
.linear()
|
|
.range(['#acd5f2', '#254e77'])
|
|
.domain([0, 3])
|
|
|
|
clickDay: (stamp) =>
|
|
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: ->
|
|
$('.js-contrib-calendar .js-tooltip').tooltip
|
|
html: true
|