diff --git a/plugins/redmine_questions/.drone.jsonnet b/plugins/redmine_questions/.drone.jsonnet new file mode 100644 index 0000000..55d8ab7 --- /dev/null +++ b/plugins/redmine_questions/.drone.jsonnet @@ -0,0 +1,34 @@ +local Pipeline(rubyVer, db, license, redmine, dependents) = { + kind: "pipeline", + name: rubyVer + "-" + db + "-" + redmine + "-" + license + "-" + dependents, + steps: [ + { + name: "tests", + image: "redmineup/redmineup_ci", + commands: [ + "service postgresql start && service mysql start && sleep 5", + "export PATH=~/.rbenv/shims:$PATH", + "export CODEPATH=`pwd`", + "/root/run_for.sh redmine_questions+" + license + " ruby-" + rubyVer + " " + db + " redmine-" + redmine + " " + dependents + ] + } + ] +}; + +[ + Pipeline("2.4.1", "mysql", "pro", "trunk", ""), + Pipeline("2.4.1", "mysql", "light", "trunk", ""), + Pipeline("2.4.1", "pg", "pro", "trunk", ""), + Pipeline("2.4.1", "mysql", "pro", "4.1", ""), + Pipeline("2.4.1", "mysql", "light", "4.1", ""), + Pipeline("2.4.1", "pg", "pro", "4.1", ""), + Pipeline("2.4.1", "mysql", "pro", "4.0", ""), + Pipeline("2.4.1", "mysql", "light", "4.0", ""), + Pipeline("2.4.1", "pg", "pro", "4.0", ""), + Pipeline("2.4.1", "pg", "light", "4.0", ""), + Pipeline("2.2.6", "mysql", "pro", "3.4", ""), + Pipeline("2.2.6", "pg", "pro", "3.4", ""), + Pipeline("2.2.6", "mysql", "pro", "3.0", ""), + Pipeline("2.2.6", "mysql", "light", "3.0", ""), + Pipeline("1.9.3", "pg", "pro", "2.6", ""), +] diff --git a/plugins/redmine_questions/app/controllers/questions_answers_controller.rb b/plugins/redmine_questions/app/controllers/questions_answers_controller.rb index 7ebf11d..f28d247 100644 --- a/plugins/redmine_questions/app/controllers/questions_answers_controller.rb +++ b/plugins/redmine_questions/app/controllers/questions_answers_controller.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Q&A (redmine_questions) plugin, # Q&A plugin for Redmine # -# Copyright (C) 2011-2018 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_questions is free software: you can redistribute it and/or modify @@ -34,9 +34,11 @@ class QuestionsAnswersController < ApplicationController end def edit + (render_403; return false) unless @answer.editable_by?(User.current) end def update + (render_403; return false) unless @answer.editable_by?(User.current) || User.current.allowed_to?(:accept_answers, @project) @answer.safe_attributes = params[:answer] @answer.save_attachments(params[:attachments]) if @answer.save @@ -87,7 +89,7 @@ class QuestionsAnswersController < ApplicationController private def redirect_to_question - redirect_to question_path(@answer.question, :anchor => "question_item_#{@answer.id}") + redirect_to question_path(@answer.question, :anchor => "questions_answer_#{@answer.id}") end def find_answer diff --git a/plugins/redmine_questions/app/controllers/questions_comments_controller.rb b/plugins/redmine_questions/app/controllers/questions_comments_controller.rb index 7c4512e..0887b64 100644 --- a/plugins/redmine_questions/app/controllers/questions_comments_controller.rb +++ b/plugins/redmine_questions/app/controllers/questions_comments_controller.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Q&A (redmine_questions) plugin, # Q&A plugin for Redmine # -# Copyright (C) 2011-2018 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_questions is free software: you can redistribute it and/or modify diff --git a/plugins/redmine_questions/app/controllers/questions_controller.rb b/plugins/redmine_questions/app/controllers/questions_controller.rb index 224844c..bc67eac 100644 --- a/plugins/redmine_questions/app/controllers/questions_controller.rb +++ b/plugins/redmine_questions/app/controllers/questions_controller.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Q&A (redmine_questions) plugin, # Q&A plugin for Redmine # -# Copyright (C) 2011-2018 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_questions is free software: you can redistribute it and/or modify @@ -54,6 +54,7 @@ class QuestionsController < ApplicationController end def update + (render_403; return false) unless @question_item.editable_by?(User.current) @question_item.safe_attributes = params[:question] @question_item.save_attachments(params[:attachments]) if @question_item.save @@ -133,6 +134,7 @@ class QuestionsController < ApplicationController @text = (params[:question] ? params[:question][:content] : nil) render :partial => 'common/preview' end + private def find_questions @@ -142,10 +144,10 @@ class QuestionsController < ApplicationController scope = Question.visible scope = scope.where(:section_id => @section) if @section - columns = ["subject", "content"] - tokens = seach.to_s.scan(%r{((\s|^)"[\s\w]+"(\s|$)|\S+)}).collect{|m| m.first.gsub(%r{(^\s*"\s*|\s*"\s*$)}, '')}.uniq.select {|w| w.length > 1 } + columns = ['subject', 'content'] + tokens = seach.to_s.scan(%r{((\s|^)"[\s\w]+"(\s|$)|\S+)}).collect { |m| m.first.gsub(%r{(^\s*"\s*|\s*"\s*$)}, '') }.uniq.select { |w| w.length > 1 } tokens = [] << tokens unless tokens.is_a?(Array) - token_clauses = columns.collect {|column| "(LOWER(#{column}) LIKE ?)"} + token_clauses = columns.collect { |column| "(LOWER(#{column}) LIKE ?)" } sql = (['(' + token_clauses.join(' OR ') + ')'] * tokens.size).join(' AND ') find_options = [sql, * (tokens.collect {|w| "%#{w.downcase}%"} * token_clauses.size).sort] @@ -166,9 +168,9 @@ class QuestionsController < ApplicationController end @limit = per_page_option - @offset = params[:page].to_i*@limit + @offset = params[:page].to_i * @limit scope = scope.limit(@limit).offset(@offset) - scope = scope.tagged_with(params[:tag]) unless params[:tag].blank? + scope = scope.tagged_with(params[:tag]) if params[:tag].present? @topic_count = scope.count @topic_pages = Paginator.new @topic_count, @limit, params[:page] @@ -178,7 +180,7 @@ class QuestionsController < ApplicationController def find_section @section = QuestionsSection.find_by_id(params[:section_id] || (params[:question] && params[:question][:section_id])) - @section ||= @project.questions_sections.first + @section ||= @project.questions_sections.first if @project rescue ActiveRecord::RecordNotFound render_404 end diff --git a/plugins/redmine_questions/app/controllers/questions_sections_controller.rb b/plugins/redmine_questions/app/controllers/questions_sections_controller.rb index b33376d..a9bb37b 100644 --- a/plugins/redmine_questions/app/controllers/questions_sections_controller.rb +++ b/plugins/redmine_questions/app/controllers/questions_sections_controller.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Q&A (redmine_questions) plugin, # Q&A plugin for Redmine # -# Copyright (C) 2011-2018 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_questions is free software: you can redistribute it and/or modify @@ -58,6 +58,7 @@ class QuestionsSectionsController < ApplicationController def update @section.safe_attributes = params[:questions_section] + @section.insert_at(@section.position) if @section.position_changed? if @section.save respond_to do |format| format.html do diff --git a/plugins/redmine_questions/app/controllers/questions_statuses_controller.rb b/plugins/redmine_questions/app/controllers/questions_statuses_controller.rb index 35db2e2..1acbc7c 100644 --- a/plugins/redmine_questions/app/controllers/questions_statuses_controller.rb +++ b/plugins/redmine_questions/app/controllers/questions_statuses_controller.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Q&A (redmine_questions) plugin, # Q&A plugin for Redmine # -# Copyright (C) 2011-2018 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_questions is free software: you can redistribute it and/or modify @@ -39,12 +39,13 @@ class QuestionsStatusesController < ApplicationController end def create - @questions_status = QuestionsStatus.new(params[:questions_status]) + @questions_status = QuestionsStatus.new + @questions_status.safe_attributes = params[:questions_status] if request.post? && @questions_status.save flash[:notice] = l(:notice_successful_create) - redirect_to :action => "plugin", :id => "redmine_questions", :controller => "settings", :tab => 'questions_statuses' + redirect_to action: 'plugin', id: 'redmine_questions', controller: 'settings', tab: 'questions_statuses' else - render :action => 'new' + render action: 'new' end end @@ -54,17 +55,18 @@ class QuestionsStatusesController < ApplicationController def update @questions_status = QuestionsStatus.find(params[:id]) - if @questions_status.update_attributes(params[:questions_status]) + @questions_status.safe_attributes = params[:questions_status] + if @questions_status.save respond_to do |format| format.html { flash[:notice] = l(:notice_successful_update) - redirect_to :action => 'plugin', :id => 'redmine_questions', :controller => 'settings', :tab => 'questions_statuses' + redirect_to action: 'plugin', id: 'redmine_questions', controller: 'settings', tab: 'questions_statuses' } format.js { head 200 } end else respond_to do |format| - format.html { render :action => 'edit' } + format.html { render action: 'edit' } format.js { head 422 } end end @@ -72,11 +74,9 @@ class QuestionsStatusesController < ApplicationController def destroy QuestionsStatus.find(params[:id]).destroy - redirect_to :action =>"plugin", :id => "redmine_questions", :controller => "settings", :tab => 'questions_statuses' + redirect_to action: 'plugin', id: 'redmine_questions', controller: 'settings', tab: 'questions_statuses' rescue flash[:error] = l(:error_products_unable_delete_questions_status) - redirect_to :action =>"plugin", :id => "redmine_questions", :controller => "settings", :tab => 'questions_statuses' + redirect_to action: 'plugin', id: 'redmine_questions', controller: 'settings', tab: 'questions_statuses' end - - end diff --git a/plugins/redmine_questions/app/helpers/questions_helper.rb b/plugins/redmine_questions/app/helpers/questions_helper.rb index a9e353c..c16eb61 100644 --- a/plugins/redmine_questions/app/helpers/questions_helper.rb +++ b/plugins/redmine_questions/app/helpers/questions_helper.rb @@ -3,7 +3,7 @@ # This file is a part of Redmine Q&A (redmine_questions) plugin, # Q&A plugin for Redmine # -# Copyright (C) 2011-2018 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_questions is free software: you can redistribute it and/or modify diff --git a/plugins/redmine_questions/app/models/question.rb b/plugins/redmine_questions/app/models/question.rb index 99efbcd..c21af9b 100644 --- a/plugins/redmine_questions/app/models/question.rb +++ b/plugins/redmine_questions/app/models/question.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Q&A (redmine_questions) plugin, # Q&A plugin for Redmine # -# Copyright (C) 2011-2018 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_questions is free software: you can redistribute it and/or modify @@ -54,22 +54,22 @@ class Question < ActiveRecord::Base :author_key => :author_id, :timestamp => "#{table_name}.created_on", :scope => joins({:section => :project}, :author) - acts_as_searchable :columns => ["#{table_name}.subject", - "#{table_name}.content", + acts_as_searchable :columns => ["#{table_name}.subject", + "#{table_name}.content", "#{QuestionsAnswer.table_name}.content"], - :scope => joins({:section => :project}, :answers), - :project_key => "#{QuestionsSection.table_name}.project_id" + :scope => joins({:section => :project}, :answers), + :project_key => "#{QuestionsSection.table_name}.project_id" else acts_as_activity_provider :type => 'questions', :permission => :view_questions, :author_key => :author_id, :timestamp => "#{table_name}.created_on", :find_options => { :include => [{:section => :project}, :author] } - acts_as_searchable :columns => ["#{table_name}.subject", - "#{table_name}.content", + acts_as_searchable :columns => ["#{table_name}.subject", + "#{table_name}.content", "#{QuestionsAnswer.table_name}.content"], :include => [{:section => :project}, :answers], - :project_key => "#{QuestionsSection.table_name}.project_id" + :project_key => "#{QuestionsSection.table_name}.project_id" end scope :solutions, lambda { joins(:section).where(:questions_sections => {:section_type => QuestionsSection::SECTION_TYPE_SOLUTIONS}) } @@ -114,7 +114,7 @@ class Question < ActiveRecord::Base allowed_to_view_condition += projects_allowed_to_view_questions.empty? ? ' OR (0=1) ' : " OR (#{table_name}.project_id IN (#{projects_allowed_to_view_questions.join(',')}))" user.admin? ? '(1=1)' : allowed_to_view_condition - end + end def self.related(question, limit) tokens = question.subject.strip.scan(%r{((\s|^)"[\s\w]+"(\s|$)|\S+)}). @@ -127,7 +127,7 @@ class Question < ActiveRecord::Base end def commentable?(user = User.current) - return false if locked? + return false if locked? user.allowed_to?(:comment_question, project) end @@ -285,6 +285,6 @@ class Question < ActiveRecord::Base end def send_notification - Mailer.question_question_added(self).deliver if Setting.notified_events.include?('question_added') + Mailer.question_question_added(User.current, self).deliver if Setting.notified_events.include?('question_added') end end diff --git a/plugins/redmine_questions/app/models/questions_answer.rb b/plugins/redmine_questions/app/models/questions_answer.rb index b1e9f0f..39c46a7 100644 --- a/plugins/redmine_questions/app/models/questions_answer.rb +++ b/plugins/redmine_questions/app/models/questions_answer.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Q&A (redmine_questions) plugin, # Q&A plugin for Redmine # -# Copyright (C) 2011-2018 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_questions is free software: you can redistribute it and/or modify @@ -97,6 +97,7 @@ class QuestionsAnswer < ActiveRecord::Base end def editable_by?(user) + (author == user && user.allowed_to?(:edit_own_answers, project)) || user.allowed_to?(:edit_questions, project) end @@ -107,7 +108,7 @@ class QuestionsAnswer < ActiveRecord::Base def votable_by?(user) user.allowed_to?(:vote_questions, project) end - + private def check_accepted question.answers.update_all(:accepted => false) if question && @@ -121,6 +122,6 @@ class QuestionsAnswer < ActiveRecord::Base end def send_notification - Mailer.question_answer_added(self).deliver if Setting.notified_events.include?('question_answer_added') + Mailer.question_answer_added(User.current, self).deliver if Setting.notified_events.include?('question_answer_added') end end diff --git a/plugins/redmine_questions/app/models/questions_section.rb b/plugins/redmine_questions/app/models/questions_section.rb index 1263bbf..44418c4 100644 --- a/plugins/redmine_questions/app/models/questions_section.rb +++ b/plugins/redmine_questions/app/models/questions_section.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Q&A (redmine_questions) plugin, # Q&A plugin for Redmine # -# Copyright (C) 2011-2018 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_questions is free software: you can redistribute it and/or modify @@ -27,7 +27,12 @@ class QuestionsSection < ActiveRecord::Base attr_protected :id if ActiveRecord::VERSION::MAJOR <= 4 safe_attributes 'name', 'project', 'position', 'description', 'section_type' - scope :with_questions_count, lambda { select("#{QuestionsSection.table_name}.*, count(#{QuestionsSection.table_name}.id) as questions_count").joins(:questions).order("project_id ASC").group("#{QuestionsSection.table_name}.id, #{QuestionsSection.table_name}.name, #{QuestionsSection.table_name}.project_id, #{QuestionsSection.table_name}.section_type") } + scope :with_questions_count, lambda { + select("#{QuestionsSection.table_name}.*, count(#{QuestionsSection.table_name}.id) as questions_count"). + joins(:questions). + order("project_id ASC"). + group(QuestionsSection.column_names.map { |column| "#{QuestionsSection.table_name}.#{column}" }.join(', ')) + } scope :for_project, lambda { |project| where(:project_id => project) unless project.blank? } scope :visible, lambda {|*args| joins(:project). diff --git a/plugins/redmine_questions/app/models/questions_settings.rb b/plugins/redmine_questions/app/models/questions_settings.rb index bd81f48..04168f6 100644 --- a/plugins/redmine_questions/app/models/questions_settings.rb +++ b/plugins/redmine_questions/app/models/questions_settings.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Q&A (redmine_questions) plugin, # Q&A plugin for Redmine # -# Copyright (C) 2011-2018 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_questions is free software: you can redistribute it and/or modify diff --git a/plugins/redmine_questions/app/models/questions_status.rb b/plugins/redmine_questions/app/models/questions_status.rb index 1014152..4400653 100644 --- a/plugins/redmine_questions/app/models/questions_status.rb +++ b/plugins/redmine_questions/app/models/questions_status.rb @@ -1,7 +1,7 @@ # This file is a part of Redmine Q&A (redmine_questions) plugin, # Q&A plugin for Redmine # -# Copyright (C) 2011-2018 RedmineUP +# Copyright (C) 2011-2020 RedmineUP # http://www.redmineup.com/ # # redmine_questions is free software: you can redistribute it and/or modify @@ -26,7 +26,7 @@ class QuestionsStatus < ActiveRecord::Base attr_protected :id if ActiveRecord::VERSION::MAJOR <= 4 safe_attributes 'name', 'is_closed', 'position', 'color' - validates :name, :presence => true, :uniqueness => true + validates :name, presence: true, uniqueness: true scope :sorted, lambda { order(:position) } diff --git a/plugins/redmine_questions/app/views/projects/_questions_settings.html.erb b/plugins/redmine_questions/app/views/projects/_questions_settings.html.erb index 9e38735..83b372e 100644 --- a/plugins/redmine_questions/app/views/projects/_questions_settings.html.erb +++ b/plugins/redmine_questions/app/views/projects/_questions_settings.html.erb @@ -1,36 +1,41 @@ +<% @project_sections = QuestionsSection.for_project(@project).sorted %>
<%= l(:field_name) %> | -<%=l(:field_type)%> | -- | |||
---|---|---|---|---|---|
- <%= h(section.name) %> - | -- <%= section.l_type %> - | -- <% if User.current.allowed_to?(:manage_sections, @project) %> - <%= reorder_handle(section, :url => project_questions_section_path(@project, section), :param => 'questions_section') if respond_to?(:reorder_handle) %> - <%= link_to l(:button_edit), {:controller => 'questions_sections', :action => 'edit', :project_id => @project, :id => section}, :class => 'icon icon-edit' %> - <%= delete_link :controller => 'questions_sections', :action => 'destroy', :project_id => @project, :id => section %> - <% end %> - | +<% if @project_sections.any? %> +
<%= l(:field_name) %> | +<%=l(:field_type)%> | +
---|
<%= l(:label_no_data) %>
+<% end %> <% if User.current.allowed_to?(:manage_sections, @project) %> - <%= link_to image_tag('add.png', :style => 'vertical-align: middle;')+l(:label_questions_section_new), :controller => 'questions_sections', :action => 'new', :project_id => @project %> + <%= link_to image_tag('add.png', style: 'vertical-align: middle;') + l(:label_questions_section_new), new_questions_section_path(project_id: @project) %> <% end %> <%= javascript_tag do %> diff --git a/plugins/redmine_questions/app/views/questions/_form.html.erb b/plugins/redmine_questions/app/views/questions/_form.html.erb index 2f22e64..25c5411 100644 --- a/plugins/redmine_questions/app/views/questions/_form.html.erb +++ b/plugins/redmine_questions/app/views/questions/_form.html.erb @@ -6,7 +6,7 @@ <%= f.text_field :subject, :id => "question_subject", :size => 120%>
- <%= f.select :section_id, options_from_collection_for_select(QuestionsSection.where(:project_id => @project),:id, :name, f.object.section_id), :style => "width: 80%;", :required => true %>
+ <%= f.select :section_id, options_from_collection_for_select(QuestionsSection.where(:project_id => @project).sorted, :id, :name, f.object.section_id), :style => "width: 80%;", :required => true %>
<%= javascript_tag do %>
$('#question_section_id').change(function() {
$.ajax({
diff --git a/plugins/redmine_questions/app/views/questions/_question_item.html.erb b/plugins/redmine_questions/app/views/questions/_question_item.html.erb
index 738298b..986641e 100644
--- a/plugins/redmine_questions/app/views/questions/_question_item.html.erb
+++ b/plugins/redmine_questions/app/views/questions/_question_item.html.erb
@@ -1,6 +1,6 @@