Commit a9288e55 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Cleanup and make contribution calendar faster

parent 6e1f9e74
...@@ -4,11 +4,13 @@ class @calendar ...@@ -4,11 +4,13 @@ class @calendar
day: "numeric" day: "numeric"
year: "numeric" year: "numeric"
constructor: (timestamps, starting_year, starting_month, activities_path) -> constructor: (timestamps, starting_year, starting_month) ->
cal = new CalHeatMap() cal = new CalHeatMap()
cal.init cal.init
itemName: ["commit"] itemName: ["commit"]
data: timestamps data: timestamps
domain: "year"
subDomain: "month"
start: new Date(starting_year, starting_month) start: new Date(starting_year, starting_month)
domainLabelFormat: "%b" domainLabelFormat: "%b"
id: "cal-heatmap" id: "cal-heatmap"
...@@ -29,43 +31,5 @@ class @calendar ...@@ -29,43 +31,5 @@ class @calendar
] ]
legendCellPadding: 3 legendCellPadding: 3
onClick: (date, count) -> onClick: (date, count) ->
$.ajax
url: activities_path
data:
date: date
dataType: "json"
success: (data) ->
$("#loading_commits").fadeIn()
calendar.calendarOnClick data, date, count
setTimeout (->
$("#calendar_onclick_placeholder").fadeIn 500
return
), 400
setTimeout (->
$("#loading_commits").hide()
return
), 400
return
return
return
@calendarOnClick: (data, date, nb)->
$("#calendar_onclick_placeholder").hide()
$("#calendar_onclick_placeholder").html ->
"<span class='calendar_onclick_second'><b>" +
((if nb is null then "no" else nb)) +
"</b><span class='calendar_commit_date'> commit" +
((if (nb isnt 1) then "s" else "")) + " " +
date.toLocaleDateString("en-US", options) +
"</span><hr class='calendar_onclick_hr'></span>"
$.each data, (key, data) ->
$.each data, (index, data) ->
$("#calendar_onclick_placeholder").append ->
"Pushed <b>" + ((if data is null then "no" else data)) + " commit" +
((if (data isnt 1) then "s" else "")) +
"</b> to <a href='/" + index + "'>" +
index + "</a><hr class='calendar_onclick_hr'>"
return return
return
return return
...@@ -25,12 +25,12 @@ class UsersController < ApplicationController ...@@ -25,12 +25,12 @@ class UsersController < ApplicationController
@title = @user.name @title = @user.name
# Get user repositories and collect timestamps for commits
user_repositories = visible_projects.map(&:repository) user_repositories = visible_projects.map(&:repository)
@timestamps = Gitlab::CommitsCalendar.create_timestamp(user_repositories, calendar = Gitlab::CommitsCalendar.new(user_repositories, @user)
@user, false) @timestamps = calendar.timestamps
@starting_year = (Time.now - 1.year).strftime("%Y") @starting_year = (Time.now - 1.year).strftime("%Y")
@starting_month = Date.today.strftime("%m").to_i @starting_month = Date.today.strftime("%m").to_i
@last_commit_date = Gitlab::CommitsCalendar.last_commit_date(@timestamps)
respond_to do |format| respond_to do |format|
format.html format.html
...@@ -38,19 +38,6 @@ class UsersController < ApplicationController ...@@ -38,19 +38,6 @@ class UsersController < ApplicationController
end end
end end
def activities
user = User.find_by_username!(params[:username])
# Projects user can view
visible_projects = ProjectsFinder.new.execute(current_user)
user_repositories = visible_projects.map(&:repository)
user_activities = Gitlab::CommitsCalendar.create_timestamp(user_repositories,
user, true)
user_activities = Gitlab::CommitsCalendar.commit_activity_match(
user_activities, params[:date])
render json: user_activities.to_json
end
def determine_layout def determine_layout
if current_user if current_user
'navless' 'navless'
......
...@@ -139,39 +139,36 @@ class Repository ...@@ -139,39 +139,36 @@ class Repository
def graph_log def graph_log
Rails.cache.fetch(cache_key(:graph_log)) do Rails.cache.fetch(cache_key(:graph_log)) do
commits = raw_repository.log(limit: 6000,
# handle empty repos that don't have a root_ref set yet skip_merges: true,
unless raw_repository.root_ref.present? ref: root_ref)
raw_repository.root_ref = 'refs/heads/master'
end
commits = raw_repository.log(limit: 6000, skip_merges: true,
ref: raw_repository.root_ref)
commits.map do |rugged_commit| commits.map do |rugged_commit|
commit = Gitlab::Git::Commit.new(rugged_commit) commit = Gitlab::Git::Commit.new(rugged_commit)
{ {
author_name: commit.author_name.force_encoding('UTF-8'), author_name: commit.author_name.force_encoding('UTF-8'),
author_email: commit.author_email.force_encoding('UTF-8'), author_email: commit.author_email.force_encoding('UTF-8'),
additions: commit.stats.additions, additions: commit.stats.additions,
deletions: commit.stats.deletions, deletions: commit.stats.deletions,
date: commit.committed_date
} }
end end
end end
end end
def graph_logs_by_user_email(user) def timestamps_by_user_log(user)
graph_log.select { |u_email| u_email[:author_email] == user.email } args = %W(git log --author=#{user.email} --since=#{(Date.today - 1.year).to_s} --pretty=format:%cd --date=short)
end dates = Gitlab::Popen.popen(args, path_to_repo).first.split("\n")
def timestamps_by_user_from_graph_log(user) if dates.present?
graph_logs_by_user_email(user).map { |graph_log| graph_log[:date].to_time.to_i } dates
else
[]
end
end end
def commits_log_of_user_by_date(user) def commits_per_day_for_user(user)
timestamps_by_user_from_graph_log(user). timestamps_by_user_log(user).
group_by { |commit_date| commit_date }. group_by { |commit_date| commit_date }.
inject({}) do |hash, (timestamp_date, commits)| inject({}) do |hash, (timestamp_date, commits)|
hash[timestamp_date] = commits.count hash[timestamp_date] = commits.count
......
#cal-heatmap.calendar #cal-heatmap.calendar
:javascript :javascript
new calendar( new calendar(
#{@timestamps.to_json}, #{@timestamps.to_json},
#{@starting_year}, #{@starting_year},
#{@starting_month}, #{@starting_month}
'#{user_activities_path}'
); );
= render "calendar_onclick"
#calendar_commit_activity.calendar_commit_activity
%h4.activity_title Commit Activity:
#loading_commits
%section.text-center
%h3
%i.icon-spinner.icon-spin
#calendar_onclick_placeholder.calendar_onclick_placeholder
%span.calendar_onclick_second.calendar_onclick_second
- if @timestamps.empty?
%span.calendar_activity_summary
%strong> #{@user.username}
&nbsp; has no activity
- else
%span.calendar_activity_summary
%strong> #{@user.username}
's last commit was on
%span.commit_date #{@last_commit_date}
%hr.calendar_onclick_hr
:javascript
$("#loading_commits").hide();
...@@ -18,8 +18,10 @@ ...@@ -18,8 +18,10 @@
%h4 Groups: %h4 Groups:
= render 'groups', groups: @groups = render 'groups', groups: @groups
%hr %hr
%h4 Calendar: %h4 Calendar:
= render 'calendar' %div= render 'calendar'
%hr
%h4 %h4
User Activity: User Activity:
......
module Gitlab module Gitlab
class CommitsCalendar class CommitsCalendar
def self.create_timestamp(repositories, user, show_activity) attr_reader :timestamps
timestamps = {}
repositories.each do |raw_repository|
if raw_repository.exists?
commits_log = raw_repository.commits_log_of_user_by_date(user)
populated_timestamps = def initialize(repositories, user)
if show_activity @timestamps = {}
populate_timestamps_by_project( date_timestamps = []
commits_log,
timestamps,
raw_repository
)
else
populate_timestamps(commits_log, timestamps)
end
timestamps.merge!(populated_timestamps)
end
end
timestamps
end
def self.populate_timestamps(commits_log, timestamps) repositories.select(&:exists?).reject(&:empty?).each do |raw_repository|
commits_log.each do |timestamp_date, commits_count| commits_log = raw_repository.commits_per_day_for_user(user)
hash = { "#{timestamp_date}" => commits_count } date_timestamps << commits_log
if timestamps.has_key?("#{timestamp_date}")
timestamps.merge!(hash) do |timestamp_date, commits_count,
new_commits_count| commits_count = commits_count.to_i +
new_commits_count
end
else
timestamps.merge!(hash)
end
end end
timestamps
end
def self.populate_timestamps_by_project(commits_log, timestamps, date_timestamps = date_timestamps.inject do |collection, date|
project) collection.merge(date) { |k, old_v, new_v| old_v + new_v }
commits_log.each do |timestamp_date, commits_count|
if timestamps.has_key?("#{timestamp_date}")
timestamps["#{timestamp_date}"].
merge!(project.path_with_namespace => commits_count)
else
hash = { "#{timestamp_date}" => { project.path_with_namespace =>
commits_count } }
timestamps.merge!(hash)
end
end end
timestamps
end
def self.latest_commit_date(timestamps) date_timestamps ||= []
if timestamps.nil? || timestamps.empty? date_timestamps.each do |date, commits|
DateTime.now.to_date timestamp = Date.parse(date).to_time.to_i.to_s
else @timestamps[timestamp] = commits
Time.at(timestamps.keys.first.to_i).to_date
end end
end end
def self.last_commit_date(timestamps)
latest_commit_date(timestamps).to_formatted_s(:long).to_s
end
def self.commit_activity_match(user_activities, date)
user_activities.select { |x| Time.at(x.to_i) == Time.parse(date) }
end
end end
end end
...@@ -2,12 +2,12 @@ require 'spec_helper' ...@@ -2,12 +2,12 @@ require 'spec_helper'
describe UsersController do describe UsersController do
let(:user) { create(:user, username: "user1", name: "User 1", email: "user1@gitlab.com") } let(:user) { create(:user, username: "user1", name: "User 1", email: "user1@gitlab.com") }
before do before do
sign_in(user) sign_in(user)
end end
describe "GET #show" do describe "GET #show" do
render_views render_views
before do before do
get :show, username: user.username get :show, username: user.username
......
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