diff --git a/.drone.jsonnet b/.drone.jsonnet
index b6c218d..735cbe0 100644
--- a/.drone.jsonnet
+++ b/.drone.jsonnet
@@ -16,14 +16,11 @@ local Pipeline(rubyVer, db, license, redmine, dependents) = {
};
[
- Pipeline("3.1.0", "mysql", "pro", "trunk", ""),
- Pipeline("3.1.0", "mysql", "light", "trunk", ""),
- Pipeline("3.1.0", "pg", "pro", "trunk", ""),
- Pipeline("3.1.0", "mysql", "pro", "5.0", ""),
- Pipeline("2.7.3", "mysql", "pro", "4.2", ""),
- Pipeline("2.7.3", "pg", "light", "4.2", ""),
- Pipeline("2.4.1", "pg", "pro", "4.0", ""),
- Pipeline("2.4.1", "mysql", "pro", "3.4", ""),
- Pipeline("2.2.6", "pg", "pro", "3.4", ""),
- Pipeline("2.2.6", "mysql", "light", "3.0", ""),
+ Pipeline("3.2.2", "mysql", "pro", "trunk", ""),
+ Pipeline("3.2.2", "pg", "pro", "5.1", ""),
+ Pipeline("3.0.6", "mysql", "pro", "5.0", "redmineup_tags"),
+ Pipeline("2.7.8", "mysql", "light", "4.2", ""),
+ Pipeline("2.7.8", "pg", "pro", "4.2", ""),
+ Pipeline("2.3.8", "mysql", "pro", "4.0", ""),
+ Pipeline("2.3.8", "pg", "pro", "4.0", "")
]
diff --git a/Gemfile b/Gemfile
index 58237bb..8696bdf 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1 +1 @@
-gem "redmine_crm"
+gem "redmineup"
diff --git a/app/controllers/questions_answers_controller.rb b/app/controllers/questions_answers_controller.rb
index 902a4f7..17f4e49 100644
--- a/app/controllers/questions_answers_controller.rb
+++ b/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-2023 RedmineUP
+# Copyright (C) 2011-2024 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
@@ -18,7 +18,6 @@
# along with redmine_questions. If not, see .
class QuestionsAnswersController < ApplicationController
- unloadable
before_action :find_question, :only => [:new, :create]
before_action :find_answer, :only => [:update, :destroy, :edit, :show]
diff --git a/app/controllers/questions_comments_controller.rb b/app/controllers/questions_comments_controller.rb
index 89dd625..21c6456 100644
--- a/app/controllers/questions_comments_controller.rb
+++ b/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-2023 RedmineUP
+# Copyright (C) 2011-2024 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb
index cb36c7e..339534c 100644
--- a/app/controllers/questions_controller.rb
+++ b/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-2023 RedmineUP
+# Copyright (C) 2011-2024 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
@@ -18,7 +18,6 @@
# along with redmine_questions. If not, see .
class QuestionsController < ApplicationController
- unloadable
before_action :find_question, :only => [:edit, :show, :update, :destroy]
before_action :find_optional_project, :only => [:index, :update_form, :new, :create, :autocomplete_for_subject]
@@ -41,7 +40,8 @@ class QuestionsController < ApplicationController
end
def show
- @answers = @question_item.answers.by_accepted.by_votes.by_date
+ @answers = @question_item.answers.
+ by_accepted.by_votes.by_date
if @answers
@limit = Setting.issues_export_limit.to_i
@answer_count = @answers.count
@@ -131,7 +131,7 @@ class QuestionsController < ApplicationController
if params[:id].present? && query = Question.find_by_id(params[:question_id])
@previewed = query
end
- @text = (params[:text] ? params[:text] : nil)
+ @text = (params[:question] ? params[:question][:content] : nil)
render :partial => 'common/preview'
end
@@ -168,13 +168,13 @@ class QuestionsController < ApplicationController
end
@limit = per_page_option
- scope = scope.tagged_with(params[:tag]) if params[:tag].present?
+ scope = scope.where(id: scope.tagged_with(params[:tag]).map(&:id)) if params[:tag].present?
@topic_count = scope.count
@topic_pages = Paginator.new(@topic_count, @limit, params[:page])
@offset = @topic_pages.offset
scope = scope.limit(@limit).offset(@offset)
-
+
@question_items = scope
end
@@ -186,12 +186,9 @@ class QuestionsController < ApplicationController
end
def find_question
- if Redmine::VERSION.to_s =~ /^2.6/
- @question_item = Question.visible.find(params[:id], readonly: false)
- else
- @question_item = Question.visible.find(params[:id])
- end
+ @question_item = Question.visible.find(params[:id])
return deny_access unless @question_item.visible?
+
@project = @question_item.project
rescue ActiveRecord::RecordNotFound
render_404
diff --git a/app/controllers/questions_sections_controller.rb b/app/controllers/questions_sections_controller.rb
index ac68a46..d16e8d7 100644
--- a/app/controllers/questions_sections_controller.rb
+++ b/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-2023 RedmineUP
+# Copyright (C) 2011-2024 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
@@ -85,7 +85,7 @@ class QuestionsSectionsController < ApplicationController
def index
ApplicationController.menu_item :questions
@question_item = Question.new
- @sections = QuestionsSection.visible.order(:project_id).sorted.for_project(@project)
+ @sections = QuestionsSection.visible.preload(:questions).order(:project_id).sorted.for_project(@project)
redirect_to project_questions_path(:section_id => @sections.last, :project_id => @sections.last.project) if @sections.size == 1
@sections = @sections.with_questions_count
diff --git a/app/controllers/questions_statuses_controller.rb b/app/controllers/questions_statuses_controller.rb
index 5f0cc22..a01d168 100644
--- a/app/controllers/questions_statuses_controller.rb
+++ b/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-2023 RedmineUP
+# Copyright (C) 2011-2024 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
@@ -18,7 +18,6 @@
# along with redmine_questions. If not, see .
class QuestionsStatusesController < ApplicationController
- unloadable
layout 'admin'
before_action :require_admin, :except => :index
diff --git a/app/helpers/questions_helper.rb b/app/helpers/questions_helper.rb
index 9b0662e..4f43d19 100644
--- a/app/helpers/questions_helper.rb
+++ b/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-2023 RedmineUP
+# Copyright (C) 2011-2024 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
@@ -20,9 +20,10 @@
# along with redmine_questions. If not, see .
module QuestionsHelper
- def question_status_tag(status)
+ def question_status_tag(status, editable=false)
return '' unless status
- content_tag(:span, status.name, :class => 'question-status-tag tag-label-color', :style => "background-color: #{status.color}")
+ content_tag(:span, status.name, class: "status-badge #{'editable' if editable}",
+ style: "color:#{status.color};border: 1px solid #{status.color};")
end
def allow_voting?(votable, user = User.current)
diff --git a/app/models/question.rb b/app/models/question.rb
index a8988a9..9b723bb 100644
--- a/app/models/question.rb
+++ b/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-2023 RedmineUP
+# Copyright (C) 2011-2024 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
@@ -17,8 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with redmine_questions. If not, see .
-class Question < ActiveRecord::Base
- unloadable
+class Question < ApplicationRecord
include Redmine::SafeAttributes
extend ApplicationHelper
@@ -31,12 +30,8 @@ class Question < ActiveRecord::Base
has_many :answers, :class_name => 'QuestionsAnswer', :dependent => :destroy
- if ActiveRecord::VERSION::MAJOR >= 4
- has_many :comments, lambda { order('created_on') }, :as => :commented, :dependent => :delete_all
- else
- has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
- end
- rcrm_acts_as_viewed
+ has_many :comments, lambda { order('created_on') }, :as => :commented, :dependent => :delete_all
+ up_acts_as_viewed
acts_as_attachable_questions
acts_as_watchable
@@ -47,30 +42,17 @@ class Question < ActiveRecord::Base
:description => :content,
:title => Proc.new {|o| o.subject }
+ acts_as_activity_provider :type => 'questions',
+ :permission => :view_questions,
+ :author_key => :author_id,
+ :timestamp => "#{table_name}.created_on",
+ :scope => joins({:section => :project}, :author)
- if ActiveRecord::VERSION::MAJOR >= 4
- acts_as_activity_provider :type => 'questions',
- :permission => :view_questions,
- :author_key => :author_id,
- :timestamp => "#{table_name}.created_on",
- :scope => joins({:section => :project}, :author)
- acts_as_searchable :columns => ["#{table_name}.subject",
- "#{table_name}.content",
- "#{QuestionsAnswer.table_name}.content"],
- :scope => eager_load({: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",
- "#{QuestionsAnswer.table_name}.content"],
- :include => [{:section => :project}, :answers],
- :project_key => "#{QuestionsSection.table_name}.project_id"
- end
+ acts_as_searchable :columns => ["#{table_name}.subject",
+ "#{table_name}.content",
+ "#{QuestionsAnswer.table_name}.content"],
+ :scope => eager_load({:section => :project}, :answers),
+ :project_key => "#{QuestionsSection.table_name}.project_id"
scope :solutions, lambda { joins(:section).where(:questions_sections => {:section_type => QuestionsSection::SECTION_TYPE_SOLUTIONS}) }
scope :questions, lambda { joins(:section).where(:questions_sections => {:section_type => QuestionsSection::SECTION_TYPE_QUESTIONS}) }
diff --git a/app/models/questions_answer.rb b/app/models/questions_answer.rb
index 3d74808..7edf329 100644
--- a/app/models/questions_answer.rb
+++ b/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-2023 RedmineUP
+# Copyright (C) 2011-2024 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
@@ -17,8 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with redmine_questions. If not, see .
-class QuestionsAnswer < ActiveRecord::Base
- unloadable
+class QuestionsAnswer < ApplicationRecord
include Redmine::SafeAttributes
extend ApplicationHelper
@@ -26,8 +25,6 @@ class QuestionsAnswer < ActiveRecord::Base
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
belongs_to :question, :counter_cache => 'answers_count', :touch => true
- attr_protected :id if ActiveRecord::VERSION::MAJOR <= 4
-
acts_as_attachable_questions
acts_as_event :datetime => :created_on,
@@ -37,19 +34,11 @@ class QuestionsAnswer < ActiveRecord::Base
:description => :content,
:title => Proc.new {|o| o.question.subject }
- if ActiveRecord::VERSION::MAJOR >= 4
acts_as_activity_provider :type => 'questions',
:permission => :view_questions,
:author_key => :author_id,
:timestamp => "#{table_name}.created_on",
:scope => joins({ :question => { :section => :project } }, :author)
- else
- acts_as_activity_provider :type => 'questions',
- :permission => :view_questions,
- :author_key => :author_id,
- :timestamp => "#{table_name}.created_on",
- :find_options => { :joins => [{ :question => { :section => :project } }, :author] }
- end
scope :visible, lambda {|*args| where(Question.visible_condition(args.shift || User.current)) }
scope :by_votes, lambda { order("#{table_name}.cached_weighted_score DESC") }
diff --git a/app/models/questions_section.rb b/app/models/questions_section.rb
index a535ec7..09af2d7 100644
--- a/app/models/questions_section.rb
+++ b/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-2023 RedmineUP
+# Copyright (C) 2011-2024 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
@@ -17,14 +17,13 @@
# You should have received a copy of the GNU General Public License
# along with redmine_questions. If not, see .
-class QuestionsSection < ActiveRecord::Base
- unloadable
+class QuestionsSection < ApplicationRecord
+
include Redmine::SafeAttributes
belongs_to :project
has_many :questions, :foreign_key => "section_id", :dependent => :destroy
- attr_protected :id if ActiveRecord::VERSION::MAJOR <= 4
safe_attributes 'name', 'project', 'position', 'description', 'section_type'
scope :with_questions_count, lambda {
@@ -39,7 +38,7 @@ class QuestionsSection < ActiveRecord::Base
}
scope :sorted, lambda { order(:position) }
- rcrm_acts_as_list :scope => 'project_id = #{project_id}'
+ up_acts_as_list :scope => 'project_id = #{project_id}'
acts_as_watchable
SECTION_TYPE_QUESTIONS = 'questions'
diff --git a/app/models/questions_settings.rb b/app/models/questions_settings.rb
index a656960..18e94e7 100644
--- a/app/models/questions_settings.rb
+++ b/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-2023 RedmineUP
+# Copyright (C) 2011-2024 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
@@ -18,7 +18,6 @@
# along with redmine_questions. If not, see .
class QuestionsSettings
- unloadable
IDEA_COLORS = {
:green => 'green',
@@ -29,7 +28,7 @@ class QuestionsSettings
:orange => 'orange',
:red => 'red',
:purple => 'purple',
- :gray => 'gray'
+ :gray => 'gray'
}
class << self
diff --git a/app/models/questions_status.rb b/app/models/questions_status.rb
index 7154c06..4e8b17a 100644
--- a/app/models/questions_status.rb
+++ b/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-2023 RedmineUP
+# Copyright (C) 2011-2024 RedmineUP
# http://www.redmineup.com/
#
# redmine_questions is free software: you can redistribute it and/or modify
@@ -17,20 +17,18 @@
# You should have received a copy of the GNU General Public License
# along with redmine_questions. If not, see .
-class QuestionsStatus < ActiveRecord::Base
- unloadable
+class QuestionsStatus < ApplicationRecord
include Redmine::SafeAttributes
belongs_to :question
- attr_protected :id if ActiveRecord::VERSION::MAJOR <= 4
safe_attributes 'name', 'is_closed', 'position', 'color'
validates :name, presence: true, uniqueness: true
scope :sorted, lambda { order(:position) }
- rcrm_acts_as_list
+ up_acts_as_list
def to_s
name
diff --git a/app/views/auto_completes/_questions_tags.json.erb b/app/views/auto_completes/_questions_tags.json.erb
deleted file mode 100644
index 987c6f5..0000000
--- a/app/views/auto_completes/_questions_tags.json.erb
+++ /dev/null
@@ -1,6 +0,0 @@
-<%= raw @questions_tags.map { |question_tag| {
- 'id' => @names_only ? question_tag.name : question_tag.id,
- 'text' => question_tag.name
- }
- }.to_json
-%>
diff --git a/app/views/questions/_question.html.erb b/app/views/questions/_question.html.erb
index bd55d58..b9e18fb 100644
--- a/app/views/questions/_question.html.erb
+++ b/app/views/questions/_question.html.erb
@@ -6,22 +6,22 @@
%>
-
<%=h @question_item.subject %>
+<%=h @question_item.subject %>
<%= render :partial => 'question_item', :object => @question_item %>
<% if @question_item.section.allow_answering? %>
<% if @answers.any? %>
<%= l(:label_questions_answer_plural) %> (<%= @answer_count %>)
- <% @answers.each do |answer| %>
- <%= render :partial => 'questions_answers/answer_item', :locals => { :question_item => answer } %>
+ <% @answers.find_each do |answer| %>
+ <%= render :partial => 'questions_answers/answer_item', :locals => { :question_item => answer } %>
<% end %>
<% end %>
<% if @question_item.allow_answering? && User.current.allowed_to?(:add_answers, @project) %>
-
<%= l(:label_questions_your_answer) %>
-
+
<%= toggle_link l(:button_reply), "reply", :focus => 'answer_content' %>
+
<%= form_for @answer, :as => :answer, :url => question_answers_path(@question_item), :html => {:multipart => true, :id => 'answer-form'} do |f| %>
<%= render :partial => 'questions_answers/form', :locals => {:f => f, :replying => true} %>
<%= submit_tag l(:button_submit) %>
diff --git a/app/views/questions/_question_list.html.erb b/app/views/questions/_question_list.html.erb
index af8a25d..c15e091 100644
--- a/app/views/questions/_question_list.html.erb
+++ b/app/views/questions/_question_list.html.erb
@@ -23,7 +23,7 @@
<%= link_to h(question.subject), { :controller => 'questions', :action => 'show', :project_id => question.project, :id => question } %>
<%= question_status_tag(question.status) %>
-
<%= truncate(Question.to_text(textilizable(question.content)), :length => 100) %>
+
<%= Question.to_text(textilizable(truncate(question.content, :length => 100))) %>
<%= submit_tag l(:button_save) %>
- <%= preview_link({:controller => 'questions', :action => 'preview', :question_id => @question_item}, 'question_form') if Redmine::VERSION.to_s <= '3.4.5' %>
| <%= link_to l(:button_cancel), question_path(@question_item) %>
<% end %>
diff --git a/app/views/questions/new.html.erb b/app/views/questions/new.html.erb
index 6dd25ca..eede9e3 100644
--- a/app/views/questions/new.html.erb
+++ b/app/views/questions/new.html.erb
@@ -6,7 +6,6 @@
<%= render partial: 'form', locals: { f: f } %>
<%= submit_tag l(:button_create) %>
- <% preview_link({ controller: 'questions', action: 'preview', id: @question_item }, 'question_form') if Redmine::VERSION.to_s <= '3.4.5' %>
<% end %>
diff --git a/app/views/questions_answers/edit.html.erb b/app/views/questions_answers/edit.html.erb
index bb93a46..762f988 100644
--- a/app/views/questions_answers/edit.html.erb
+++ b/app/views/questions_answers/edit.html.erb
@@ -5,7 +5,6 @@
<%= back_url_hidden_field_tag %>
<%= render :partial => 'form', :locals => {:f => f} %>
<%= submit_tag l(:button_save) %>
- <%= preview_link(preview_questions_answers_path(@answer), 'answer-form') if Redmine::VERSION.to_s <= '3.4.5' %>
| <%= link_to l(:button_cancel), question_path(@answer.question, :anchor => "question_item_#{@answer.id}") %>
<% end %>
diff --git a/app/views/questions_comments/_comment.html.erb b/app/views/questions_comments/_comment.html.erb
index 2f4d008..8deadca 100644
--- a/app/views/questions_comments/_comment.html.erb
+++ b/app/views/questions_comments/_comment.html.erb
@@ -1,3 +1,4 @@
+<% allowed_to_edit = User.current.allowed_to?(:edit_question_comments, comment.commented.project) || (comment.author == User.current && User.current.allowed_to?(:edit_own_question_comments, comment.commented.project)) %>
-
diff --git a/app/views/questions_comments/_comment_list.html.erb b/app/views/questions_comments/_comment_list.html.erb
index 8442b49..1917bc9 100644
--- a/app/views/questions_comments/_comment_list.html.erb
+++ b/app/views/questions_comments/_comment_list.html.erb
@@ -1,6 +1,6 @@
<% if question_item.comments.any? %>