Browse files

version 0.0.2

  • Loading branch information...
0 parents commit 9a7b6ad5872cadea8e75f90746e08d7b76d93427 unknown committed Apr 29, 2009
3 README.rdoc
@@ -0,0 +1,3 @@
+= vote
+
+Description goes here
15 app/controllers/issues_controller.rb
@@ -0,0 +1,15 @@
+require 'redmine'
+require_dependency 'issues_controller'
+
+class IssuesController < ApplicationController
+ skip_before_filter :authorize, :only => [:vote]
+ #before_filter :find_issue, :only => [:vote] #[:show, :edit, :reply]
+ #before_filter :authorize, :only => [:vote] #:except => [:index, :changes, :gantt, :calendar, :preview, :update_form, :context_menu]
+ def vote
+ find_issue
+ authorize
+ @issue.vote(params[:vote] == "up" ? :up : :down)
+ @issue.save
+ redirect_to :controller => 'issues', :action => 'show', :id => @issue
+ end
+end
12 app/models/vote.rb
@@ -0,0 +1,12 @@
+class Vote < ActiveRecord::Base
+
+ # NOTE: Votes belong to a user
+ belongs_to :user
+ belongs_to :voteable, :polymorphic => true
+ def self.find_votes_cast_by_user(user)
+ find(:all,
+ :conditions => ["user_id = ?", user.id],
+ :order => "created_at DESC"
+ )
+ end
+end
BIN assets/images/arrow_090.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN assets/images/arrow_090_small.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN assets/images/arrow_270.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN assets/images/arrow_270_small.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN assets/images/auction_hammer__minus.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN assets/images/auction_hammer__plus.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN assets/images/light_bulb.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN assets/images/light_bulb__minus.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN assets/images/light_bulb__plus.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN assets/images/light_bulb_off.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 assets/stylesheets/stylesheet.css
@@ -0,0 +1,4 @@
+.icon-vote-up { background-image: url(../images/arrow_090.png); }
+.icon-vote-down { background-image: url(../images/arrow_270.png); }
+span.votes-positive { color: green; font-weight: bold }
+span.votes-negative { color: red; font-weight: bold }
6 config/locales/en.yml
@@ -0,0 +1,6 @@
+# English strings go here
+en:
+ button_vote_up: up
+ button_vote_down: down
+ label_votes: Votes
+ field_votes_value: Votes
6 config/locales/ru.yml
@@ -0,0 +1,6 @@
+# Russian strings go here
+ru:
+ button_vote_up: вверх
+ button_vote_down: вниз
+ label_votes: Голоса
+ field_votes_value: Голоса
18 db/migrate/001_votes_table_create.rb
@@ -0,0 +1,18 @@
+class VotesTableCreate < ActiveRecord::Migration
+ def self.up
+ create_table :votes, :force => true do |t|
+ t.column :vote, :boolean, :default => false
+ t.column :created_at, :datetime, :null => false
+ t.column :voteable_type, :string, :default => "", :null => false
+ t.column :voteable_id, :integer, :default => 0, :null => false
+ t.column :user_id, :integer, :default => 0, :null => false
+ end
+
+ add_index :votes, [:user_id], :name => "fk_votes_user"
+ add_index :votes, [:voteable_id, :voteable_type], :name => "fk_votes_voteable"
+ end
+
+ def self.down
+ drop_table :votes
+ end
+end
9 db/migrate/002_issues_add_votes_value.rb
@@ -0,0 +1,9 @@
+class IssuesAddVotesValue < ActiveRecord::Migration
+ def self.up
+ add_column :issues, :votes_value, :integer, :default => 0, :null => false
+ end
+
+ def self.down
+ remove_column :issues, :votes_value
+ end
+end
18 init.rb
@@ -0,0 +1,18 @@
+require 'redmine'
+require 'issue_vote_patch'
+require 'query_vote_patch'
+require_dependency 'issues_vote_hook'
+
+Redmine::Plugin.register :redmine_vote do
+ name 'Redmine Vote plugin'
+ author 'Andrew Chaika'
+ description 'This is a plugin for Redmine'
+ version '0.0.2'
+ project_module :issue_tracking do
+ permission :issues_vote, {:issues => :vote}, :require => :loggedin
+ end
+end
+
+class RedmineVoteListener < Redmine::Hook::ViewListener
+ render_on :view_layouts_base_html_head, :inline => "<%= stylesheet_link_tag 'stylesheet', :plugin => 'redmine_vote' %>"
+end
4 lang/en.yml
@@ -0,0 +1,4 @@
+# English strings go here
+my_label: "My label"
+button_vote_up: up
+button_vote_up: down
70 lib/acts_as_voteable.rb
@@ -0,0 +1,70 @@
+# ActsAsVoteable
+module Juixe
+ module Acts #:nodoc:
+ module Voteable #:nodoc:
+
+ def self.included(base)
+ base.extend ClassMethods
+ end
+
+ module ClassMethods
+ def acts_as_voteable
+ has_many :votes, :as => :voteable, :dependent => :delete_all
+ include Juixe::Acts::Voteable::InstanceMethods
+ extend Juixe::Acts::Voteable::SingletonMethods
+ end
+ end
+
+ # This module contains class methods
+ module SingletonMethods
+ def find_votes_cast_by_user(user=User.current)
+ voteable = ActiveRecord::Base.send(:class_name_of_active_record_descendant, self).to_s
+ Vote.find(:all,
+ :conditions => ["user_id = ? and voteable_type = ?", user.id, voteable],
+ :order => "created_at DESC"
+ )
+ end
+ end
+
+ # This module contains instance methods
+ module InstanceMethods
+ def vote( vote=:up, user=User.current )
+ return if voted_by_user? user
+ Vote.create( :voteable => self, :vote => vote == :up, :user => user )
+ self.votes_value += vote == :up ? 1:-1;
+ end
+ def votes_for
+ self.votes.select{|v| v.vote}.size
+ end
+
+ def votes_against
+ self.votes.select{|v| !v.vote}.size
+ end
+
+ def votes_count
+ self.votes.size
+ end
+
+ def users_who_voted
+ users = []
+ self.votes.each { |v|
+ users << v.user
+ }
+ users
+ end
+
+ def voted_by_user?(user=User.current)
+ rtn = false
+ if user
+ self.votes.each { |v|
+ rtn = true if user.id == v.user_id
+ }
+ end
+ rtn
+ end
+ end
+ end
+ end
+end
+
+ActiveRecord::Base.send :include, Juixe::Acts::Voteable #:nodoc:
6 lib/issue_vote_patch.rb
@@ -0,0 +1,6 @@
+require 'vote'
+require 'acts_as_voteable'
+
+Issue.class_eval do
+ acts_as_voteable
+end
14 lib/issues_vote_hook.rb
@@ -0,0 +1,14 @@
+# Provides a link to the issue age graph on the issue index page
+class IssuesVoteHook < Redmine::Hook::ViewListener
+ render_on :view_issues_show_details_bottom, :inline => <<-END
+ <tr><td><b><%= l :label_votes %>:</b></td><td>
+ <% vv = @issue.votes_value %>
+ <%= content_tag('span', vv, :class => (vv > 0? 'votes-positive': ( vv < 0 ? 'votes-negative' : ''))) %>
+ <% @project = @issue.project %>
+ <% if authorize_for('issues', 'vote') && !@issue.voted_by_user? %>
+ <%= link_to("", {:controller => 'issues', :action => 'vote', :id => @issue, :vote => :up}, :class => 'icon icon-vote-up') %>
+ <%= link_to("", {:controller => 'issues', :action => 'vote', :id => @issue, :vote => :down}, :class => 'icon icon-vote-down') %>
+ <% end %>
+ </td></tr>
+END
+end
11 lib/query_vote_patch.rb
@@ -0,0 +1,11 @@
+require_dependency 'query'
+
+module QueryVotePatch
+ def self.included(base)
+ base.class_eval <<-END
+ @@available_columns += [QueryColumn.new(:votes_value, :sortable => "#{Issue.table_name}.votes_value")]
+END
+ end
+end
+
+Query.send :include, QueryVotePatch
5 test/test_helper.rb
@@ -0,0 +1,5 @@
+# Load the normal Rails helper
+require File.expand_path(File.dirname(__FILE__) + '/../../../../test/test_helper')
+
+# Ensure that we are using the temporary fixture path
+Engines::Testing.set_fixture_path

0 comments on commit 9a7b6ad

Please sign in to comment.