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:
parent
36fdbc6edb
commit
18b361cf80
9 changed files with 132 additions and 120 deletions
|
@ -19,7 +19,6 @@
|
|||
#= require jquery.scrollTo
|
||||
#= require jquery.turbolinks
|
||||
#= require d3
|
||||
#= require cal-heatmap
|
||||
#= require turbolinks
|
||||
#= require autosave
|
||||
#= require bootstrap/affix
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
*= require select2
|
||||
*= require_self
|
||||
*= require dropzone/basic
|
||||
*= require cal-heatmap
|
||||
*= require cropper.css
|
||||
*= require animate
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -66,12 +66,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.calendar-hint {
|
||||
margin-top: -12px;
|
||||
float: right;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.profile-link-holder {
|
||||
display: inline;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}'
|
||||
);
|
||||
|
|
|
@ -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} }
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue