Actualizar plugin Questions a 1.0.2 light
This commit is contained in:
parent
b9e569d03f
commit
b37d1305f1
64 changed files with 394 additions and 229 deletions
34
plugins/redmine_questions/.drone.jsonnet
Normal file
34
plugins/redmine_questions/.drone.jsonnet
Normal file
|
@ -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", ""),
|
||||
]
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) }
|
||||
|
||||
|
|
|
@ -1,36 +1,41 @@
|
|||
<% @project_sections = QuestionsSection.for_project(@project).sorted %>
|
||||
<h3><%= l(:label_questions_sections_plural) %></h3>
|
||||
|
||||
<table class="list questions_sections">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><%= l(:field_name) %></th>
|
||||
<th><%=l(:field_type)%></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% QuestionsSection.for_project(@project).sorted.each do |section| %>
|
||||
<tr class="<%= cycle 'odd', 'even' %>">
|
||||
<td class="name">
|
||||
<%= h(section.name) %>
|
||||
</td>
|
||||
<td>
|
||||
<%= section.l_type %>
|
||||
</td>
|
||||
<td class="buttons">
|
||||
<% 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 %>
|
||||
</td>
|
||||
<% if @project_sections.any? %>
|
||||
<table class="list questions_sections">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><%= l(:field_name) %></th>
|
||||
<th><%=l(:field_type)%></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @project_sections.each do |section| %>
|
||||
<tr class="<%= cycle 'odd', 'even' %>">
|
||||
<td class="name">
|
||||
<%= h(section.name) %>
|
||||
</td>
|
||||
<td>
|
||||
<%= section.l_type %>
|
||||
</td>
|
||||
<td class="buttons">
|
||||
<% 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), edit_questions_section_path(section, project_id: @project), class: 'icon icon-edit' %>
|
||||
<%= delete_link questions_section_path(section, project_id: @project) %>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% else %>
|
||||
<p class="nodata"><%= l(:label_no_data) %></p>
|
||||
<% 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 %>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<%= f.text_field :subject, :id => "question_subject", :size => 120%>
|
||||
</p>
|
||||
<p><label><%= l(:label_questions_section) %></label><br />
|
||||
<%= 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({
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="question<%= " votable" if question_item.allow_voting? %> div-table" id="question_<%= question_item.id %>">
|
||||
<a href="#<%= question_item.id %>" class="wiki-anchor"></a>
|
||||
<% if question_item.allow_voting? && User.current.allowed_to?(:vote_questions, @project) %>
|
||||
<% if question_item.allow_voting? %>
|
||||
<div class="vote">
|
||||
<%= render :partial => 'questions_votes/question_item_vote', :locals => {:question_item => question_item} %>
|
||||
</div>
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
<%= render :partial => 'form', :locals => {:f => f} %>
|
||||
</div>
|
||||
<%= submit_tag l(:button_save) %>
|
||||
<%= preview_link({:controller => 'questions', :action => 'preview', :question_id => @question_item}, 'question_form') %>
|
||||
<%= 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 %>
|
||||
<div id="preview" class="wiki"></div>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<div class="filters">
|
||||
<%= form_tag({:controller => "questions", :action => "index"}, :method => :get, :id => "query_form") do %>
|
||||
<%= text_field_tag(:topic_search, params[:topic_search], :autocomplete => "off", :class => "questions-search", :placeholder => l(:label_questions_search) ) %>
|
||||
<%= javascript_tag "observeSearchfield('topic_search', 'topics_list', '#{ escape_javascript(autocomplete_for_subject_questions_path(:project_id => @project, :section_id => @section)) }')" %>
|
||||
<%= javascript_tag "observeSearchfield('topic_search', 'topics_list', '#{ escape_javascript(autocomplete_for_subject_questions_path(:project_id => @project, :section_id => @section, :sort_order => @sort_order)) }')" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<h2><%= l(:label_message_new) %></h2>
|
||||
|
||||
<%= form_for @question_item, { :url => questions_path, :html => {:multipart => true,
|
||||
<%= form_for @question_item, { :url => project_questions_path(@project, {}), :html => {:multipart => true,
|
||||
:id => 'question_form'}} do |f| %>
|
||||
<div id="all_attributes">
|
||||
<%= render :partial => 'form', :locals => {:f => f} %>
|
||||
<%= render partial: 'form', locals: { f: f } %>
|
||||
</div>
|
||||
<%= submit_tag l(:button_create) %>
|
||||
<% preview_link({:controller => 'questions', :action => 'preview', :id => @question_item}, 'question_form') %>
|
||||
<% preview_link({ controller: 'questions', action: 'preview', id: @question_item }, 'question_form') if Redmine::VERSION.to_s <= '3.4.5' %>
|
||||
<% end %>
|
||||
|
||||
<div id="preview" class="wiki"></div>
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
<div class="contextual">
|
||||
<%= link_to(l(:button_edit), edit_questions_answer_path(question_item), :class => 'icon icon-edit') if question_item.editable_by?(User.current) %>
|
||||
<%= link_to(l(:button_delete), questions_answer_path(question_item), :method => :delete, :data => {:confirm => l(:text_are_you_sure)}, :class => 'icon icon-del') if question_item.destroyable_by?(User.current)
|
||||
<% if question_item.editable_by?(User.current) %>
|
||||
<%= link_to(l(:button_edit), edit_questions_answer_path(question_item), :class => 'icon icon-edit') %>
|
||||
<% elsif User.current.allowed_to?(:accept_answers, @project) && !question_item.accepted? %>
|
||||
<%= link_to(l(:label_questions_accept), questions_answer_path(question_item, answer: {accepted: true}), method: :put, :class => 'icon icon-accept') %>
|
||||
<% elsif User.current.allowed_to?(:accept_answers, @project) && question_item.accepted? %>
|
||||
<%= link_to(l(:label_questions_discard), questions_answer_path(question_item, answer: {accepted: false}), method: :put, :class => 'icon icon-discard') %>
|
||||
<% end %>
|
||||
<%= link_to(l(:button_delete), questions_answer_path(question_item), :method => :delete, :data => {:confirm => l(:text_are_you_sure)}, :class => 'icon icon-del') if question_item.destroyable_by?(User.current)
|
||||
%>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="question answer<%= ' votable' if question_item.allow_voting? %> div-table" id="questions_answer_<%= question_item.id %>">
|
||||
<a href="#<%= question_item.id %>" class="wiki-anchor"></a>
|
||||
<% if question_item.allow_voting? && User.current.allowed_to?(:vote_questions, @project) %>
|
||||
<% if question_item.allow_voting? %>
|
||||
<div class="vote" >
|
||||
<%= render :partial => 'questions_votes/question_item_vote', :locals => {:question_item => question_item } %>
|
||||
</div>
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<%= 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') %>
|
||||
|
||||
<%= 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 %>
|
||||
<div id="preview" class="wiki"></div>
|
||||
|
||||
|
|
|
@ -1,29 +1,25 @@
|
|||
<% previous_group = false %>
|
||||
<div class="section-list">
|
||||
<% @sections.each do |section| %>
|
||||
<% if @project.blank? && (group = section.project) != previous_group %>
|
||||
<% reset_cycle %>
|
||||
<% @sections.group_by(&:project).each do |project, sections| %>
|
||||
<% if @project.blank? %>
|
||||
<div class="project-forums">
|
||||
<h3>
|
||||
<%= project.name %>
|
||||
<%= link_to " \xc2\xbb", project_questions_sections_path(project_id: project.identifier) %>
|
||||
</h3>
|
||||
</div>
|
||||
<% if group %>
|
||||
<div class="project-forums">
|
||||
<h3>
|
||||
<%= group.name %>
|
||||
<%= link_to " \xc2\xbb", project_questions_sections_path(:project_id => group.identifier) %>
|
||||
</h3>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="section-list">
|
||||
<% previous_group = group %>
|
||||
<% end %>
|
||||
|
||||
<a href="<%= url_for({:controller => "questions", :action => 'index', :section_id => section, :project_id => section.project}) %>" id="section_<%= section.id %>" class="section-tile">
|
||||
<h4>
|
||||
<%= section.name %>
|
||||
<span class="topic-count"><%= "(#{section.questions_count})" %></span>
|
||||
</h4>
|
||||
<div class="description">
|
||||
<%= section.description %>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="section-list">
|
||||
<% sections.each do |section| %>
|
||||
<a id="section_<%= section.id %>" class="section-tile"
|
||||
href="<%= url_for({ controller: "questions", action: 'index', section_id: section, project_id: section.project }) %>">
|
||||
<h4>
|
||||
<%= section.name %>
|
||||
<span class="topic-count"><%= "(#{section.questions_count})" %></span>
|
||||
</h4>
|
||||
<div class="description">
|
||||
<%= section.description %>
|
||||
</div>
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
|
|
@ -26,4 +26,3 @@
|
|||
<% content_for :header_tags do %>
|
||||
<%= javascript_include_tag :questions, :plugin => 'redmine_questions' %>
|
||||
<% end %>
|
||||
|
||||
|
|
BIN
plugins/redmine_questions/assets/images/accept.png
Normal file
BIN
plugins/redmine_questions/assets/images/accept.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 781 B |
BIN
plugins/redmine_questions/assets/images/discard.png
Normal file
BIN
plugins/redmine_questions/assets/images/discard.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
|
@ -400,3 +400,5 @@ div.question.votable .question-container .contextual {margin-top: 0px;}
|
|||
.icon-tag { background-image: url(../images/tag_blue.png); }
|
||||
.icon-question { background-image: url(../../../images/help.png); }
|
||||
.icon-solution { background-image: url(../images/book_open.png); }
|
||||
.icon-accept { background-image: url(../images/accept.png); }
|
||||
.icon-discard { background-image: url(../images/discard.png); }
|
|
@ -169,4 +169,6 @@ en:
|
|||
permission_vote_questions: Vote questions
|
||||
permission_accept_answers: Accept answers
|
||||
permission_manage_sections: Manage sections
|
||||
permission_create_tags: Create new tags
|
||||
permission_create_tags: Create new tags
|
||||
label_questions_discard: Discard
|
||||
permission_edit_own_answers: Edit own answers
|
|
@ -22,8 +22,6 @@ es:
|
|||
|
||||
field_questions_tags: Etiquetas
|
||||
|
||||
label_questions_most_popular: Más populares
|
||||
|
||||
permission_view_questions: Ver Ayuda y Soporte
|
||||
permission_edit_messages_tags: Editar etiquetas
|
||||
permission_edit_vote_messages: Votar mensajes
|
|
@ -94,4 +94,6 @@ ru:
|
|||
permission_vote_questions: Голосовать за вопросы
|
||||
permission_accept_answers: Принимать ответы
|
||||
permission_manage_sections: Управлять секциями
|
||||
permission_create_tags: Создавать новые тэги
|
||||
permission_create_tags: Создавать новые тэги
|
||||
label_questions_discard: Не принимать
|
||||
permission_edit_own_answers: Редактировать свои ответы
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,9 +1,27 @@
|
|||
== Redmine Q&A plugin changelog
|
||||
|
||||
Redmine Q&A plugin
|
||||
Copyright (C) 2011-2018 RedmineUP
|
||||
Copyright (C) 2011-2020 RedmineUP
|
||||
https://www.redmineup.com/
|
||||
|
||||
== 2020-03-03 v1.0.2
|
||||
|
||||
* Redmine 4.1 support
|
||||
* Fixed section position bug
|
||||
* Fixed MSSQL group by bug
|
||||
* Fixed "Help & Support" page layout
|
||||
|
||||
== 2019-08-23 v1.0.1
|
||||
|
||||
* Accept answer links
|
||||
* Edit own answers permission
|
||||
* Redmine 4 support
|
||||
* Fixed sorting by unanswered question not working
|
||||
* Fixed project variable dismissed
|
||||
* Fixed status creating bug
|
||||
* Fixed preview link, empty project bug
|
||||
* Fixed boards migration bug
|
||||
|
||||
== 2018-08-31 v1.0.0
|
||||
|
||||
* Separate models for questions, answers and comments
|
||||
|
|
|
@ -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
|
||||
|
@ -17,11 +17,11 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with redmine_questions. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
requires_redmine_crm version_or_higher: '0.0.38'
|
||||
requires_redmine_crm version_or_higher: '0.0.41'
|
||||
|
||||
require 'redmine_questions'
|
||||
|
||||
QA_VERSION_NUMBER = '1.0.0'
|
||||
QA_VERSION_NUMBER = '1.0.2'
|
||||
QA_VERSION_TYPE = "Light version"
|
||||
|
||||
Redmine::Plugin.register :redmine_questions do
|
||||
|
@ -47,6 +47,7 @@ Redmine::Plugin.register :redmine_questions do
|
|||
permission :add_questions, { questions: [:create, :new, :preview, :update_form] }
|
||||
permission :edit_questions, { questions: [:edit, :update, :preview, :update_form], questions_answers: [:edit, :update, :preview] }, require: :loggedin
|
||||
permission :edit_own_questions, {questions: [:edit, :update, :preview, :update_form]}, require: :loggedin
|
||||
permission :edit_own_answers, {questions_answers: [:edit, :update, :preview]}, require: :loggedin
|
||||
permission :add_answers, { questions_answers: [:create, :show, :new, :edit, :update, :preview] }
|
||||
permission :view_questions, { questions: [:index, :show, :autocomplete_for_subject], questions_sections: [:index] }, read: true
|
||||
permission :delete_questions, { questions: [:destroy] }, require: :loggedin
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -70,6 +70,7 @@ module Redmine
|
|||
end
|
||||
|
||||
def save_attachments(attachments, author = User.current)
|
||||
attachments = attachments.to_unsafe_hash if attachments.respond_to?(:to_unsafe_hash)
|
||||
attachments = attachments.values if attachments.is_a?(Hash)
|
||||
if attachments.is_a?(Array)
|
||||
attachments.each do |attachment|
|
||||
|
|
|
@ -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
|
||||
|
@ -28,5 +28,3 @@ require_dependency 'redmine_questions/patches/auto_completes_controller_patch'
|
|||
require_dependency 'redmine_questions/patches/comment_patch'
|
||||
|
||||
require_dependency 'acts_as_attachable_questions/init'
|
||||
|
||||
require 'redmine_questions/patches/compatibility/application_controller_patch' if Rails::VERSION::MAJOR < 4
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
# This file is a part of Redmine Q&A (redmine_questions) plugin,
|
||||
# Q&A plugin for Redmine
|
||||
#
|
||||
# Copyright (C) 2011-2018 RedmineUP
|
||||
# http://www.redmineup.com/
|
||||
#
|
||||
# redmine_questions is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# redmine_questions is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with redmine_questions. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
module RedmineQuestions
|
||||
module Patches
|
||||
module ApplicationControllerPatch
|
||||
def self.included(base) # :nodoc:
|
||||
base.class_eval do
|
||||
unloadable # Send unloadable so it will not be unloaded in development
|
||||
class << self
|
||||
alias_method :before_action, :before_filter
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
unless ApplicationController.included_modules.include?(RedmineQuestions::Patches::ApplicationControllerPatch)
|
||||
ApplicationController.send(:include, RedmineQuestions::Patches::ApplicationControllerPatch)
|
||||
end
|
|
@ -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
|
||||
|
@ -20,8 +20,15 @@
|
|||
module RedmineQuestions
|
||||
module Patches
|
||||
module MailerPatch
|
||||
|
||||
module ClassMethods
|
||||
def deliver_question_comment_added(comment)
|
||||
question_comment_added(User.current, comment).deliver_later
|
||||
end
|
||||
end
|
||||
|
||||
module InstanceMethods
|
||||
def question_comment_added(comment)
|
||||
def question_comment_added(_user = User.current, comment)
|
||||
question = comment.commented.is_a?(Question) ? comment.commented : comment.commented.question
|
||||
@question_url = url_for(:controller => 'questions', :action => 'show', :id => question.id)
|
||||
project_identifier = question.project.try(:identifier)
|
||||
|
@ -36,7 +43,7 @@ module RedmineQuestions
|
|||
:subject => "[#{project_prefix}] RE: #{question.subject}"
|
||||
end
|
||||
|
||||
def question_question_added(question)
|
||||
def question_question_added(_user = Current.user, question)
|
||||
@question_url = url_for(:controller => 'questions', :action => 'show', :id => question.id)
|
||||
project_identifier = question.project.try(:identifier)
|
||||
redmine_headers 'Project' => project_identifier, 'Question-Id' => question.id
|
||||
|
@ -51,9 +58,9 @@ module RedmineQuestions
|
|||
:subject => "[#{project_prefix}] #{question.subject}"
|
||||
end
|
||||
|
||||
def question_answer_added(answer)
|
||||
def question_answer_added(_user = Current.user, answer)
|
||||
question = answer.question
|
||||
@question_url = url_for(:controller => 'questions', :action => 'show', :id => question.id)
|
||||
@question_url = url_for(controller: 'questions', action: 'show', id: question.id)
|
||||
project_identifier = question.project.try(:identifier)
|
||||
redmine_headers 'Project' => project_identifier, 'Question-Id' => question.id
|
||||
message_id question
|
||||
|
@ -66,13 +73,14 @@ module RedmineQuestions
|
|||
@answer = answer
|
||||
@question = question
|
||||
project_prefix = [project_identifier, question.section_name, "q&a#{question.id}"].compact.join(' - ')
|
||||
mail :to => recipients,
|
||||
:cc => cc,
|
||||
:subject => "[#{project_prefix}] - answ##{answer.id} - RE: #{question.subject}"
|
||||
mail to: recipients,
|
||||
cc: cc,
|
||||
subject: "[#{project_prefix}] - answ##{answer.id} - RE: #{question.subject}"
|
||||
end
|
||||
end
|
||||
|
||||
def self.included(receiver)
|
||||
receiver.send :extend, ClassMethods
|
||||
receiver.send :include, InstanceMethods
|
||||
receiver.class_eval do
|
||||
unloadable
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -38,13 +38,13 @@ END_DESC
|
|||
next
|
||||
end
|
||||
|
||||
question_attrs = topic.attributes.slice('subject', 'content', 'author_id', 'locked').merge('project_id' => project.try(:id))
|
||||
question_attrs = topic.attributes.slice('subject', 'content', 'author_id', 'locked')
|
||||
migrated_question = section.questions.create(question_attrs)
|
||||
migrated_question.attachments = topic.attachments.map { |attachment| attachment.copy }
|
||||
|
||||
topic.children.each do |reply|
|
||||
if section.section_type == 'questions'
|
||||
answer_attrs = reply.slice('subject', 'content', 'author_id', 'locked').merge('project_id' => project.try(:id))
|
||||
answer_attrs = reply.slice('subject', 'content', 'author_id', 'locked')
|
||||
migrated_answer = migrated_question.answers.create(answer_attrs)
|
||||
migrated_answer.attachments = reply.attachments.map { |attachment| attachment.copy }
|
||||
else
|
||||
|
|
|
@ -9,4 +9,10 @@ answer_002:
|
|||
content: This is answer for question_002
|
||||
question_id: 2
|
||||
author_id: 1
|
||||
accepted: false
|
||||
accepted: false
|
||||
answer_003:
|
||||
id: 3
|
||||
content: This is a second answer for question_001
|
||||
question_id: 1
|
||||
author_id: 3
|
||||
accepted: false
|
10
plugins/redmine_questions/test/fixtures/questions_statuses.yml
vendored
Normal file
10
plugins/redmine_questions/test/fixtures/questions_statuses.yml
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
section_001:
|
||||
id: 1
|
||||
name: Open
|
||||
color: green
|
||||
is_closed: false
|
||||
section_002:
|
||||
id: 2
|
||||
name: Closed
|
||||
color: red
|
||||
is_closed: true
|
|
@ -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
|
||||
|
@ -79,7 +79,7 @@ class QuestionsAnswersControllerTest < ActionController::TestCase
|
|||
assert_redirected_to :controller => 'questions',
|
||||
:action => 'show',
|
||||
:id => question,
|
||||
:anchor => "question_item_#{QuestionsAnswer.order(:id).last.id}"
|
||||
:anchor => "questions_answer_#{QuestionsAnswer.order(:id).last.id}"
|
||||
assert_equal old_answer_count + 1, question.answers.count
|
||||
assert_equal 'Answer for the first question', question.answers.last.content
|
||||
end
|
||||
|
@ -92,11 +92,7 @@ class QuestionsAnswersControllerTest < ActionController::TestCase
|
|||
:content => "Previewed answer",
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'fieldset' do
|
||||
assert_select 'legend', :text => 'Preview'
|
||||
assert_select 'p', :text => 'Previewed answer'
|
||||
end
|
||||
|
||||
assert_select 'p', :text => 'Previewed answer'
|
||||
end
|
||||
|
||||
def test_preview_edited_answer
|
||||
|
@ -107,11 +103,7 @@ class QuestionsAnswersControllerTest < ActionController::TestCase
|
|||
:content => "Previewed answer 1",
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'fieldset' do
|
||||
assert_select 'legend', :text => 'Preview'
|
||||
assert_select 'p', :text => 'Previewed answer 1'
|
||||
end
|
||||
|
||||
assert_select 'p', :text => 'Previewed answer 1'
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
|
@ -121,7 +113,7 @@ class QuestionsAnswersControllerTest < ActionController::TestCase
|
|||
assert_difference 'QuestionsAnswer.count', -1 do
|
||||
compatible_request :post, :destroy, :id => answer.id
|
||||
end
|
||||
assert_redirected_to question_path(answer.question, :anchor => "question_item_#{answer.id}")
|
||||
assert_redirected_to question_path(answer.question, :anchor => "questions_answer_#{answer.id}")
|
||||
assert_nil QuestionsAnswer.find_by_id(answer.id)
|
||||
end
|
||||
|
||||
|
@ -144,6 +136,6 @@ class QuestionsAnswersControllerTest < ActionController::TestCase
|
|||
}
|
||||
# assert_response :success
|
||||
answer.reload
|
||||
assert !answer.accepted, "Mark as officail answer did set for answer after update for user without permission"
|
||||
assert !answer.accepted, "Mark as official answer did set for answer after update for user without permission"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
@ -22,8 +22,8 @@
|
|||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class QuestionsCommentsControllerTest < ActionController::TestCase
|
||||
fixtures :users,
|
||||
:projects,
|
||||
fixtures :users,
|
||||
:projects,
|
||||
:roles,
|
||||
:members,
|
||||
:member_roles,
|
||||
|
@ -38,7 +38,7 @@ class QuestionsCommentsControllerTest < ActionController::TestCase
|
|||
:issue_categories,
|
||||
:enabled_modules,
|
||||
:workflows,
|
||||
:questions,
|
||||
:questions,
|
||||
:questions_answers,
|
||||
:questions_sections
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -22,8 +22,8 @@
|
|||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class QuestionsControllerTest < ActionController::TestCase
|
||||
fixtures :users,
|
||||
:projects,
|
||||
fixtures :users,
|
||||
:projects,
|
||||
:roles,
|
||||
:members,
|
||||
:member_roles,
|
||||
|
@ -40,14 +40,13 @@ class QuestionsControllerTest < ActionController::TestCase
|
|||
:attachments,
|
||||
:workflows,
|
||||
:time_entries,
|
||||
:questions,
|
||||
:questions_answers,
|
||||
:questions,
|
||||
:questions_answers,
|
||||
:questions_sections
|
||||
|
||||
fixtures :email_addresses if ActiveRecord::VERSION::MAJOR >= 4
|
||||
|
||||
RedmineQuestions::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_questions).directory + '/test/fixtures/',
|
||||
[:tags, :taggings, :comments])
|
||||
RedmineQuestions::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_questions).directory + '/test/fixtures/', [:tags, :taggings, :comments])
|
||||
|
||||
def setup
|
||||
RedmineQuestions::TestCase.prepare
|
||||
|
@ -77,6 +76,34 @@ class QuestionsControllerTest < ActionController::TestCase
|
|||
assert_select 'p.breadcrumb'
|
||||
end
|
||||
|
||||
def test_get_new
|
||||
@request.session[:user_id] = 1
|
||||
compatible_request :get, :new, project_id: @project
|
||||
|
||||
assert_select 'input#question_subject'
|
||||
assert_select 'select#question_section_id'
|
||||
assert_select 'input[type=?]', 'submit'
|
||||
end
|
||||
|
||||
def test_get_edit
|
||||
@request.session[:user_id] = 1
|
||||
compatible_request :get, :edit, id: 1
|
||||
|
||||
assert_select 'input#question_subject'
|
||||
assert_select 'select#question_section_id'
|
||||
assert_select 'input[type=?]', 'submit'
|
||||
end
|
||||
|
||||
def test_post_create_failed
|
||||
@request.session[:user_id] = 1
|
||||
compatible_request :post, :create, :project_id => @project,
|
||||
:question => {
|
||||
|
||||
:content => "Body of text"
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_post_create
|
||||
@request.session[:user_id] = 1
|
||||
ActionMailer::Base.deliveries.clear
|
||||
|
@ -118,7 +145,7 @@ class QuestionsControllerTest < ActionController::TestCase
|
|||
assert_select 'div#reply'
|
||||
assert_select 'a.icon-del'
|
||||
assert_select 'a.add-comment-link'
|
||||
assert_select 'span.items', {:text => "(1-1/1)"}
|
||||
assert_select 'span.items', {:text => "(1-2/2)"}
|
||||
@dev_role.permissions << :add_answers
|
||||
@dev_role.save
|
||||
@request.session[:user_id] = 3
|
||||
|
@ -164,20 +191,17 @@ class QuestionsControllerTest < ActionController::TestCase
|
|||
end
|
||||
assert_redirected_to questions_path(:section_id => question.section)
|
||||
assert_nil Question.find_by_id(question.id)
|
||||
end
|
||||
end
|
||||
|
||||
def test_preview_new_question
|
||||
@request.session[:user_id] = 1
|
||||
question = questions(:question_001)
|
||||
compatible_xhr_request :post, :preview,
|
||||
compatible_xhr_request :post, :preview,
|
||||
:question => {
|
||||
:content => "Previewed question",
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'fieldset' do
|
||||
assert_select 'legend', :text => 'Preview'
|
||||
assert_select 'p', :text => 'Previewed question'
|
||||
end
|
||||
assert_select 'p', :text => 'Previewed question'
|
||||
end
|
||||
|
||||
def test_update_question
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
# encoding: utf-8
|
||||
#
|
||||
# This file is a part of Redmine Q&A (redmine_questions) plugin,
|
||||
# Q&A plugin for Redmine
|
||||
#
|
||||
# Copyright (C) 2011-2020 RedmineUP
|
||||
# http://www.redmineup.com/
|
||||
#
|
||||
# redmine_questions is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# redmine_questions is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with redmine_questions. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class QuestionsStatusesControllerTest < ActionController::TestCase
|
||||
fixtures :users,
|
||||
:projects,
|
||||
:roles,
|
||||
:members,
|
||||
:member_roles,
|
||||
:trackers,
|
||||
:enumerations,
|
||||
:projects_trackers,
|
||||
:issues,
|
||||
:issue_statuses,
|
||||
:versions,
|
||||
:trackers,
|
||||
:projects_trackers,
|
||||
:issue_categories,
|
||||
:enabled_modules,
|
||||
:workflows,
|
||||
:questions,
|
||||
:questions_answers,
|
||||
:questions_sections
|
||||
|
||||
fixtures :email_addresses if ActiveRecord::VERSION::MAJOR >= 4
|
||||
|
||||
RedmineQuestions::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_questions).directory + '/test/fixtures/', [:questions,
|
||||
:questions_answers,
|
||||
:questions_sections,
|
||||
:questions_statuses])
|
||||
|
||||
def setup
|
||||
RedmineQuestions::TestCase.prepare
|
||||
@project = Project.find(1)
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_new
|
||||
@request.session[:user_id] = 1
|
||||
compatible_request :get, :new
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input#questions_status_name'
|
||||
assert_select 'input[type=?]', 'submit'
|
||||
end
|
||||
|
||||
def test_create
|
||||
@request.session[:user_id] = 1
|
||||
assert_difference 'QuestionsStatus.count' do
|
||||
compatible_request :post, :create, questions_status: { name: 'Test status', color: 'green', is_closed: '0' }
|
||||
end
|
||||
assert_equal 'Test status', QuestionsStatus.last.name
|
||||
end
|
||||
|
||||
def test_delete
|
||||
@request.session[:user_id] = 1
|
||||
|
||||
status = QuestionsStatus.find(1)
|
||||
assert_difference 'QuestionsStatus.count', -1 do
|
||||
compatible_request :delete, :destroy, id: status
|
||||
end
|
||||
assert_nil QuestionsStatus.where(id: status.id).first
|
||||
end
|
||||
|
||||
def test_update
|
||||
@request.session[:user_id] = 1
|
||||
|
||||
status = QuestionsStatus.find(1)
|
||||
compatible_request :put, :update, id: status, questions_status: { name: 'New name', color: 'green', is_closed: '0' }
|
||||
status.reload
|
||||
assert_equal status.name, 'New name'
|
||||
end
|
||||
end
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -74,7 +74,7 @@ class RedmineQuestions::TestCase
|
|||
end
|
||||
|
||||
def self.prepare
|
||||
Role.where(:id => [1, 3]).each do |r|
|
||||
Role.where(:id => 1).each do |r|
|
||||
# user_2
|
||||
r.permissions << :view_questions
|
||||
r.permissions << :global_view_questions
|
||||
|
@ -103,11 +103,6 @@ class RedmineQuestions::TestCase
|
|||
r.save
|
||||
end
|
||||
|
||||
Role.where(:id => 1).each do |r|
|
||||
r.permissions << :accept_answers
|
||||
r.save
|
||||
end
|
||||
|
||||
Project.where(:id => [1, 2, 3, 4, 5]).each do |project|
|
||||
EnabledModule.create(:project => project, :name => 'questions')
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue