Permalink
Browse files

version 0.0.2

  • Loading branch information...
0 parents commit 9a7b6ad5872cadea8e75f90746e08d7b76d93427 unknown committed Apr 29, 2009
@@ -0,0 +1,3 @@
+= vote
+
+Description goes here
@@ -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
@@ -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
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -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 }
@@ -0,0 +1,6 @@
+# English strings go here
+en:
+ button_vote_up: up
+ button_vote_down: down
+ label_votes: Votes
+ field_votes_value: Votes
@@ -0,0 +1,6 @@
+# Russian strings go here
+ru:
+ button_vote_up: вверх
+ button_vote_down: вниз
+ label_votes: Голоса
+ field_votes_value: Голоса
@@ -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
@@ -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
@@ -0,0 +1,4 @@
+# English strings go here
+my_label: "My label"
+button_vote_up: up
+button_vote_up: down
@@ -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:
@@ -0,0 +1,6 @@
+require 'vote'
+require 'acts_as_voteable'
+
+Issue.class_eval do
+ acts_as_voteable
+end
@@ -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
@@ -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
@@ -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.