Add comment events to contributions calendar
Signed-off-by: Rémy Coutable <remy@rymai.me>
This commit is contained in:
parent
79d6838303
commit
4f51e1fad0
|
@ -45,9 +45,10 @@ class Event < ActiveRecord::Base
|
||||||
class << self
|
class << self
|
||||||
# Update Gitlab::ContributionsCalendar#activity_dates if this changes
|
# Update Gitlab::ContributionsCalendar#activity_dates if this changes
|
||||||
def contributions
|
def contributions
|
||||||
where("action = ? OR (target_type in (?) AND action in (?))",
|
where("action = ? OR (target_type IN (?) AND action IN (?)) OR (target_type = ? AND action = ?)",
|
||||||
Event::PUSHED, ["MergeRequest", "Issue"],
|
Event::PUSHED,
|
||||||
[Event::CREATED, Event::CLOSED, Event::MERGED])
|
["MergeRequest", "Issue"], [Event::CREATED, Event::CLOSED, Event::MERGED],
|
||||||
|
"Note", Event::COMMENTED)
|
||||||
end
|
end
|
||||||
|
|
||||||
def limit_recent(limit = 20, offset = nil)
|
def limit_recent(limit = 20, offset = nil)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
.clearfix.calendar
|
.clearfix.calendar
|
||||||
.js-contrib-calendar
|
.js-contrib-calendar
|
||||||
.calendar-hint
|
.calendar-hint
|
||||||
Summary of issues, merge requests, and push events
|
Summary of issues, merge requests, push events, and comments
|
||||||
:javascript
|
:javascript
|
||||||
new Calendar(
|
new Calendar(
|
||||||
#{@activity_dates.to_json},
|
#{@activity_dates.to_json},
|
||||||
|
|
|
@ -13,8 +13,10 @@
|
||||||
#{event.action_name} #{event.ref_type} #{event.ref_name}
|
#{event.action_name} #{event.ref_type} #{event.ref_name}
|
||||||
- else
|
- else
|
||||||
= event_action_name(event)
|
= event_action_name(event)
|
||||||
- if event.target
|
- if event.note?
|
||||||
%strong= link_to "#{event.target.to_reference}", [event.project.namespace.becomes(Namespace), event.project, event.target]
|
%strong= link_to event.note_target.to_reference, event_note_target_path(event)
|
||||||
|
- elsif event.target
|
||||||
|
%strong= link_to event.target.to_reference, [event.project.namespace.becomes(Namespace), event.project, event.target]
|
||||||
|
|
||||||
at
|
at
|
||||||
%strong
|
%strong
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Add discussion events to contributions calendar
|
||||||
|
merge_request: 8821
|
||||||
|
author:
|
|
@ -22,8 +22,10 @@ module Gitlab
|
||||||
having(action: [Event::CREATED, Event::CLOSED], target_type: "Issue")
|
having(action: [Event::CREATED, Event::CLOSED], target_type: "Issue")
|
||||||
mr_events = event_counts(date_from, :merge_requests).
|
mr_events = event_counts(date_from, :merge_requests).
|
||||||
having(action: [Event::MERGED, Event::CREATED, Event::CLOSED], target_type: "MergeRequest")
|
having(action: [Event::MERGED, Event::CREATED, Event::CLOSED], target_type: "MergeRequest")
|
||||||
|
note_events = event_counts(date_from, :merge_requests).
|
||||||
|
having(action: [Event::COMMENTED], target_type: "Note")
|
||||||
|
|
||||||
union = Gitlab::SQL::Union.new([repo_events, issue_events, mr_events])
|
union = Gitlab::SQL::Union.new([repo_events, issue_events, mr_events, note_events])
|
||||||
events = Event.find_by_sql(union.to_sql).map(&:attributes)
|
events = Event.find_by_sql(union.to_sql).map(&:attributes)
|
||||||
|
|
||||||
@activity_events = events.each_with_object(Hash.new {|h, k| h[k] = 0 }) do |event, activities|
|
@activity_events = events.each_with_object(Hash.new {|h, k| h[k] = 0 }) do |event, activities|
|
||||||
|
@ -38,7 +40,7 @@ module Gitlab
|
||||||
|
|
||||||
# Use visible_to_user? instead of the complicated logic in activity_dates
|
# Use visible_to_user? instead of the complicated logic in activity_dates
|
||||||
# because we're only viewing the events for a single day.
|
# because we're only viewing the events for a single day.
|
||||||
events.select {|event| event.visible_to_user?(current_user) }
|
events.select { |event| event.visible_to_user?(current_user) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def starting_year
|
def starting_year
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
feature 'Contributions Calendar', js: true, feature: true do
|
feature 'Contributions Calendar', :feature, :js do
|
||||||
include WaitForAjax
|
include WaitForAjax
|
||||||
|
|
||||||
|
let(:user) { create(:user) }
|
||||||
let(:contributed_project) { create(:project, :public) }
|
let(:contributed_project) { create(:project, :public) }
|
||||||
|
let(:issue_note) { create(:note, project: contributed_project) }
|
||||||
|
|
||||||
# Ex/ Sunday Jan 1, 2016
|
# Ex/ Sunday Jan 1, 2016
|
||||||
date_format = '%A %b %-d, %Y'
|
date_format = '%A %b %-d, %Y'
|
||||||
|
@ -12,30 +14,30 @@ feature 'Contributions Calendar', js: true, feature: true do
|
||||||
issue_params = { title: issue_title }
|
issue_params = { title: issue_title }
|
||||||
|
|
||||||
def get_cell_color_selector(contributions)
|
def get_cell_color_selector(contributions)
|
||||||
contribution_cell = '.user-contrib-cell'
|
activity_colors = %w[#ededed #acd5f2 #7fa8c9 #527ba0 #254e77]
|
||||||
activity_colors = Array['#ededed', '#acd5f2', '#7fa8c9', '#527ba0', '#254e77']
|
# We currently don't actually test the cases with contributions >= 20
|
||||||
activity_colors_index = 0
|
activity_colors_index =
|
||||||
|
|
||||||
if contributions > 0 && contributions < 10
|
if contributions > 0 && contributions < 10
|
||||||
activity_colors_index = 1
|
1
|
||||||
elsif contributions >= 10 && contributions < 20
|
elsif contributions >= 10 && contributions < 20
|
||||||
activity_colors_index = 2
|
2
|
||||||
elsif contributions >= 20 && contributions < 30
|
elsif contributions >= 20 && contributions < 30
|
||||||
activity_colors_index = 3
|
3
|
||||||
elsif contributions >= 30
|
elsif contributions >= 30
|
||||||
activity_colors_index = 4
|
4
|
||||||
|
else
|
||||||
|
0
|
||||||
end
|
end
|
||||||
|
|
||||||
"#{contribution_cell}[fill='#{activity_colors[activity_colors_index]}']"
|
".user-contrib-cell[fill='#{activity_colors[activity_colors_index]}']"
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_cell_date_selector(contributions, date)
|
def get_cell_date_selector(contributions, date)
|
||||||
contribution_text = 'No contributions'
|
contribution_text =
|
||||||
|
if contributions.zero?
|
||||||
if contributions === 1
|
'No contributions'
|
||||||
contribution_text = '1 contribution'
|
else
|
||||||
elsif contributions > 1
|
"#{contributions} #{'contribution'.pluralize(contributions)}"
|
||||||
contribution_text = "#{contributions} contributions"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
"#{get_cell_color_selector(contributions)}[data-original-title='#{contribution_text}<br />#{date}']"
|
"#{get_cell_color_selector(contributions)}[data-original-title='#{contribution_text}<br />#{date}']"
|
||||||
|
@ -45,129 +47,155 @@ feature 'Contributions Calendar', js: true, feature: true do
|
||||||
push_params = {
|
push_params = {
|
||||||
project: contributed_project,
|
project: contributed_project,
|
||||||
action: Event::PUSHED,
|
action: Event::PUSHED,
|
||||||
author_id: @user.id,
|
author_id: user.id,
|
||||||
data: { commit_count: 3 }
|
data: { commit_count: 3 }
|
||||||
}
|
}
|
||||||
|
|
||||||
Event.create(push_params)
|
Event.create(push_params)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_first_cell_content
|
def note_comment_contribution
|
||||||
|
note_comment_params = {
|
||||||
|
project: contributed_project,
|
||||||
|
action: Event::COMMENTED,
|
||||||
|
target: issue_note,
|
||||||
|
author_id: user.id
|
||||||
|
}
|
||||||
|
|
||||||
|
Event.create(note_comment_params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def selected_day_activities
|
||||||
find('.user-calendar-activities').text
|
find('.user-calendar-activities').text
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
login_as :user
|
login_as user
|
||||||
visit @user.username
|
end
|
||||||
|
|
||||||
|
describe 'calendar day selection' do
|
||||||
|
before do
|
||||||
|
visit user.username
|
||||||
wait_for_ajax
|
wait_for_ajax
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'displays calendar', js: true do
|
it 'displays calendar' do
|
||||||
expect(page).to have_css('.js-contrib-calendar')
|
expect(page).to have_css('.js-contrib-calendar')
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'select calendar day', js: true do
|
describe 'select calendar day' do
|
||||||
let(:cells) { page.all('.user-contrib-cell') }
|
let(:cells) { page.all('.user-contrib-cell') }
|
||||||
let(:first_cell_content_before) { get_first_cell_content }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
cells[0].click
|
cells[0].click
|
||||||
wait_for_ajax
|
wait_for_ajax
|
||||||
first_cell_content_before
|
@first_day_activities = selected_day_activities
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'displays calendar day activities', js: true do
|
it 'displays calendar day activities' do
|
||||||
expect(get_first_cell_content).not_to eq('')
|
expect(selected_day_activities).not_to be_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'select another calendar day', js: true do
|
describe 'select another calendar day' do
|
||||||
before do
|
before do
|
||||||
cells[1].click
|
cells[1].click
|
||||||
wait_for_ajax
|
wait_for_ajax
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'displays different calendar day activities', js: true do
|
it 'displays different calendar day activities' do
|
||||||
expect(get_first_cell_content).not_to eq(first_cell_content_before)
|
expect(selected_day_activities).not_to eq(@first_day_activities)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'deselect calendar day', js: true do
|
describe 'deselect calendar day' do
|
||||||
before do
|
before do
|
||||||
cells[0].click
|
cells[0].click
|
||||||
wait_for_ajax
|
wait_for_ajax
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'hides calendar day activities', js: true do
|
it 'hides calendar day activities' do
|
||||||
expect(get_first_cell_content).to eq('')
|
expect(selected_day_activities).to be_empty
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '1 calendar activity' do
|
describe 'calendar daily activities' do
|
||||||
|
shared_context 'visit user page' do
|
||||||
before do
|
before do
|
||||||
Issues::CreateService.new(contributed_project, @user, issue_params).execute
|
visit user.username
|
||||||
visit @user.username
|
|
||||||
wait_for_ajax
|
wait_for_ajax
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it 'displays calendar activity log', js: true do
|
shared_examples 'a day with activity' do |contribution_count:|
|
||||||
|
include_context 'visit user page'
|
||||||
|
|
||||||
|
it 'displays calendar activity square color for 1 contribution' do
|
||||||
|
expect(page).to have_selector(get_cell_color_selector(contribution_count), count: 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'displays calendar activity square on the correct date' do
|
||||||
|
today = Date.today.strftime(date_format)
|
||||||
|
expect(page).to have_selector(get_cell_date_selector(contribution_count, today), count: 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '1 issue creation calendar activity' do
|
||||||
|
before do
|
||||||
|
Issues::CreateService.new(contributed_project, user, issue_params).execute
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'a day with activity', contribution_count: 1
|
||||||
|
|
||||||
|
describe 'issue title is shown on activity page' do
|
||||||
|
include_context 'visit user page'
|
||||||
|
|
||||||
|
it 'displays calendar activity log' do
|
||||||
expect(find('.content_list .event-note')).to have_content issue_title
|
expect(find('.content_list .event-note')).to have_content issue_title
|
||||||
end
|
end
|
||||||
|
end
|
||||||
it 'displays calendar activity square color for 1 contribution', js: true do
|
|
||||||
expect(page).to have_selector(get_cell_color_selector(1), count: 1)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'displays calendar activity square on the correct date', js: true do
|
describe '1 comment calendar activity' do
|
||||||
today = Date.today.strftime(date_format)
|
before do
|
||||||
expect(page).to have_selector(get_cell_date_selector(1, today), count: 1)
|
note_comment_contribution
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'a day with activity', contribution_count: 1
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '10 calendar activities' do
|
describe '10 calendar activities' do
|
||||||
before do
|
before do
|
||||||
(0..9).each do |i|
|
10.times { push_code_contribution }
|
||||||
push_code_contribution()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
visit @user.username
|
it_behaves_like 'a day with activity', contribution_count: 10
|
||||||
wait_for_ajax
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'displays calendar activity square color for 10 contributions', js: true do
|
|
||||||
expect(page).to have_selector(get_cell_color_selector(10), count: 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'displays calendar activity square on the correct date', js: true do
|
|
||||||
today = Date.today.strftime(date_format)
|
|
||||||
expect(page).to have_selector(get_cell_date_selector(10, today), count: 1)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'calendar activity on two days' do
|
describe 'calendar activity on two days' do
|
||||||
before do
|
before do
|
||||||
push_code_contribution()
|
push_code_contribution
|
||||||
|
|
||||||
Timecop.freeze(Date.yesterday)
|
Timecop.freeze(Date.yesterday) do
|
||||||
Issues::CreateService.new(contributed_project, @user, issue_params).execute
|
Issues::CreateService.new(contributed_project, user, issue_params).execute
|
||||||
Timecop.return
|
|
||||||
|
|
||||||
visit @user.username
|
|
||||||
wait_for_ajax
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
include_context 'visit user page'
|
||||||
|
|
||||||
it 'displays calendar activity squares for both days', js: true do
|
it 'displays calendar activity squares for both days' do
|
||||||
expect(page).to have_selector(get_cell_color_selector(1), count: 2)
|
expect(page).to have_selector(get_cell_color_selector(1), count: 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'displays calendar activity square for yesterday', js: true do
|
it 'displays calendar activity square for yesterday' do
|
||||||
yesterday = Date.yesterday.strftime(date_format)
|
yesterday = Date.yesterday.strftime(date_format)
|
||||||
expect(page).to have_selector(get_cell_date_selector(1, yesterday), count: 1)
|
expect(page).to have_selector(get_cell_date_selector(1, yesterday), count: 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'displays calendar activity square for today', js: true do
|
it 'displays calendar activity square for today' do
|
||||||
today = Date.today.strftime(date_format)
|
today = Date.today.strftime(date_format)
|
||||||
expect(page).to have_selector(get_cell_date_selector(1, today), count: 1)
|
expect(page).to have_selector(get_cell_date_selector(1, today), count: 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue