Commit 18b361cf authored by Phil Hughes's avatar Phil Hughes

Group the contributing calendar by day

This aligns the boxes correctly with the day on the left side of the calendar
parent 36fdbc6e
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#= require jquery.scrollTo #= require jquery.scrollTo
#= require jquery.turbolinks #= require jquery.turbolinks
#= require d3 #= require d3
#= require cal-heatmap
#= require turbolinks #= require turbolinks
#= require autosave #= require autosave
#= require bootstrap/affix #= require bootstrap/affix
......
class @Calendar class @Calendar
constructor: (timestamps, starting_year, starting_month, calendar_activities_path) -> constructor: (timestamps, calendar_activities_path) ->
# Get the highest value from the timestampes # Get the highest value from the timestampes
highestValue = 0 highestValue = 0
_.each timestamps, (count) -> _.each timestamps, (count) ->
if count > highestValue if count > highestValue
highestValue = count highestValue = count
timestamps = _.chain(timestamps) # Loop through the timestamps to create a group of objects
.map (stamp, key) -> # The group of objects will be grouped based on the day of the week they are
{ timestampsTmp = []
count: stamp i = 0
date: key group = 0
} _.each timestamps, (count, date) ->
.groupBy (stamp, i) -> newDate = new Date parseInt(date) * 1000
Math.floor i / 7 day = newDate.getDay()
.toArray()
.value() # 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'] monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
months = [] months = []
svg = d3.select '#cal-heatmap' svg = d3.select '.js-contrib-calendar'
.append 'svg' .append 'svg'
.attr 'width', 53 * 17 .attr 'width', 54 * 17
.attr 'height', 140 .attr 'height', 167
.attr 'class', 'contrib-calendar'
# Setup each day box # Setup each day box
svg.selectAll 'g' svg.selectAll 'g'
.data timestamps .data timestampsTmp
.enter() .enter()
.append 'g' .append 'g'
.attr 'transform', (group, i) -> .attr 'transform', (group, i) ->
_.each group, (stamp) -> _.each group, (stamp, a) ->
month = new Date(parseInt(stamp.date) * 1000).getMonth() if a is 0 and stamp.day is 0
x = 17 * i + 1 month = stamp.date.getMonth()
lastMonth = _.last(months) x = (17 * i + 1) + 17
lastMonth = _.last(months)
if lastMonth?
lastMonthX = lastMonth.x
# If undefined, push if !lastMonth?
if !lastMonth?
months.push
month: month
x: x
else if lastMonth.x is x
lastMonth.month = month
else if lastMonth.month isnt month
months.push months.push
month: month month: month
x: x 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' .selectAll 'rect'
.data (stamp) -> .data (stamp) ->
stamp stamp
...@@ -54,22 +85,20 @@ class @Calendar ...@@ -54,22 +85,20 @@ class @Calendar
.append 'rect' .append 'rect'
.attr 'x', '0' .attr 'x', '0'
.attr 'y', (stamp, i) -> .attr 'y', (stamp, i) ->
17 * i (17 * stamp.day)
.attr 'width', 15 .attr 'width', 15
.attr 'height', 15 .attr 'height', 15
.attr 'title', (stamp) -> .attr 'title', (stamp) ->
"#{stamp.count} contributions<br />#{gl.utils.formatDate parseInt(stamp.date) * 1000}" "#{stamp.count} contributions<br />#{gl.utils.formatDate stamp.date}"
.attr 'class', (stamp) -> .attr 'class', 'user-contrib-cell js-tooltip'
extraClass = '' .attr 'fill', (stamp) ->
if stamp.count isnt 0 if stamp.count isnt 0
diff = stamp.count / highestValue color(stamp.count)
classNumber = Math.floor (diff / 0.25) + 1 else
extraClass += "user-contrib-cell-#{classNumber}" '#ededed'
"user-contrib-cell #{extraClass} js-tooltip"
.attr 'data-container', 'body' .attr 'data-container', 'body'
.on 'click', (stamp) -> .on 'click', (stamp) ->
date = new Date(parseInt(stamp.date) * 1000) date = stamp.date
formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate() formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
$.ajax $.ajax
url: calendar_activities_path url: calendar_activities_path
...@@ -80,6 +109,7 @@ class @Calendar ...@@ -80,6 +109,7 @@ class @Calendar
success: (data) -> success: (data) ->
$(".user-calendar-activities").html data $(".user-calendar-activities").html data
# Month titles
svg.append 'g' svg.append 'g'
.selectAll 'text' .selectAll 'text'
.data months .data months
...@@ -92,5 +122,44 @@ class @Calendar ...@@ -92,5 +122,44 @@ class @Calendar
.text (date) -> .text (date) ->
monthNames[date.month] 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 html: true
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
*= require select2 *= require select2
*= require_self *= require_self
*= require dropzone/basic *= require dropzone/basic
*= require cal-heatmap
*= require cropper.css *= require cropper.css
*= require animate *= require animate
*/ */
......
...@@ -26,75 +26,28 @@ ...@@ -26,75 +26,28 @@
} }
} }
/** .user-calendar {
* This overwrites the default values of the cal-heatmap gem text-align: center;
*/
.calendar {
.qi {
fill: #fff;
}
.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 { .calendar {
padding: 3px; display: inline-block;
font-weight: 550;
} }
} }
.user-contrib-cell { .user-contrib-cell {
fill: #ededed;
cursor: pointer;
&:hover { &:hover {
cursor: pointer;
stroke: #000; 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 { .user-contrib-text {
font-size: 12px; font-size: 12px;
fill: #959494; fill: #959494;
} }
.calendar-hint {
margin-top: -23px;
float: right;
font-size: 12px;
}
...@@ -66,12 +66,6 @@ ...@@ -66,12 +66,6 @@
} }
} }
.calendar-hint {
margin-top: -12px;
float: right;
font-size: 12px;
}
.profile-link-holder { .profile-link-holder {
display: inline; display: inline;
......
...@@ -74,8 +74,6 @@ class UsersController < ApplicationController ...@@ -74,8 +74,6 @@ class UsersController < ApplicationController
def calendar def calendar
calendar = contributions_calendar calendar = contributions_calendar
@timestamps = calendar.timestamps @timestamps = calendar.timestamps
@starting_year = calendar.starting_year
@starting_month = calendar.starting_month
render 'calendar', layout: false render 'calendar', layout: false
end end
......
#cal-heatmap.calendar .clearfix.calendar
:javascript .js-contrib-calendar
new Calendar( .calendar-hint
#{@timestamps.to_json}, Summary of issues, merge requests, and push events
#{@starting_year}, :javascript
#{@starting_month}, new Calendar(
'#{user_calendar_activities_path}' #{@timestamps.to_json},
); '#{user_calendar_activities_path}'
);
...@@ -89,10 +89,9 @@ ...@@ -89,10 +89,9 @@
.tab-content .tab-content
#activity.tab-pane #activity.tab-pane
.row-content-block.calender-block.white.second-block.hidden-xs .row-content-block.calender-block.white.second-block.hidden-xs
%div{ class: container_class } .user-calendar{data: {href: user_calendar_path}}
.user-calendar{data: {href: user_calendar_path}} %h4.center.light
%h4.center.light %i.fa.fa-spinner.fa-spin
%i.fa.fa-spinner.fa-spin
.user-calendar-activities .user-calendar-activities
.content_list{ data: {href: user_path} } .content_list{ data: {href: user_path} }
......
...@@ -19,7 +19,7 @@ module Gitlab ...@@ -19,7 +19,7 @@ module Gitlab
select('date(created_at) as date, count(id) as total_amount'). select('date(created_at) as date, count(id) as total_amount').
map(&:attributes) 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| dates.each do |date|
date_id = date.to_time.to_i.to_s date_id = date.to_time.to_i.to_s
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment