Commit 40eec08c authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge pull request #1409 from riyad/update-votes

Update votes for issues and merge requests
parents d8f6d38d 0bfcc574
...@@ -415,13 +415,48 @@ p.time { ...@@ -415,13 +415,48 @@ p.time {
} }
} }
.upvotes { .votes {
font-size: 14px; font-size: 13px;
font-weight: bold; line-height: 15px;
color: #468847; .progress {
text-align: right; height: 4px;
padding: 4px; margin: 0;
margin: 2px; .bar {
float: left;
height: 100%;
}
.bar-success {
background-color: #468847;
@include bg-gradient(#62C462, #51A351);
}
.bar-danger {
background-color: #B94A48;
@include bg-gradient(#EE5F5B, #BD362F);
}
}
.upvotes {
display: inline-block;
color: #468847;
}
.downvotes {
display: inline-block;
color: #B94A48;
}
}
.votes-block {
margin: 14px 6px 6px 0;
.downvotes {
float: right;
}
}
.votes-inline {
display: inline-block;
margin: 0 8px;
.progress {
display: inline-block;
padding: 0 0 2px;
width: 45px;
}
} }
/* Fix for readme code (stopped it from being yellow) */ /* Fix for readme code (stopped it from being yellow) */
......
class Issue < ActiveRecord::Base class Issue < ActiveRecord::Base
include IssueCommonality include IssueCommonality
include Upvote include Votes
acts_as_taggable_on :labels acts_as_taggable_on :labels
......
...@@ -2,7 +2,7 @@ require File.join(Rails.root, "app/models/commit") ...@@ -2,7 +2,7 @@ require File.join(Rails.root, "app/models/commit")
class MergeRequest < ActiveRecord::Base class MergeRequest < ActiveRecord::Base
include IssueCommonality include IssueCommonality
include Upvote include Votes
BROKEN_DIFF = "--broken-diff" BROKEN_DIFF = "--broken-diff"
......
...@@ -105,6 +105,12 @@ class Note < ActiveRecord::Base ...@@ -105,6 +105,12 @@ class Note < ActiveRecord::Base
def upvote? def upvote?
note.start_with?('+1') || note.start_with?(':+1:') note.start_with?('+1') || note.start_with?(':+1:')
end end
# Returns true if this is a downvote note,
# otherwise false is returned
def downvote?
note.start_with?('-1') || note.start_with?(':-1:')
end
end end
# == Schema Information # == Schema Information
# #
......
module Upvote
# Return the number of +1 comments (upvotes)
def upvotes
notes.select(&:upvote?).size
end
end
module Votes
# Return the number of +1 comments (upvotes)
def upvotes
notes.select(&:upvote?).size
end
def upvotes_in_percent
if votes_count.zero?
0
else
100.0 / votes_count * upvotes
end
end
# Return the number of -1 comments (downvotes)
def downvotes
notes.select(&:downvote?).size
end
def downvotes_in_percent
if votes_count.zero?
0
else
100.0 - upvotes_in_percent
end
end
# Return the total number of votes
def votes_count
upvotes + downvotes
end
end
...@@ -34,5 +34,5 @@ ...@@ -34,5 +34,5 @@
- else - else
&nbsp; &nbsp;
- if issue.upvotes > 0 - if issue.votes_count > 0
%span.badge.badge-success= "+#{issue.upvotes}" = render 'votes/votes_inline', votable: issue
...@@ -8,22 +8,22 @@ ...@@ -8,22 +8,22 @@
%span.right %span.right
- if can?(current_user, :admin_project, @project) || @issue.author == current_user - if can?(current_user, :admin_project, @project) || @issue.author == current_user
- if @issue.closed - if @issue.closed
= link_to 'Reopen', project_issue_path(@project, @issue, issue: {closed: false }, status_only: true), method: :put, class: "btn small" = link_to 'Reopen', project_issue_path(@project, @issue, issue: {closed: false }, status_only: true), method: :put, class: "btn grouped success"
- else - else
= link_to 'Close', project_issue_path(@project, @issue, issue: {closed: true }, status_only: true), method: :put, class: "btn small", title: "Close Issue" = link_to 'Close', project_issue_path(@project, @issue, issue: {closed: true }, status_only: true), method: :put, class: "btn grouped danger", title: "Close Issue"
- if can?(current_user, :admin_project, @project) || @issue.author == current_user - if can?(current_user, :admin_project, @project) || @issue.author == current_user
= link_to edit_project_issue_path(@project, @issue), class: "btn small" do = link_to edit_project_issue_path(@project, @issue), class: "btn grouped" do
%i.icon-edit %i.icon-edit
Edit Edit
%br .right
- if @issue.upvotes > 0 .span3#votes= render 'votes/votes_block', votable: @issue
.upvotes#upvotes= "+#{pluralize @issue.upvotes, 'upvote'}"
.back_link .back_link
= link_to project_issues_path(@project) do = link_to project_issues_path(@project) do
&larr; To issues list &larr; To issues list
.main_box .main_box
.top_box_content .top_box_content
%h4 %h4
......
...@@ -23,5 +23,6 @@ ...@@ -23,5 +23,6 @@
authored by #{merge_request.author_name} authored by #{merge_request.author_name}
= time_ago_in_words(merge_request.created_at) = time_ago_in_words(merge_request.created_at)
ago ago
- if merge_request.upvotes > 0
%span.badge.badge-success= "+#{merge_request.upvotes}" - if merge_request.votes_count > 0
= render 'votes/votes_inline', votable: merge_request
...@@ -23,10 +23,8 @@ ...@@ -23,10 +23,8 @@
%i.icon-edit %i.icon-edit
Edit Edit
%br .right
- if @merge_request.upvotes > 0 .span3#votes= render 'votes/votes_block', votable: @merge_request
.upvotes#upvotes= "+#{pluralize @merge_request.upvotes, 'upvote'}"
.back_link .back_link
= link_to project_merge_requests_path(@project) do = link_to project_merge_requests_path(@project) do
......
.votes.votes-block
.progress
.bar.bar-success{style: "width: #{votable.upvotes_in_percent}%;"}
.bar.bar-danger{style: "width: #{votable.downvotes_in_percent}%;"}
.upvotes= "#{votable.upvotes} up"
.downvotes= "#{votable.downvotes} down"
.votes.votes-inline
.upvotes= votable.upvotes
.progress
.bar.bar-success{style: "width: #{votable.upvotes_in_percent}%;"}
.bar.bar-danger{style: "width: #{votable.downvotes_in_percent}%;"}
.downvotes= votable.downvotes
...@@ -12,7 +12,7 @@ describe Issue do ...@@ -12,7 +12,7 @@ describe Issue do
describe 'modules' do describe 'modules' do
it { should include_module(IssueCommonality) } it { should include_module(IssueCommonality) }
it { should include_module(Upvote) } it { should include_module(Votes) }
end end
subject { Factory.create(:issue) } subject { Factory.create(:issue) }
......
...@@ -8,6 +8,6 @@ describe MergeRequest do ...@@ -8,6 +8,6 @@ describe MergeRequest do
describe 'modules' do describe 'modules' do
it { should include_module(IssueCommonality) } it { should include_module(IssueCommonality) }
it { should include_module(Upvote) } it { should include_module(Votes) }
end end
end end
...@@ -24,6 +24,13 @@ describe Note do ...@@ -24,6 +24,13 @@ describe Note do
it "recognizes a neutral note" do it "recognizes a neutral note" do
note = Factory(:note, note: "This is not a +1 note") note = Factory(:note, note: "This is not a +1 note")
note.should_not be_upvote note.should_not be_upvote
note.should_not be_downvote
end
it "recognizes a neutral emoji note" do
note = build(:note, note: "I would :+1: this, but I don't want to")
note.should_not be_upvote
note.should_not be_downvote
end end
it "recognizes a +1 note" do it "recognizes a +1 note" do
...@@ -31,19 +38,19 @@ describe Note do ...@@ -31,19 +38,19 @@ describe Note do
note.should be_upvote note.should be_upvote
end end
it "recognizes a -1 note as no vote" do
note = Factory(:note, note: "-1 for this")
note.should_not be_upvote
end
it "recognizes a +1 emoji as a vote" do it "recognizes a +1 emoji as a vote" do
note = build(:note, note: ":+1: for this") note = build(:note, note: ":+1: for this")
note.should be_upvote note.should be_upvote
end end
it "recognizes a neutral emoji note" do it "recognizes a -1 note" do
note = build(:note, note: "I would :+1: this, but I don't want to") note = Factory(:note, note: "-1 for this")
note.should_not be_upvote note.should be_downvote
end
it "recognizes a -1 emoji as a vote" do
note = build(:note, note: ":-1: for this")
note.should be_downvote
end end
end end
......
require 'spec_helper'
describe Issue, "Upvote" do
let(:issue) { create(:issue) }
it "with no notes has a 0/0 score" do
issue.upvotes.should == 0
end
it "should recognize non-+1 notes" do
issue.notes << create(:note, note: "No +1 here")
issue.should have(1).note
issue.notes.first.upvote?.should be_false
issue.upvotes.should == 0
end
it "should recognize a single +1 note" do
issue.notes << create(:note, note: "+1 This is awesome")
issue.upvotes.should == 1
end
it "should recognize multiple +1 notes" do
issue.notes << create(:note, note: "+1 This is awesome")
issue.notes << create(:note, note: "+1 I want this")
issue.upvotes.should == 2
end
end
require 'spec_helper'
describe Issue do
let(:issue) { create(:issue) }
describe "#upvotes" do
it "with no notes has a 0/0 score" do
issue.upvotes.should == 0
end
it "should recognize non-+1 notes" do
issue.notes << create(:note, note: "No +1 here")
issue.should have(1).note
issue.notes.first.upvote?.should be_false
issue.upvotes.should == 0
end
it "should recognize a single +1 note" do
issue.notes << create(:note, note: "+1 This is awesome")
issue.upvotes.should == 1
end
it "should recognize multiple +1 notes" do
issue.notes << create(:note, note: "+1 This is awesome")
issue.notes << create(:note, note: "+1 I want this")
issue.upvotes.should == 2
end
end
describe "#downvotes" do
it "with no notes has a 0/0 score" do
issue.downvotes.should == 0
end
it "should recognize non--1 notes" do
issue.notes << create(:note, note: "Almost got a -1")
issue.should have(1).note
issue.notes.first.downvote?.should be_false
issue.downvotes.should == 0
end
it "should recognize a single -1 note" do
issue.notes << create(:note, note: "-1 This is bad")
issue.downvotes.should == 1
end
it "should recognize multiple -1 notes" do
issue.notes << create(:note, note: "-1 This is bad")
issue.notes << create(:note, note: "-1 Away with this")
issue.downvotes.should == 2
end
end
describe "#votes_count" do
it "with no notes has a 0/0 score" do
issue.votes_count.should == 0
end
it "should recognize non notes" do
issue.notes << create(:note, note: "No +1 here")
issue.should have(1).note
issue.votes_count.should == 0
end
it "should recognize a single +1 note" do
issue.notes << create(:note, note: "+1 This is awesome")
issue.votes_count.should == 1
end
it "should recognize a single -1 note" do
issue.notes << create(:note, note: "-1 This is bad")
issue.votes_count.should == 1
end
it "should recognize multiple notes" do
issue.notes << create(:note, note: "+1 This is awesome")
issue.notes << create(:note, note: "-1 This is bad")
issue.notes << create(:note, note: "+1 I want this")
issue.votes_count.should == 3
end
end
describe "#upvotes_in_percent" do
it "with no notes has a 0% score" do
issue.upvotes_in_percent.should == 0
end
it "should count a single 1 note as 100%" do
issue.notes << create(:note, note: "+1 This is awesome")
issue.upvotes_in_percent.should == 100
end
it "should count multiple +1 notes as 100%" do
issue.notes << create(:note, note: "+1 This is awesome")
issue.notes << create(:note, note: "+1 I want this")
issue.upvotes_in_percent.should == 100
end
it "should count fractions for multiple +1 and -1 notes correctly" do
issue.notes << create(:note, note: "+1 This is awesome")
issue.notes << create(:note, note: "+1 I want this")
issue.notes << create(:note, note: "-1 This is bad")
issue.notes << create(:note, note: "+1 me too")
issue.upvotes_in_percent.should == 75
end
end
describe "#downvotes_in_percent" do
it "with no notes has a 0% score" do
issue.downvotes_in_percent.should == 0
end
it "should count a single -1 note as 100%" do
issue.notes << create(:note, note: "-1 This is bad")
issue.downvotes_in_percent.should == 100
end
it "should count multiple -1 notes as 100%" do
issue.notes << create(:note, note: "-1 This is bad")
issue.notes << create(:note, note: "-1 Away with this")
issue.downvotes_in_percent.should == 100
end
it "should count fractions for multiple +1 and -1 notes correctly" do
issue.notes << create(:note, note: "+1 This is awesome")
issue.notes << create(:note, note: "+1 I want this")
issue.notes << create(:note, note: "-1 This is bad")
issue.notes << create(:note, note: "+1 me too")
issue.downvotes_in_percent.should == 25
end
end
end
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