diff --git a/README.rdoc b/README.rdoc index ad15379..1c63adb 100644 --- a/README.rdoc +++ b/README.rdoc @@ -2,32 +2,32 @@ A plugin for Redmine[www.redmine.org] which allows users to up- or down-vote issues. -Current version: 1.0.2 +Current version: 1.0.3 Developed on Redmine 3.3.2 == Usage * Install plugin - + * Download latest release[https://github.com/ojde/redmine-vote_on_issues-plugin/releases] - + * Extract into Redmine's plugin directory /plugins - + * Rename the redmine-vote_on_issues-plugin-x.y.z directory to vote_on_issues - + * Restart Redmine - + * Enable for project * Enable permissions for roles (minimum requirement is always the user being logged in) - + * "Vote on issue": Up- or down-vote on issues; change own votes or withdraw them. See own votes. * "View votes": See the total number of votes on an issue. - + * "View voters": See who voted how on an issue. There are Up- and down-votes columns available for the issue listing. diff --git a/app/controllers/vote_on_issues_controller.rb b/app/controllers/vote_on_issues_controller.rb index f2a6674..bacd9d4 100644 --- a/app/controllers/vote_on_issues_controller.rb +++ b/app/controllers/vote_on_issues_controller.rb @@ -1,13 +1,12 @@ class VoteOnIssuesController < ApplicationController # respond_to :html, :js - unloadable #Authorize against global permissions defined in init.rb # ?? does prevent everythin below admin? # TODO - find out how this works - #before_filter :authorize_global - #before_filter :authorize - + #before_action :authorize_global + #before_action :authorize + def index @project = Project.find(params[:project_id]) @votes = VoteOnIssue.all @@ -22,16 +21,17 @@ def cast_vote elsif 'nil' == params[:vote_val] @iMyVote = 0; end - - begin - @vote = VoteOnIssue.find_by!("issue_id = ? AND user_id = ?", params[:issue_id], User.current.id) + + @vote = VoteOnIssue.where(issue_id: params[:issue_id]).where(user_id: User.current.id).first + + if @vote if 0 != @iMyVote @vote.vote_val = @iMyVote @vote.save else @vote.destroy end - rescue ActiveRecord::RecordNotFound + else if 0 != @iMyVote @vote = VoteOnIssue.new @vote.user_id = User.current.id @@ -40,15 +40,15 @@ def cast_vote @vote.save end end - + @nVotesUp = VoteOnIssue.getUpVoteCountOnIssue(params[:issue_id]) @nVotesDn = VoteOnIssue.getDnVoteCountOnIssue(params[:issue_id]) @issue = Issue.find(params[:issue_id]) - + # Auto loads /app/views/vote_on_issues/cast_vote.js.erb end - + def show_voters @issue = Issue.find(params[:issue_id]) @UpVotes = VoteOnIssue.getListOfUpVotersOnIssue(params[:issue_id]) diff --git a/app/helpers/vote_on_issues_helper.rb b/app/helpers/vote_on_issues_helper.rb deleted file mode 100644 index 22fadf5..0000000 --- a/app/helpers/vote_on_issues_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module VoteOnIssuesHelper -end diff --git a/app/models/voi_query_column.rb b/app/models/voi_query_column.rb new file mode 100644 index 0000000..e2a1e95 --- /dev/null +++ b/app/models/voi_query_column.rb @@ -0,0 +1,11 @@ +require 'query' + +class VoiQueryColumn < QueryColumn + def value(object) + object.send name, object + end + + def value_object(object) + object.send name, object + end +end diff --git a/app/models/vote_on_issue.rb b/app/models/vote_on_issue.rb index 33d8e74..267cef8 100644 --- a/app/models/vote_on_issue.rb +++ b/app/models/vote_on_issue.rb @@ -1,44 +1,33 @@ class VoteOnIssue < ActiveRecord::Base - unloadable - # Every vote belongs to a user and an issue belongs_to :user belongs_to :issue - + + scope :up_vote, lambda { where('vote_val > 0') } + scope :down_vote, lambda { where('vote_val < 0') } + def self.getMyVote(issue) iRet = 0 begin - @vote = VoteOnIssue.find_by!("issue_id = ? AND user_id = ?", issue.id, User.current.id) - iRet = @vote.vote_val - rescue ActiveRecord::RecordNotFound - iRet = 0 + @vote = where(issue_id: issue.id).where(user_id: User.current.id).first + iRet = @vote.vote_val if @vote end iRet end - + def self.getUpVoteCountOnIssue(issue_id) - where("issue_id = ? AND vote_val > 0", issue_id).count + where(issue_id: issue_id).up_vote.count end - + def self.getDnVoteCountOnIssue(issue_id) - where("issue_id = ? AND vote_val < 0", issue_id).count + where(issue_id: issue_id).down_vote.count end def self.getListOfUpVotersOnIssue(issue_id) - # this does load the users, but costly: One query for each user - # where("issue_id = ? AND vote_val > 0", issue_id) - # this does load the users, less costly: One query for all users - # includes(:user).where("issue_id = ? AND vote_val > 0", issue_id) - # where("issue_id = ? AND vote_val > 0", issue_id).includes(:user) - # joins users successfully, but still execs one query for each user - # where("issue_id = ? AND vote_val > 0", issue_id).joins(:user) - # This does what I want, but I'd love to find out how to do this in rails... - find_by_sql( ["SELECT `vote_on_issues`.`vote_val` AS vote_val, `users`.`login` AS user_login FROM `vote_on_issues` LEFT JOIN `users` ON (`users`.`id` = `vote_on_issues`.`user_id`) WHERE (`issue_id` = ? AND `vote_val` > 0) ORDER BY user_login ASC", issue_id] ) + where(issue_id: issue_id).up_vote.joins(:user).order('users.login ASC').pluck(:vote_val, 'users.login') end - + def self.getListOfDnVotersOnIssue(issue_id) - # see getListOfUpVotersOnIssue - find_by_sql( ["SELECT `vote_on_issues`.`vote_val` AS vote_val, `users`.`login` AS user_login FROM `vote_on_issues` LEFT JOIN `users` ON (`users`.`id` = `vote_on_issues`.`user_id`) WHERE (`issue_id` = ? AND `vote_val` < 0) ORDER BY user_login ASC", issue_id] ) + where(issue_id: issue_id).down_vote.joins(:user).order('users.login ASC').pluck(:vote_val, 'users.login') end - end diff --git a/app/views/issues/_my_votes.html.erb b/app/views/issues/_my_votes.html.erb new file mode 100644 index 0000000..f6b2482 --- /dev/null +++ b/app/views/issues/_my_votes.html.erb @@ -0,0 +1,18 @@ +
+
+ + <%= image_tag('arrow-u-r-green.png', :id => 'vote_on_issues_MyVoteUpOn', :style => 'display:none', :class => 'vote_on_issues-icon-vote', :plugin => 'vote_on_issues') %> + <%= image_tag('arrow-d-r-red.png', :id => 'vote_on_issues_MyVoteDnOn', :style => 'display:none', :class => 'vote_on_issues-icon-vote', :plugin => 'vote_on_issues') %> +
+ +
+   <%= l(:view_issues_my_vote_opt) %>: + <%= link_to(image_tag('arrow-u-r-blank.png', :id => 'vote_on_issues_MyVoteUpOff', :style => 'display:none', :class => 'vote_on_issues-icon-vote', :plugin => 'vote_on_issues'), {:controller => 'vote_on_issues', :action => 'cast_vote', :issue_id => @issue, :vote_val => 'vup' }, remote: true, :class => 'vote_on_issues-icon-vote', :title => l(:view_issues_my_vote_opt_up) ) %> + <%= link_to(image_tag('arrow-d-r-blank.png', :id => 'vote_on_issues_MyVoteDnOff', :style => 'display:none', :class => 'vote_on_issues-icon-vote', :plugin => 'vote_on_issues'), {:controller => 'vote_on_issues', :action => 'cast_vote', :issue_id => @issue, :vote_val => 'vdn' }, remote: true, :class => 'vote_on_issues-icon-vote', :title => l(:view_issues_my_vote_opt_dn) ) %> + <%= link_to(image_tag('delete-black.png', :id => 'vote_on_issues_MyVoteDelete', :style => 'display:none', :class => 'vote_on_issues-icon-vote', :plugin => 'vote_on_issues'), {:controller => 'vote_on_issues', :action => 'cast_vote', :issue_id => @issue, :vote_val => 'nil' }, remote: true, :class => 'vote_on_issues-icon-vote', :title => l(:view_issues_my_vote_opt_nil) ) %> +
+ + +
\ No newline at end of file diff --git a/app/views/issues/_show_details_bottom.erb b/app/views/issues/_show_details_bottom.erb new file mode 100644 index 0000000..4d00533 --- /dev/null +++ b/app/views/issues/_show_details_bottom.erb @@ -0,0 +1,14 @@ +<% if @project.module_enabled?(:vote_on_issues) %> + + <%= issue_fields_rows do |rows| %> +<% + if authorize_for('issues', 'view_votes') + rows.left l(:view_issues_label_votes), render(partial: 'issues/votes') + end + + if authorize_for('issues', 'cast_vote') + rows.right l(:view_issues_my_vote), render(partial: 'issues/my_votes') + end +%> + <% end %> +<% end %> \ No newline at end of file diff --git a/app/views/issues/_votes.html.erb b/app/views/issues/_votes.html.erb new file mode 100644 index 0000000..9db0ace --- /dev/null +++ b/app/views/issues/_votes.html.erb @@ -0,0 +1,33 @@ +
+
+ <%= image_tag 'arrow-u-r-green.png', :class => 'vote_on_issues-icon-votes', :plugin => 'vote_on_issues' %> +
+
+ <%= image_tag 'arrow-d-r-red.png', :class => 'vote_on_issues-icon-votes', :plugin => 'vote_on_issues' %> +
+ + <% if authorize_for('issues', 'view_voters') %> +
+ <%= link_to(l(:view_issues_label_voters), {:controller => 'vote_on_issues', :action => 'show_voters', :issue_id => @issue }, remote: true, :id => "vote_on_issues-link-voters", :class => 'vote_on_issues-link-voters', :title => l(:view_issues_show_voters) ) %> +
+ + + <% end %> + + +
\ No newline at end of file diff --git a/app/views/view_issues/_show_details_bottom.erb b/app/views/view_issues/_show_details_bottom.erb deleted file mode 100644 index d3c3fa1..0000000 --- a/app/views/view_issues/_show_details_bottom.erb +++ /dev/null @@ -1,72 +0,0 @@ -<% if @project.module_enabled?(:vote_on_issues) %> - -
- <% if authorize_for('issues', 'view_votes') %> -
-
-
<%= l(:view_issues_label_votes) %>:
-
-
- <%= image_tag 'arrow-u-r-green.png', :class => 'vote_on_issues-icon-votes', :plugin => 'vote_on_issues' %> -
-
- <%= image_tag 'arrow-d-r-red.png', :class => 'vote_on_issues-icon-votes', :plugin => 'vote_on_issues' %> -
- - <% if authorize_for('issues', 'view_voters') %> -
- <%= link_to(l(:view_issues_label_voters), {:controller => 'vote_on_issues', :action => 'show_voters', :issue_id => @issue }, remote: true, :id => "vote_on_issues-link-voters", :class => 'vote_on_issues-link-voters', :title => l(:view_issues_show_voters) ) %> -
- - - <% end %> - - -
-
-
- <% end %> - - <% if authorize_for('issues', 'cast_vote') %> -
-
-
<%= l(:view_issues_my_vote) %>:
-
-
- - <%= image_tag('arrow-u-r-green.png', :id => 'vote_on_issues_MyVoteUpOn', :style => 'display:none', :class => 'vote_on_issues-icon-vote', :plugin => 'vote_on_issues') %> - <%= image_tag('arrow-d-r-red.png', :id => 'vote_on_issues_MyVoteDnOn', :style => 'display:none', :class => 'vote_on_issues-icon-vote', :plugin => 'vote_on_issues') %> -
- -
-   <%= l(:view_issues_my_vote_opt) %>: - <%= link_to(image_tag('arrow-u-r-blank.png', :id => 'vote_on_issues_MyVoteUpOff', :style => 'display:none', :class => 'vote_on_issues-icon-vote', :plugin => 'vote_on_issues'), {:controller => 'vote_on_issues', :action => 'cast_vote', :issue_id => @issue, :vote_val => 'vup' }, remote: true, :class => 'vote_on_issues-icon-vote', :title => l(:view_issues_my_vote_opt_up) ) %> - <%= link_to(image_tag('arrow-d-r-blank.png', :id => 'vote_on_issues_MyVoteDnOff', :style => 'display:none', :class => 'vote_on_issues-icon-vote', :plugin => 'vote_on_issues'), {:controller => 'vote_on_issues', :action => 'cast_vote', :issue_id => @issue, :vote_val => 'vdn' }, remote: true, :class => 'vote_on_issues-icon-vote', :title => l(:view_issues_my_vote_opt_dn) ) %> - <%= link_to(image_tag('delete-black.png', :id => 'vote_on_issues_MyVoteDelete', :style => 'display:none', :class => 'vote_on_issues-icon-vote', :plugin => 'vote_on_issues'), {:controller => 'vote_on_issues', :action => 'cast_vote', :issue_id => @issue, :vote_val => 'nil' }, remote: true, :class => 'vote_on_issues-icon-vote', :title => l(:view_issues_my_vote_opt_nil) ) %> -
- - -
-
-
- <% end %> -
- -<% end %> diff --git a/app/views/vote_on_issues/show_voters.js.erb b/app/views/vote_on_issues/show_voters.js.erb index 00a0293..06921aa 100644 --- a/app/views/vote_on_issues/show_voters.js.erb +++ b/app/views/vote_on_issues/show_voters.js.erb @@ -1,12 +1,12 @@ vote_on_issues.clearListOfVoters(); -<% @UpVotes.each do |vote| %> - vote_on_issues.addToListOfVoters(<%= vote['vote_val'] %>, "<%= vote['user_login'] %>"); +<% @UpVotes.each do |vote, login| %> + vote_on_issues.addToListOfVoters(<%= vote %>, "<%= login %>"); <% end %> -<% @DnVotes.each do |vote| %> - vote_on_issues.addToListOfVoters(<%= vote['vote_val'] %>, "<%= vote['user_login'] %>"); +<% @DnVotes.each do |vote, login| %> + vote_on_issues.addToListOfVoters(<%= vote %>, "<%= login %>"); <% end %> vote_on_issues.showListOfVoters(); diff --git a/assets/javascripts/view_issues_vote.js b/assets/javascripts/view_issues_vote.js index b3bb64b..ea5672a 100644 --- a/assets/javascripts/view_issues_vote.js +++ b/assets/javascripts/view_issues_vote.js @@ -1,7 +1,7 @@ /** ** ** -** @package +** @package ** @author Ole Jungclaussen ** @version 1.0.0 ** @.copyright 2017, Ole Jungclaussen @@ -10,13 +10,13 @@ var vote_on_issues = { version : '1.0.0' ,sImgUp : '' ,sImgDn : '' - + // ALL VOTES , showVotesOnIssue: function(nVotesUp, nVotesDn){ $('#vote_on_issues_nVotesUp').html(nVotesUp); $('#vote_on_issues_nVotesDn').html(nVotesDn); } - + // LIST OF VOTERS , isListOfVotersOpen : function() { return('none' != $('#vote_on_issues-issue-voters').css('display')); @@ -37,12 +37,12 @@ var vote_on_issues = { , showListOfVoters : function() { var ListBox = $('#vote_on_issues-issue-voters'); var Anchor = $('#vote_on_issues-link-voters'); - + ListBox.css({ top: Anchor.position().top, left: Anchor.position().left }); - + if('none' == ListBox.css('display')){ var that = this; $(document).on('click.vote_on_issues-ListBox', function() { @@ -53,7 +53,7 @@ var vote_on_issues = { e.stopPropagation(); // This is the preferred method. return false; // This should not be used unless you do not want // any click events registering inside the div - }); + }); ListBox.show(); } } @@ -66,18 +66,18 @@ var vote_on_issues = { } this.clearListOfVoters(); } - + // MY VOTE , showMyVote : function(iUserVote){ - + $('#vote_on_issues_MyVoteNil').hide(); - + $('#vote_on_issues_MyVoteUpOn').hide(); $('#vote_on_issues_MyVoteDnOn').hide(); $('#vote_on_issues_MyVoteUpOff').hide(); $('#vote_on_issues_MyVoteDnOff').hide(); $('#vote_on_issues_MyVoteDelete').hide(); - + if(!iUserVote){ $('#vote_on_issues_MyVoteNil').show(); $('#vote_on_issues_MyVoteUpOff').show(); diff --git a/assets/stylesheets/view_issues_vote.css b/assets/stylesheets/view_issues_vote.css index 276abfd..657a698 100644 --- a/assets/stylesheets/view_issues_vote.css +++ b/assets/stylesheets/view_issues_vote.css @@ -24,29 +24,30 @@ div.vote_on_issues-issue-votes-nowrap { left: 1em; width: 25em; max-width: 50%; - + border: 2px solid #CCC; border-radius: 5px; - + background-color: #FFF; - + overflow: hidden; - + box-shadow: 0.5em 0.5em 0.3em rgba(0,0,0,0.5); } #vote_on_issues-issue-voters > div:nth-child(1) { background-color: #628DB6; color:#FFF; -} +} #vote_on_issues-issue-voters > div:nth-child(2) { border-radius: 0 0 5px 5px; padding:0.2em; min-height: 10vh; max-height: 40vh; - + overflow: auto; -} +} + /* TITLE BAR */ #vote_on_issues-issue-voters > div:nth-child(1) > table { width:100%; @@ -66,6 +67,7 @@ div.vote_on_issues-issue-votes-nowrap { width:0.7em; height:0.7em; } + /* LIST TABLE */ #vote_on_issues-issue-voters > div:nth-child(2) > table { width:100%; @@ -73,13 +75,14 @@ div.vote_on_issues-issue-votes-nowrap { } #vote_on_issues-issue-voters-list tr { border-bottom:1px solid #CCC; -} +} #vote_on_issues-issue-voters-list tr:last-child { border-bottom:none; -} +} + #vote_on_issues-issue-voters-list td { - } + #vote_on_issues-issue-voters-list td:nth-child(1) { width:16px; } @@ -93,6 +96,7 @@ div.vote_on_issues-issue-votes-nowrap { #vote_on_issues-issue-voters-list span[data-vote-val="-1"] { color:#800; } + /** ** ** MY VOTE @@ -101,12 +105,14 @@ div.vote_on_issues-issue-votes-nowrap { span.vote_on_issues-my-vote-opt { clear:left; } + img.vote_on_issues-icon-votes { width:0.8em; height:0.8em; margin-left:0.2em; margin-right:0.8em; -} +} + .vote_on_issues-icon-vote { text-decoration: none !important; } diff --git a/changelog b/changelog index beb2d05..31b24ba 100644 --- a/changelog +++ b/changelog @@ -1,5 +1,12 @@ +1.0.3: Added sum votes up and down column +use Rails.configuration.to_prepare to permit hot reload +downgraded version_or_higher to Redmine 2.6.10 +query_column -> voi_query_column +Hot reload enabled in development +Applied standard rails conventions +== 1.0.2: Added permission 'view voters' == 1.0.1: Added permission 'view votes' -== -1.0.0: Initial version \ No newline at end of file +== +1.0.0: Initial version diff --git a/config/locales/de.yml b/config/locales/de.yml index a891b8f..8010812 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -2,26 +2,27 @@ de: # my_label: "My label" project_module_vote_on_issues: "Über Tickets abstimmen" - + menu_title: "Abstimmungen" - permission_cast_votes: "Über Tickets abstimmen" + permission_cast_votes: "Über Tickets abstimmen" permission_view_votes: "Stimmen anzeigen" permission_view_voter: "Abstimmer Anzeigen" - + view_issues_label_votes: "Stimmen" - + view_issues_label_voters: "Abstimmer" view_issues_show_voters: "Abstimmer anzeigen" view_issues_issue_voters: "Liste der Abstimmer" - + view_issues_my_vote: "Meine Stimme" view_issues_my_vote_opt: "Ändern" - + view_issues_my_vote_opt_up: "Hoch wählen" view_issues_my_vote_opt_dn: "Runter wählen" view_issues_my_vote_opt_nil: "Stimme zurück ziehen" field_sum_votes_up: "Stimmen hoch" field_sum_votes_dn: "Stimmen runter" - + + field_sum_votes_up_and_dn: "Stimmen hoch und runter" diff --git a/config/locales/en.yml b/config/locales/en.yml index ddfe7ca..47a2ccb 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2,26 +2,27 @@ en: # my_label: "My label" project_module_vote_on_issues: "Vote On Issues" - + menu_title: "Votes" - permission_cast_votes: "Vote on issues" + permission_cast_votes: "Vote on issues" permission_view_votes: "View votes" permission_view_voter: "View voters" - + view_issues_label_votes: "Votes" - + view_issues_label_voters: "Voters" view_issues_show_voters: "Show voters" view_issues_issue_voters: "List of Voters" - + view_issues_my_vote: "My vote" view_issues_my_vote_opt: "Change" - + view_issues_my_vote_opt_up: "Vote up" view_issues_my_vote_opt_dn: "Vote down" view_issues_my_vote_opt_nil: "Withdraw vote" field_sum_votes_up: "Votes Up" field_sum_votes_dn: "Votes Down" - \ No newline at end of file + + field_sum_votes_up_and_dn: "Votes Up and Down" diff --git a/config/locales/fr.yml b/config/locales/fr.yml new file mode 100644 index 0000000..0d9f32c --- /dev/null +++ b/config/locales/fr.yml @@ -0,0 +1,27 @@ +# French strings go here for Rails i18n +fr: + project_module_vote_on_issues: "Vote sur les Demandes" + + menu_title: "Votes" + + permission_cast_votes: "Vote sur les demandes" + permission_view_votes: "Voir votes" + permission_view_voter: "Voir voteurs" + + view_issues_label_votes: "Votes" + + view_issues_label_voters: "Voteurs" + view_issues_show_voters: "Montrer voteurs" + view_issues_issue_voters: "Liste des Voteurs" + + view_issues_my_vote: "Mon vote" + view_issues_my_vote_opt: "Change" + + view_issues_my_vote_opt_up: "Voter 👍" + view_issues_my_vote_opt_dn: "Voter 👎" + view_issues_my_vote_opt_nil: "Annule vote" + + field_sum_votes_up: "Votes 👍" + field_sum_votes_dn: "Votes 👎" + + field_sum_votes_up_and_dn: "Votes total" diff --git a/db/migrate/001_create_vote_on_issues.rb b/db/migrate/001_create_vote_on_issues.rb index c0e4645..2922e36 100644 --- a/db/migrate/001_create_vote_on_issues.rb +++ b/db/migrate/001_create_vote_on_issues.rb @@ -1,4 +1,10 @@ -class CreateVoteOnIssues < ActiveRecord::Migration +if Rails.version >= '5' + MigrationKlass = ActiveRecord::Migration[4.2] +else + MigrationKlass = ActiveRecord::Migration +end + +class CreateVoteOnIssues < MigrationKlass def self.up create_table :vote_on_issues do |t| t.datetime :created_at @@ -9,7 +15,7 @@ def self.up end # add_index :vote_on_issues, [:issue_id, :user_id], unique: true end - + def self.down drop_table :vote_on_issues end diff --git a/init.rb b/init.rb index 9d264a3..d456591 100644 --- a/init.rb +++ b/init.rb @@ -1,34 +1,26 @@ require 'redmine' -require_dependency 'hooks' -require_dependency 'query_column' - -# patch issue_query to allow columns for votes -issue_query = (IssueQuery rescue Query) -issue_query.add_available_column(VOI_QueryColumn.new(:sum_votes_up, :sortable => '(SELECT abs(sum(vote_val)) FROM vote_on_issues WHERE vote_val > 0 AND issue_id=issues.id )')) -issue_query.add_available_column(VOI_QueryColumn.new(:sum_votes_dn, :sortable => '(SELECT abs(sum(vote_val)) FROM vote_on_issues WHERE vote_val < 0 AND issue_id=issues.id )')) -Issue.send(:include, VoteOnIssues::Patches::QueryPatch) Redmine::Plugin.register :vote_on_issues do name 'Vote On Issues' description 'This plugin allows to up- and down-vote issues.' - version '1.0.2' + version '1.0.3' url 'https://github.com/ojde/redmine-vote_on_issues-plugin' author 'Ole Jungclaussen' author_url 'https://jungclaussen.com' - - requires_redmine :version_or_higher => '3.3.2' - + + requires_redmine :version_or_higher => '2.6.10' + project_module :vote_on_issues do permission :cast_votes, {:issues => :cast_vote }, :require => :loggedin permission :view_votes, {:issues => :view_votes}, :require => :loggedin - permission :view_voters, {:issues => :view_voters}, :require => :loggedin + permission :view_voters, {:issues => :view_voters}, :require => :loggedin end # permission for menu # permission :vote_on_issues, { :vote_on_issues => [:index] }, :public => true # menu :project_menu, - # :vote_on_issues, + # :vote_on_issues, # { :controller => 'vote_on_issues', :action => 'index' }, # :caption => :menu_title, # :after => :issues, @@ -36,12 +28,25 @@ # :if => Proc.new { # User.current.allowed_to?(:view_votes, nil, :global => true) # } - end -class VoteOnIssuesListener < Redmine::Hook::ViewListener - render_on :view_layouts_base_html_head, :inline => <<-END - <%= stylesheet_link_tag 'view_issues_vote', :plugin => 'vote_on_issues' %> - <%= javascript_include_tag 'view_issues_vote', :plugin => 'vote_on_issues' %> - END -end +# Executed after Rails initialization, each time the classes are reloaded +Rails.configuration.to_prepare do + require_dependency 'hooks' + require_dependency 'vote_on_issue' + require_dependency 'voi_query_column' + + # patch issue_query to allow columns for votes + issue_query = (IssueQuery rescue Query) + issue_query.add_available_column(VoiQueryColumn.new(:sum_votes_up, :sortable => '(SELECT abs(sum(vote_val)) FROM vote_on_issues WHERE vote_val > 0 AND issue_id=issues.id )')) + issue_query.add_available_column(VoiQueryColumn.new(:sum_votes_dn, :sortable => '(SELECT abs(sum(vote_val)) FROM vote_on_issues WHERE vote_val < 0 AND issue_id=issues.id )')) + issue_query.add_available_column(VoiQueryColumn.new(:sum_votes_up_and_dn, :sortable => '(SELECT sum(vote_val) FROM vote_on_issues WHERE issue_id=issues.id )')) + Issue.send(:include, VoteOnIssues::Patches::QueryPatch) + + class VoteOnIssuesListener < Redmine::Hook::ViewListener + render_on :view_layouts_base_html_head, :inline => <<-END + <%= stylesheet_link_tag 'view_issues_vote', :plugin => 'vote_on_issues' %> + <%= javascript_include_tag 'view_issues_vote', :plugin => 'vote_on_issues' %> + END + end +end \ No newline at end of file diff --git a/lib/hooks.rb b/lib/hooks.rb index e0c272e..1cf480b 100644 --- a/lib/hooks.rb +++ b/lib/hooks.rb @@ -6,7 +6,7 @@ class Hooks < Redmine::Hook::ViewListener # Html File expected is: /plugins/plugin_name/app/views/abc/_test.erb # Otherwise we'll get a 404 on the whole view render_on :view_issues_show_details_bottom, - :partial => 'view_issues/show_details_bottom' + :partial => 'issues/show_details_bottom' # Writing Html code directly # render_on :view_issues_show_details_bottom, :inline => <<-END @@ -54,7 +54,7 @@ class Hooks < Redmine::Hook::ViewListener # # # -# ------ INSERT -------- +# ------ INSERT -------- #
#
#
@@ -63,5 +63,5 @@ class Hooks < Redmine::Hook::ViewListener #
#
#
-# ------ INSERT -------- +# ------ INSERT -------- # diff --git a/lib/query_column.rb b/lib/query_column.rb deleted file mode 100644 index 7e09ae0..0000000 --- a/lib/query_column.rb +++ /dev/null @@ -1,54 +0,0 @@ -require 'query' - -class VOI_QueryColumn < QueryColumn -=begin - attr_accessor :name, :sortable, :groupable, :default_order - include Redmine::I18n - - def initialize(name, options={}) - self.name = name - self.sortable = options[:sortable] - self.groupable = options[:groupable] || false - if groupable == true - self.groupable = name.to_s - end - self.default_order = options[:default_order] - @inline = options.key?(:inline) ? options[:inline] : true - @caption_key = options[:caption] || "field_#{name}".to_sym - @frozen = options[:frozen] - end - - def caption - @caption_key.is_a?(Symbol) ? l(@caption_key) : @caption_key - end - - # Returns true if the column is sortable, otherwise false - def sortable? - !@sortable.nil? - end - - def sortable - @sortable.is_a?(Proc) ? @sortable.call : @sortable - end - - def inline? - @inline - end - - def frozen? - @frozen - end -=end - def value(object) - object.send name, object - end - - def value_object(object) - object.send name, object - end -=begin - def css_classes - name - end -=end -end diff --git a/lib/vote_on_issues/patches/query_patch.rb b/lib/vote_on_issues/patches/query_patch.rb index dba48f4..87685bf 100644 --- a/lib/vote_on_issues/patches/query_patch.rb +++ b/lib/vote_on_issues/patches/query_patch.rb @@ -2,10 +2,10 @@ module VoteOnIssues module Patches module QueryPatch - + def sum_votes_up(issue) if User.current.allowed_to?(:view_votes, nil, :global => true) - VoteOnIssue.where('vote_val > 0 AND issue_id=?', issue.id).sum('vote_val') + VoteOnIssue.where(issue_id: issue.id).where('vote_val > 0').sum('vote_val') else '-' end @@ -13,12 +13,19 @@ def sum_votes_up(issue) def sum_votes_dn(issue) if User.current.allowed_to?(:view_votes, nil, :global => true) - VoteOnIssue.where('vote_val < 0 AND issue_id=?', issue.id).sum('vote_val') + VoteOnIssue.where(issue_id: issue.id).where('vote_val < 0').sum('vote_val') + else + '-' + end + end + + def sum_votes_up_and_dn(issue) + if User.current.allowed_to?(:view_votes, nil, :global => true) + VoteOnIssue.where(issue_id: issue.id).sum('vote_val') else '-' end end - end end end \ No newline at end of file