Merge pull request #1409 from riyad/update-votes

Update votes for issues and merge requests
This commit is contained in:
Dmitriy Zaporozhets 2012-09-11 23:08:19 -07:00
commit 40eec08c99
17 changed files with 256 additions and 66 deletions

View file

@ -415,13 +415,48 @@ p.time {
}
}
.upvotes {
font-size: 14px;
font-weight: bold;
color: #468847;
text-align: right;
padding: 4px;
margin: 2px;
.votes {
font-size: 13px;
line-height: 15px;
.progress {
height: 4px;
margin: 0;
.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) */

View file

@ -1,6 +1,6 @@
class Issue < ActiveRecord::Base
include IssueCommonality
include Upvote
include Votes
acts_as_taggable_on :labels

View file

@ -2,7 +2,7 @@ require File.join(Rails.root, "app/models/commit")
class MergeRequest < ActiveRecord::Base
include IssueCommonality
include Upvote
include Votes
BROKEN_DIFF = "--broken-diff"

View file

@ -105,6 +105,12 @@ class Note < ActiveRecord::Base
def upvote?
note.start_with?('+1') || note.start_with?(':+1:')
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
# == Schema Information
#

View file

@ -1,6 +0,0 @@
module Upvote
# Return the number of +1 comments (upvotes)
def upvotes
notes.select(&:upvote?).size
end
end

32
app/roles/votes.rb Normal file
View file

@ -0,0 +1,32 @@
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

View file

@ -34,5 +34,5 @@
- else
&nbsp;
- if issue.upvotes > 0
%span.badge.badge-success= "+#{issue.upvotes}"
- if issue.votes_count > 0
= render 'votes/votes_inline', votable: issue

View file

@ -8,22 +8,22 @@
%span.right
- if can?(current_user, :admin_project, @project) || @issue.author == current_user
- 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
= 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
= 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
Edit
%br
- if @issue.upvotes > 0
.upvotes#upvotes= "+#{pluralize @issue.upvotes, 'upvote'}"
.right
.span3#votes= render 'votes/votes_block', votable: @issue
.back_link
= link_to project_issues_path(@project) do
&larr; To issues list
.main_box
.top_box_content
%h4

View file

@ -23,5 +23,6 @@
authored by #{merge_request.author_name}
= time_ago_in_words(merge_request.created_at)
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

View file

@ -23,10 +23,8 @@
%i.icon-edit
Edit
%br
- if @merge_request.upvotes > 0
.upvotes#upvotes= "+#{pluralize @merge_request.upvotes, 'upvote'}"
.right
.span3#votes= render 'votes/votes_block', votable: @merge_request
.back_link
= link_to project_merge_requests_path(@project) do

View file

@ -0,0 +1,6 @@
.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"

View file

@ -0,0 +1,6 @@
.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

View file

@ -12,7 +12,7 @@ describe Issue do
describe 'modules' do
it { should include_module(IssueCommonality) }
it { should include_module(Upvote) }
it { should include_module(Votes) }
end
subject { Factory.create(:issue) }

View file

@ -8,6 +8,6 @@ describe MergeRequest do
describe 'modules' do
it { should include_module(IssueCommonality) }
it { should include_module(Upvote) }
it { should include_module(Votes) }
end
end

View file

@ -24,6 +24,13 @@ describe Note do
it "recognizes a neutral note" do
note = Factory(:note, note: "This is not a +1 note")
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
it "recognizes a +1 note" do
@ -31,19 +38,19 @@ describe Note do
note.should be_upvote
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
note = build(:note, note: ":+1: for this")
note.should be_upvote
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
it "recognizes a -1 note" do
note = Factory(:note, note: "-1 for this")
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

View file

@ -1,27 +0,0 @@
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

132
spec/roles/votes_spec.rb Normal file
View file

@ -0,0 +1,132 @@
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