Group the contributing calendar by day

This aligns the boxes correctly with the day on the left side of the calendar
This commit is contained in:
Phil Hughes 2016-04-27 11:07:46 +01:00
parent 36fdbc6edb
commit 18b361cf80
9 changed files with 132 additions and 120 deletions

View file

@ -19,7 +19,6 @@
#= require jquery.scrollTo
#= require jquery.turbolinks
#= require d3
#= require cal-heatmap
#= require turbolinks
#= require autosave
#= require bootstrap/affix

View file

@ -1,52 +1,83 @@
class @Calendar
constructor: (timestamps, starting_year, starting_month, calendar_activities_path) ->
constructor: (timestamps, calendar_activities_path) ->
# Get the highest value from the timestampes
highestValue = 0
_.each timestamps, (count) ->
if count > highestValue
highestValue = count
timestamps = _.chain(timestamps)
.map (stamp, key) ->
{
count: stamp
date: key
}
.groupBy (stamp, i) ->
Math.floor i / 7
.toArray()
.value()
# 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++
# Color function for chart
color = d3
.scale
.linear()
.range(['#acd5f2', '#254e77'])
.domain([0, highestValue])
# Color function for key
colorKey = d3
.scale
.linear()
.range(['#acd5f2', '#254e77'])
.domain([0, 3])
keyColors = ['#ededed', colorKey(0), colorKey(1), colorKey(2), colorKey(3)]
monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
months = []
svg = d3.select '#cal-heatmap'
svg = d3.select '.js-contrib-calendar'
.append 'svg'
.attr 'width', 53 * 17
.attr 'height', 140
.attr 'width', 54 * 17
.attr 'height', 167
.attr 'class', 'contrib-calendar'
# Setup each day box
svg.selectAll 'g'
.data timestamps
.data timestampsTmp
.enter()
.append 'g'
.attr 'transform', (group, i) ->
_.each group, (stamp) ->
month = new Date(parseInt(stamp.date) * 1000).getMonth()
x = 17 * i + 1
lastMonth = _.last(months)
_.each group, (stamp, a) ->
if a is 0 and stamp.day is 0
month = stamp.date.getMonth()
x = (17 * i + 1) + 17
lastMonth = _.last(months)
if lastMonth?
lastMonthX = lastMonth.x
# If undefined, push
if !lastMonth?
months.push
month: month
x: x
else if lastMonth.x is x
lastMonth.month = month
else if lastMonth.month isnt month
if !lastMonth?
months.push
month: month
x: x
"translate(#{17 * i + 1}, 18)"
else if month isnt lastMonth.month and x - 17 isnt lastMonthX
months.push
month: month
x: x
"translate(#{(17 * i + 1) + 17}, 18)"
.selectAll 'rect'
.data (stamp) ->
stamp
@ -54,22 +85,20 @@ class @Calendar
.append 'rect'
.attr 'x', '0'
.attr 'y', (stamp, i) ->
17 * i
(17 * stamp.day)
.attr 'width', 15
.attr 'height', 15
.attr 'title', (stamp) ->
"#{stamp.count} contributions<br />#{gl.utils.formatDate parseInt(stamp.date) * 1000}"
.attr 'class', (stamp) ->
extraClass = ''
"#{stamp.count} contributions<br />#{gl.utils.formatDate stamp.date}"
.attr 'class', 'user-contrib-cell js-tooltip'
.attr 'fill', (stamp) ->
if stamp.count isnt 0
diff = stamp.count / highestValue
classNumber = Math.floor (diff / 0.25) + 1
extraClass += "user-contrib-cell-#{classNumber}"
"user-contrib-cell #{extraClass} js-tooltip"
color(stamp.count)
else
'#ededed'
.attr 'data-container', 'body'
.on 'click', (stamp) ->
date = new Date(parseInt(stamp.date) * 1000)
date = stamp.date
formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
$.ajax
url: calendar_activities_path
@ -80,6 +109,7 @@ class @Calendar
success: (data) ->
$(".user-calendar-activities").html data
# Month titles
svg.append 'g'
.selectAll 'text'
.data months
@ -92,5 +122,44 @@ class @Calendar
.text (date) ->
monthNames[date.month]
$('#cal-heatmap .js-tooltip').tooltip
# Day titles
days = [{
text: 'M'
y: 29 + (17 * 1)
}, {
text: 'W'
y: 29 + (17 * 3)
}, {
text: 'F'
y: 29 + (17 * 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'
# Key with color boxes
svg.append 'g'
.attr 'transform', "translate(18, #{17 * 8 + 16})"
.selectAll 'rect'
.data keyColors
.enter()
.append 'rect'
.attr 'width', 15
.attr 'height', 15
.attr 'x', (color, i) ->
17 * i
.attr 'y', 0
.attr 'fill', (color) ->
color
$('.js-contrib-calendar .js-tooltip').tooltip
html: true

View file

@ -8,7 +8,6 @@
*= require select2
*= require_self
*= require dropzone/basic
*= require cal-heatmap
*= require cropper.css
*= require animate
*/

View file

@ -26,75 +26,28 @@
}
}
/**
* This overwrites the default values of the cal-heatmap gem
*/
.calendar {
.qi {
fill: #fff;
}
.user-calendar {
text-align: center;
.q1 {
fill: #ededed !important;
}
.q2 {
fill: #acd5f2 !important;
}
.q3 {
fill: #7fa8d1 !important;
}
.q4 {
fill: #49729b !important;
}
.q5 {
fill: #254e77 !important;
}
.future {
visibility: hidden;
}
.domain-background {
fill: none;
shape-rendering: crispedges;
}
.ch-tooltip {
padding: 3px;
font-weight: 550;
.calendar {
display: inline-block;
}
}
.user-contrib-cell {
fill: #ededed;
cursor: pointer;
&:hover {
cursor: pointer;
stroke: #000;
}
}
.user-contrib-cell-1 {
fill: #acd5f2;
}
.user-contrib-cell-3 {
fill: #7fa8d1;
}
.user-contrib-cell-4 {
fill: #49729b;
}
.user-contrib-cell-5 {
fill: #254e77;
}
.user-contrib-text {
font-size: 12px;
fill: #959494;
}
.calendar-hint {
margin-top: -23px;
float: right;
font-size: 12px;
}

View file

@ -66,12 +66,6 @@
}
}
.calendar-hint {
margin-top: -12px;
float: right;
font-size: 12px;
}
.profile-link-holder {
display: inline;

View file

@ -74,8 +74,6 @@ class UsersController < ApplicationController
def calendar
calendar = contributions_calendar
@timestamps = calendar.timestamps
@starting_year = calendar.starting_year
@starting_month = calendar.starting_month
render 'calendar', layout: false
end

View file

@ -1,8 +1,9 @@
#cal-heatmap.calendar
:javascript
new Calendar(
#{@timestamps.to_json},
#{@starting_year},
#{@starting_month},
'#{user_calendar_activities_path}'
);
.clearfix.calendar
.js-contrib-calendar
.calendar-hint
Summary of issues, merge requests, and push events
:javascript
new Calendar(
#{@timestamps.to_json},
'#{user_calendar_activities_path}'
);

View file

@ -89,10 +89,9 @@
.tab-content
#activity.tab-pane
.row-content-block.calender-block.white.second-block.hidden-xs
%div{ class: container_class }
.user-calendar{data: {href: user_calendar_path}}
%h4.center.light
%i.fa.fa-spinner.fa-spin
.user-calendar{data: {href: user_calendar_path}}
%h4.center.light
%i.fa.fa-spinner.fa-spin
.user-calendar-activities
.content_list{ data: {href: user_path} }

View file

@ -19,7 +19,7 @@ module Gitlab
select('date(created_at) as date, count(id) as total_amount').
map(&:attributes)
dates = (1.year.ago.to_date..(Date.today + 1.day)).to_a
dates = (1.year.ago.to_date..Date.today).to_a
dates.each do |date|
date_id = date.to_time.to_i.to_s