summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Schatz <jschatz@gitlab.com>2016-05-25 23:29:41 +0000
committerJacob Schatz <jschatz@gitlab.com>2016-05-25 23:29:41 +0000
commit3d009f77853261d43f1d5302d8016f4641ba5fca (patch)
tree6416c7ee98aa2d88c3c205d69ce62c0121881c78
parent4b4cda85b24bbf825a37f55b4ce1430c1ccc9965 (diff)
parent527d64463530df5a2f5f800885f5f84920b1058b (diff)
downloadgitlab-ce-3d009f77853261d43f1d5302d8016f4641ba5fca.tar.gz
Merge branch 'updated-contrib-calendar' into 'master'
POC: Updated contrib calendar In an effort to cut down the JS file size - i've removed the heatmap calendar used for the contributing calendar on users profiles. We already have d3 on the page so why not use it instead of using a library which uses it? ![Screen_Shot_2016-04-27_at_11.08.41](/uploads/64c40f0c766f800fd0e33ac8be7f9644/Screen_Shot_2016-04-27_at_11.08.41.png) cc. @jschatz1 See merge request !3944
-rw-r--r--Gemfile3
-rw-r--r--Gemfile.lock2
-rw-r--r--app/assets/javascripts/application.js.coffee1
-rw-r--r--app/assets/javascripts/calendar.js.coffee228
-rw-r--r--app/assets/stylesheets/application.scss1
-rw-r--r--app/assets/stylesheets/framework/calendar.scss72
-rw-r--r--app/assets/stylesheets/pages/profile.scss6
-rw-r--r--app/controllers/users_controller.rb2
-rw-r--r--app/views/users/calendar.html.haml19
-rw-r--r--app/views/users/calendar_activities.html.haml42
-rw-r--r--app/views/users/show.html.haml7
-rw-r--r--features/steps/user.rb2
-rw-r--r--lib/gitlab/contributions_calendar.rb2
13 files changed, 256 insertions, 131 deletions
diff --git a/Gemfile b/Gemfile
index c236f37e14a..b897dc0a741 100644
--- a/Gemfile
+++ b/Gemfile
@@ -178,9 +178,6 @@ gem 'ruby-fogbugz', '~> 0.2.1'
# d3
gem 'd3_rails', '~> 3.5.0'
-#cal-heatmap
-gem 'cal-heatmap-rails', '~> 3.6.0'
-
# underscore-rails
gem "underscore-rails", "~> 1.8.0"
diff --git a/Gemfile.lock b/Gemfile.lock
index dbc0fd15ef4..fa2b72b2524 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -102,7 +102,6 @@ GEM
bundler (~> 1.2)
thor (~> 0.18)
byebug (8.2.1)
- cal-heatmap-rails (3.6.0)
capybara (2.6.2)
addressable
mime-types (>= 1.16)
@@ -908,7 +907,6 @@ DEPENDENCIES
bullet
bundler-audit
byebug
- cal-heatmap-rails (~> 3.6.0)
capybara (~> 2.6.2)
capybara-screenshot (~> 1.0.0)
carrierwave (~> 0.10.0)
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee
index bffce5a0c0f..ff69e27bbcf 100644
--- a/app/assets/javascripts/application.js.coffee
+++ b/app/assets/javascripts/application.js.coffee
@@ -19,7 +19,6 @@
#= require jquery.scrollTo
#= require jquery.turbolinks
#= require d3
-#= require cal-heatmap
#= require turbolinks
#= require autosave
#= require bootstrap/affix
diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee
index d80e0e716ce..f9c7bffdadb 100644
--- a/app/assets/javascripts/calendar.js.coffee
+++ b/app/assets/javascripts/calendar.js.coffee
@@ -1,34 +1,198 @@
class @Calendar
- constructor: (timestamps, starting_year, starting_month, calendar_activities_path) ->
- cal = new CalHeatMap()
- cal.init
- itemName: ["contribution"]
- data: timestamps
- start: new Date(starting_year, starting_month)
- domainLabelFormat: "%b"
- id: "cal-heatmap"
- domain: "month"
- subDomain: "day"
- range: 12
- tooltip: true
- label:
- position: "top"
- legend: [
- 0
- 10
- 20
- 30
- ]
- legendCellPadding: 3
- cellSize: $('.user-calendar').width() / 73
- onClick: (date, count) ->
- formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
- $.ajax
- url: calendar_activities_path
- data:
- date: formated_date
- cache: false
- dataType: "html"
- success: (data) ->
- $(".user-calendar-activities").html data
+ 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
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index e2d590f4df4..8b93665d085 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -8,7 +8,6 @@
*= require select2
*= require_self
*= require dropzone/basic
- *= require cal-heatmap
*= require cropper.css
*/
diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss
index 11f39d583bd..8642b7530e2 100644
--- a/app/assets/stylesheets/framework/calendar.scss
+++ b/app/assets/stylesheets/framework/calendar.scss
@@ -1,70 +1,44 @@
.calender-block {
+ padding-left: 0;
+ padding-right: 0;
+
@media (min-width: $screen-sm-min) and (max-width: $screen-lg-min) {
overflow-x: scroll;
}
}
.user-calendar-activities {
- .calendar_onclick_hr {
- padding: 0;
- margin: 10px 0;
- }
-
.str-truncated {
max-width: 70%;
}
- .text-expander {
- background: #eee;
- color: #555;
- padding: 0 5px;
- cursor: pointer;
- margin-left: 4px;
- &:hover {
- background-color: #ddd;
- }
+ .user-calendar-activities-loading {
+ font-size: 24px;
}
}
-/**
-* This overwrites the default values of the cal-heatmap gem
-*/
-.calendar {
- .qi {
- fill: #fff;
- }
-
- .q1 {
- fill: #ededed !important;
- }
+.user-calendar {
+ text-align: center;
- .q2 {
- fill: #acd5f2 !important;
- }
-
- .q3 {
- fill: #7fa8d1 !important;
- }
-
- .q4 {
- fill: #49729b !important;
- }
-
- .q5 {
- fill: #254e77 !important;
+ .calendar {
+ display: inline-block;
}
+}
- .future {
- visibility: hidden;
+.user-contrib-cell {
+ &:hover {
+ cursor: pointer;
+ stroke: #000;
}
+}
- .domain-background {
- fill: none;
- shape-rendering: crispedges;
- }
+.user-contrib-text {
+ font-size: 12px;
+ fill: #959494;
+}
- .ch-tooltip {
- padding: 3px;
- font-weight: 550;
- }
+.calendar-hint {
+ margin-top: -23px;
+ float: right;
+ font-size: 12px;
}
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 8040dd0a1d8..167ab40d881 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -66,12 +66,6 @@
}
}
-.calendar-hint {
- margin-top: -12px;
- float: right;
- font-size: 12px;
-}
-
.profile-link-holder {
display: inline;
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 799421c185b..a99632454d9 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -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
diff --git a/app/views/users/calendar.html.haml b/app/views/users/calendar.html.haml
index 1de71f37d1a..77f2ddefb1e 100644
--- a/app/views/users/calendar.html.haml
+++ b/app/views/users/calendar.html.haml
@@ -1,10 +1,9 @@
-#cal-heatmap.calendar
- :javascript
- new Calendar(
- #{@timestamps.to_json},
- #{@starting_year},
- #{@starting_month},
- '#{user_calendar_activities_path}'
- );
-
-.calendar-hint Summary of issues, merge requests, and push events
+.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}'
+ );
diff --git a/app/views/users/calendar_activities.html.haml b/app/views/users/calendar_activities.html.haml
index 027a93a75fc..630d97e339d 100644
--- a/app/views/users/calendar_activities.html.haml
+++ b/app/views/users/calendar_activities.html.haml
@@ -1,23 +1,27 @@
%h4.prepend-top-20
- %span.light Contributions for
+ Contributions for
%strong #{@calendar_date.to_s(:short)}
-%ul.bordered-list
- - @events.sort_by(&:created_at).each do |event|
- %li
- %span.light
- %i.fa.fa-clock-o
- = event.created_at.to_s(:time)
- - if event.push?
- #{event.action_name} #{event.ref_type} #{event.ref_name}
- - else
- = event_action_name(event)
- - if event.target
- %strong= link_to "##{event.target_iid}", [event.project.namespace.becomes(Namespace), event.project, event.target]
-
- at
- %strong
- - if event.project
- = link_to_project event.project
+- if @events.any?
+ %ul.bordered-list
+ - @events.sort_by(&:created_at).each do |event|
+ %li
+ %span.light
+ %i.fa.fa-clock-o
+ = event.created_at.to_s(:time)
+ - if event.push?
+ #{event.action_name} #{event.ref_type} #{event.ref_name}
- else
- = event.project_name
+ = event_action_name(event)
+ - if event.target
+ %strong= link_to "##{event.target_iid}", [event.project.namespace.becomes(Namespace), event.project, event.target]
+
+ at
+ %strong
+ - if event.project
+ = link_to_project event.project
+ - else
+ = event.project_name
+- else
+ %p
+ No contributions found for #{@calendar_date.to_s(:short)}
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 9017fd54fcc..0c513308308 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -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} }
diff --git a/features/steps/user.rb b/features/steps/user.rb
index b1d088f07f9..59385a6ab59 100644
--- a/features/steps/user.rb
+++ b/features/steps/user.rb
@@ -34,7 +34,7 @@ class Spinach::Features::User < Spinach::FeatureSteps
end
step 'I should see contributions calendar' do
- expect(page).to have_css('.cal-heatmap-container')
+ expect(page).to have_css('.js-contrib-calendar')
end
def contributed_project
diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb
index 85583dce9ee..9dc2602867e 100644
--- a/lib/gitlab/contributions_calendar.rb
+++ b/lib/gitlab/contributions_calendar.rb
@@ -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