Actualizar plugin Questions a 1.0.2 light

This commit is contained in:
Manuel Cillero 2020-11-22 21:40:10 +01:00
parent b9e569d03f
commit b37d1305f1
64 changed files with 394 additions and 229 deletions

View 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", ""),
]

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify
@ -34,9 +34,11 @@ class QuestionsAnswersController < ApplicationController
end end
def edit def edit
(render_403; return false) unless @answer.editable_by?(User.current)
end end
def update 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.safe_attributes = params[:answer]
@answer.save_attachments(params[:attachments]) @answer.save_attachments(params[:attachments])
if @answer.save if @answer.save
@ -87,7 +89,7 @@ class QuestionsAnswersController < ApplicationController
private private
def redirect_to_question 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 end
def find_answer def find_answer

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify
@ -54,6 +54,7 @@ class QuestionsController < ApplicationController
end end
def update def update
(render_403; return false) unless @question_item.editable_by?(User.current)
@question_item.safe_attributes = params[:question] @question_item.safe_attributes = params[:question]
@question_item.save_attachments(params[:attachments]) @question_item.save_attachments(params[:attachments])
if @question_item.save if @question_item.save
@ -133,6 +134,7 @@ class QuestionsController < ApplicationController
@text = (params[:question] ? params[:question][:content] : nil) @text = (params[:question] ? params[:question][:content] : nil)
render :partial => 'common/preview' render :partial => 'common/preview'
end end
private private
def find_questions def find_questions
@ -142,7 +144,7 @@ class QuestionsController < ApplicationController
scope = Question.visible scope = Question.visible
scope = scope.where(:section_id => @section) if @section scope = scope.where(:section_id => @section) if @section
columns = ["subject", "content"] 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 = 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) tokens = [] << tokens unless tokens.is_a?(Array)
token_clauses = columns.collect { |column| "(LOWER(#{column}) LIKE ?)" } token_clauses = columns.collect { |column| "(LOWER(#{column}) LIKE ?)" }
@ -168,7 +170,7 @@ class QuestionsController < ApplicationController
@limit = per_page_option @limit = per_page_option
@offset = params[:page].to_i * @limit @offset = params[:page].to_i * @limit
scope = scope.limit(@limit).offset(@offset) 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_count = scope.count
@topic_pages = Paginator.new @topic_count, @limit, params[:page] @topic_pages = Paginator.new @topic_count, @limit, params[:page]
@ -178,7 +180,7 @@ class QuestionsController < ApplicationController
def find_section def find_section
@section = QuestionsSection.find_by_id(params[:section_id] || (params[:question] && params[:question][:section_id])) @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 rescue ActiveRecord::RecordNotFound
render_404 render_404
end end

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify
@ -58,6 +58,7 @@ class QuestionsSectionsController < ApplicationController
def update def update
@section.safe_attributes = params[:questions_section] @section.safe_attributes = params[:questions_section]
@section.insert_at(@section.position) if @section.position_changed?
if @section.save if @section.save
respond_to do |format| respond_to do |format|
format.html do format.html do

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify
@ -39,12 +39,13 @@ class QuestionsStatusesController < ApplicationController
end end
def create 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 if request.post? && @questions_status.save
flash[:notice] = l(:notice_successful_create) 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 else
render :action => 'new' render action: 'new'
end end
end end
@ -54,17 +55,18 @@ class QuestionsStatusesController < ApplicationController
def update def update
@questions_status = QuestionsStatus.find(params[:id]) @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| respond_to do |format|
format.html { format.html {
flash[:notice] = l(:notice_successful_update) 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 } format.js { head 200 }
end end
else else
respond_to do |format| respond_to do |format|
format.html { render :action => 'edit' } format.html { render action: 'edit' }
format.js { head 422 } format.js { head 422 }
end end
end end
@ -72,11 +74,9 @@ class QuestionsStatusesController < ApplicationController
def destroy def destroy
QuestionsStatus.find(params[:id]).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 rescue
flash[:error] = l(:error_products_unable_delete_questions_status) 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
end end

View file

@ -3,7 +3,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify
@ -285,6 +285,6 @@ class Question < ActiveRecord::Base
end end
def send_notification 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
end end

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify
@ -97,6 +97,7 @@ class QuestionsAnswer < ActiveRecord::Base
end end
def editable_by?(user) def editable_by?(user)
(author == user && user.allowed_to?(:edit_own_answers, project)) ||
user.allowed_to?(:edit_questions, project) user.allowed_to?(:edit_questions, project)
end end
@ -121,6 +122,6 @@ class QuestionsAnswer < ActiveRecord::Base
end end
def send_notification 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
end end

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # 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 attr_protected :id if ActiveRecord::VERSION::MAJOR <= 4
safe_attributes 'name', 'project', 'position', 'description', 'section_type' 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 :for_project, lambda { |project| where(:project_id => project) unless project.blank? }
scope :visible, lambda {|*args| scope :visible, lambda {|*args|
joins(:project). joins(:project).

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # 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 attr_protected :id if ActiveRecord::VERSION::MAJOR <= 4
safe_attributes 'name', 'is_closed', 'position', 'color' safe_attributes 'name', 'is_closed', 'position', 'color'
validates :name, :presence => true, :uniqueness => true validates :name, presence: true, uniqueness: true
scope :sorted, lambda { order(:position) } scope :sorted, lambda { order(:position) }

View file

@ -1,5 +1,7 @@
<% @project_sections = QuestionsSection.for_project(@project).sorted %>
<h3><%= l(:label_questions_sections_plural) %></h3> <h3><%= l(:label_questions_sections_plural) %></h3>
<% if @project_sections.any? %>
<table class="list questions_sections"> <table class="list questions_sections">
<thead> <thead>
<tr> <tr>
@ -9,7 +11,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<% QuestionsSection.for_project(@project).sorted.each do |section| %> <% @project_sections.each do |section| %>
<tr class="<%= cycle 'odd', 'even' %>"> <tr class="<%= cycle 'odd', 'even' %>">
<td class="name"> <td class="name">
<%= h(section.name) %> <%= h(section.name) %>
@ -19,18 +21,21 @@
</td> </td>
<td class="buttons"> <td class="buttons">
<% if User.current.allowed_to?(:manage_sections, @project) %> <% 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) %> <%= 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' %> <%= link_to l(:button_edit), edit_questions_section_path(section, project_id: @project), class: 'icon icon-edit' %>
<%= delete_link :controller => 'questions_sections', :action => 'destroy', :project_id => @project, :id => section %> <%= delete_link questions_section_path(section, project_id: @project) %>
<% end %> <% end %>
</td> </td>
</tr> </tr>
<% end %> <% end %>
</tbody> </tbody>
</table> </table>
<% else %>
<p class="nodata"><%= l(:label_no_data) %></p>
<% end %>
<% if User.current.allowed_to?(:manage_sections, @project) %> <% 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 %> <% end %>
<%= javascript_tag do %> <%= javascript_tag do %>

View file

@ -6,7 +6,7 @@
<%= f.text_field :subject, :id => "question_subject", :size => 120%> <%= f.text_field :subject, :id => "question_subject", :size => 120%>
</p> </p>
<p><label><%= l(:label_questions_section) %></label><br /> <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 %> <%= javascript_tag do %>
$('#question_section_id').change(function() { $('#question_section_id').change(function() {
$.ajax({ $.ajax({

View file

@ -1,6 +1,6 @@
<div class="question<%= " votable" if question_item.allow_voting? %> div-table" id="question_<%= question_item.id %>"> <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> <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"> <div class="vote">
<%= render :partial => 'questions_votes/question_item_vote', :locals => {:question_item => question_item} %> <%= render :partial => 'questions_votes/question_item_vote', :locals => {:question_item => question_item} %>
</div> </div>

View file

@ -8,7 +8,8 @@
<%= render :partial => 'form', :locals => {:f => f} %> <%= render :partial => 'form', :locals => {:f => f} %>
</div> </div>
<%= submit_tag l(:button_save) %> <%= 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 %> <% end %>
<div id="preview" class="wiki"></div> <div id="preview" class="wiki"></div>

View file

@ -19,7 +19,7 @@
<div class="filters"> <div class="filters">
<%= form_tag({:controller => "questions", :action => "index"}, :method => :get, :id => "query_form") do %> <%= 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) ) %> <%= 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 %> <% end %>
</div> </div>
</div> </div>

View file

@ -1,12 +1,12 @@
<h2><%= l(:label_message_new) %></h2> <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| %> :id => 'question_form'}} do |f| %>
<div id="all_attributes"> <div id="all_attributes">
<%= render :partial => 'form', :locals => {:f => f} %> <%= render partial: 'form', locals: { f: f } %>
</div> </div>
<%= submit_tag l(:button_create) %> <%= 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 %> <% end %>
<div id="preview" class="wiki"></div> <div id="preview" class="wiki"></div>

View file

@ -1,5 +1,11 @@
<div class="contextual"> <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) %> <% 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) <%= 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> </div>

View file

@ -1,6 +1,6 @@
<div class="question answer<%= ' votable' if question_item.allow_voting? %> div-table" id="questions_answer_<%= question_item.id %>"> <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> <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" > <div class="vote" >
<%= render :partial => 'questions_votes/question_item_vote', :locals => {:question_item => question_item } %> <%= render :partial => 'questions_votes/question_item_vote', :locals => {:question_item => question_item } %>
</div> </div>

View file

@ -5,8 +5,8 @@
<%= back_url_hidden_field_tag %> <%= back_url_hidden_field_tag %>
<%= render :partial => 'form', :locals => {:f => f} %> <%= render :partial => 'form', :locals => {:f => f} %>
<%= submit_tag l(:button_save) %> <%= 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 %> <% end %>
<div id="preview" class="wiki"></div> <div id="preview" class="wiki"></div>

View file

@ -1,22 +1,17 @@
<% previous_group = false %> <% @sections.group_by(&:project).each do |project, sections| %>
<div class="section-list"> <% if @project.blank? %>
<% @sections.each do |section| %>
<% if @project.blank? && (group = section.project) != previous_group %>
<% reset_cycle %>
</div>
<% if group %>
<div class="project-forums"> <div class="project-forums">
<h3> <h3>
<%= group.name %> <%= project.name %>
<%= link_to " \xc2\xbb", project_questions_sections_path(:project_id => group.identifier) %> <%= link_to " \xc2\xbb", project_questions_sections_path(project_id: project.identifier) %>
</h3> </h3>
</div> </div>
<% end %> <% 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"> <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> <h4>
<%= section.name %> <%= section.name %>
<span class="topic-count"><%= "(#{section.questions_count})" %></span> <span class="topic-count"><%= "(#{section.questions_count})" %></span>
@ -26,4 +21,5 @@
</div> </div>
</a> </a>
<% end %> <% end %>
</ul> </div>
<% end %>

View file

@ -26,4 +26,3 @@
<% content_for :header_tags do %> <% content_for :header_tags do %>
<%= javascript_include_tag :questions, :plugin => 'redmine_questions' %> <%= javascript_include_tag :questions, :plugin => 'redmine_questions' %>
<% end %> <% end %>

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -400,3 +400,5 @@ div.question.votable .question-container .contextual {margin-top: 0px;}
.icon-tag { background-image: url(../images/tag_blue.png); } .icon-tag { background-image: url(../images/tag_blue.png); }
.icon-question { background-image: url(../../../images/help.png); } .icon-question { background-image: url(../../../images/help.png); }
.icon-solution { background-image: url(../images/book_open.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); }

View file

@ -170,3 +170,5 @@ en:
permission_accept_answers: Accept answers permission_accept_answers: Accept answers
permission_manage_sections: Manage sections 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

View file

@ -22,8 +22,6 @@ es:
field_questions_tags: Etiquetas field_questions_tags: Etiquetas
label_questions_most_popular: Más populares
permission_view_questions: Ver Ayuda y Soporte permission_view_questions: Ver Ayuda y Soporte
permission_edit_messages_tags: Editar etiquetas permission_edit_messages_tags: Editar etiquetas
permission_edit_vote_messages: Votar mensajes permission_edit_vote_messages: Votar mensajes

View file

@ -95,3 +95,5 @@ ru:
permission_accept_answers: Принимать ответы permission_accept_answers: Принимать ответы
permission_manage_sections: Управлять секциями permission_manage_sections: Управлять секциями
permission_create_tags: Создавать новые тэги permission_create_tags: Создавать новые тэги
label_questions_discard: Не принимать
permission_edit_own_answers: Редактировать свои ответы

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,9 +1,27 @@
== Redmine Q&A plugin changelog == Redmine Q&A plugin changelog
Redmine Q&A plugin Redmine Q&A plugin
Copyright (C) 2011-2018 RedmineUP Copyright (C) 2011-2020 RedmineUP
https://www.redmineup.com/ 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 == 2018-08-31 v1.0.0
* Separate models for questions, answers and comments * Separate models for questions, answers and comments

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # 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 # You should have received a copy of the GNU General Public License
# along with redmine_questions. If not, see <http://www.gnu.org/licenses/>. # 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' require 'redmine_questions'
QA_VERSION_NUMBER = '1.0.0' QA_VERSION_NUMBER = '1.0.2'
QA_VERSION_TYPE = "Light version" QA_VERSION_TYPE = "Light version"
Redmine::Plugin.register :redmine_questions do 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 :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_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_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 :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 :view_questions, { questions: [:index, :show, :autocomplete_for_subject], questions_sections: [:index] }, read: true
permission :delete_questions, { questions: [:destroy] }, require: :loggedin permission :delete_questions, { questions: [:destroy] }, require: :loggedin

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify
@ -70,6 +70,7 @@ module Redmine
end end
def save_attachments(attachments, author = User.current) 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) attachments = attachments.values if attachments.is_a?(Hash)
if attachments.is_a?(Array) if attachments.is_a?(Array)
attachments.each do |attachment| attachments.each do |attachment|

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # 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 'redmine_questions/patches/comment_patch'
require_dependency 'acts_as_attachable_questions/init' require_dependency 'acts_as_attachable_questions/init'
require 'redmine_questions/patches/compatibility/application_controller_patch' if Rails::VERSION::MAJOR < 4

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -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

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify
@ -20,8 +20,15 @@
module RedmineQuestions module RedmineQuestions
module Patches module Patches
module MailerPatch module MailerPatch
module ClassMethods
def deliver_question_comment_added(comment)
question_comment_added(User.current, comment).deliver_later
end
end
module InstanceMethods 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 = comment.commented.is_a?(Question) ? comment.commented : comment.commented.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) project_identifier = question.project.try(:identifier)
@ -36,7 +43,7 @@ module RedmineQuestions
:subject => "[#{project_prefix}] RE: #{question.subject}" :subject => "[#{project_prefix}] RE: #{question.subject}"
end 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) @question_url = url_for(:controller => 'questions', :action => 'show', :id => question.id)
project_identifier = question.project.try(:identifier) project_identifier = question.project.try(:identifier)
redmine_headers 'Project' => project_identifier, 'Question-Id' => question.id redmine_headers 'Project' => project_identifier, 'Question-Id' => question.id
@ -51,9 +58,9 @@ module RedmineQuestions
:subject => "[#{project_prefix}] #{question.subject}" :subject => "[#{project_prefix}] #{question.subject}"
end end
def question_answer_added(answer) def question_answer_added(_user = Current.user, answer)
question = answer.question 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) project_identifier = question.project.try(:identifier)
redmine_headers 'Project' => project_identifier, 'Question-Id' => question.id redmine_headers 'Project' => project_identifier, 'Question-Id' => question.id
message_id question message_id question
@ -66,13 +73,14 @@ module RedmineQuestions
@answer = answer @answer = answer
@question = question @question = question
project_prefix = [project_identifier, question.section_name, "q&a#{question.id}"].compact.join(' - ') project_prefix = [project_identifier, question.section_name, "q&a#{question.id}"].compact.join(' - ')
mail :to => recipients, mail to: recipients,
:cc => cc, cc: cc,
:subject => "[#{project_prefix}] - answ##{answer.id} - RE: #{question.subject}" subject: "[#{project_prefix}] - answ##{answer.id} - RE: #{question.subject}"
end end
end end
def self.included(receiver) def self.included(receiver)
receiver.send :extend, ClassMethods
receiver.send :include, InstanceMethods receiver.send :include, InstanceMethods
receiver.class_eval do receiver.class_eval do
unloadable unloadable

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -38,13 +38,13 @@ END_DESC
next next
end 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 = section.questions.create(question_attrs)
migrated_question.attachments = topic.attachments.map { |attachment| attachment.copy } migrated_question.attachments = topic.attachments.map { |attachment| attachment.copy }
topic.children.each do |reply| topic.children.each do |reply|
if section.section_type == 'questions' 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 = migrated_question.answers.create(answer_attrs)
migrated_answer.attachments = reply.attachments.map { |attachment| attachment.copy } migrated_answer.attachments = reply.attachments.map { |attachment| attachment.copy }
else else

View file

@ -10,3 +10,9 @@ answer_002:
question_id: 2 question_id: 2
author_id: 1 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

View 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

View file

@ -3,7 +3,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # 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', assert_redirected_to :controller => 'questions',
:action => 'show', :action => 'show',
:id => question, :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 old_answer_count + 1, question.answers.count
assert_equal 'Answer for the first question', question.answers.last.content assert_equal 'Answer for the first question', question.answers.last.content
end end
@ -92,13 +92,9 @@ class QuestionsAnswersControllerTest < ActionController::TestCase
:content => "Previewed answer", :content => "Previewed answer",
} }
assert_response :success assert_response :success
assert_select 'fieldset' do
assert_select 'legend', :text => 'Preview'
assert_select 'p', :text => 'Previewed answer' assert_select 'p', :text => 'Previewed answer'
end end
end
def test_preview_edited_answer def test_preview_edited_answer
@request.session[:user_id] = 1 @request.session[:user_id] = 1
answer = questions_answers(:answer_002) answer = questions_answers(:answer_002)
@ -107,13 +103,9 @@ class QuestionsAnswersControllerTest < ActionController::TestCase
:content => "Previewed answer 1", :content => "Previewed answer 1",
} }
assert_response :success assert_response :success
assert_select 'fieldset' do
assert_select 'legend', :text => 'Preview'
assert_select 'p', :text => 'Previewed answer 1' assert_select 'p', :text => 'Previewed answer 1'
end end
end
def test_destroy def test_destroy
@request.session[:user_id] = 1 @request.session[:user_id] = 1
answer = questions_answers(:answer_002) answer = questions_answers(:answer_002)
@ -121,7 +113,7 @@ class QuestionsAnswersControllerTest < ActionController::TestCase
assert_difference 'QuestionsAnswer.count', -1 do assert_difference 'QuestionsAnswer.count', -1 do
compatible_request :post, :destroy, :id => answer.id compatible_request :post, :destroy, :id => answer.id
end 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) assert_nil QuestionsAnswer.find_by_id(answer.id)
end end
@ -144,6 +136,6 @@ class QuestionsAnswersControllerTest < ActionController::TestCase
} }
# assert_response :success # assert_response :success
answer.reload 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
end end

View file

@ -3,7 +3,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -3,7 +3,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify
@ -46,8 +46,7 @@ class QuestionsControllerTest < ActionController::TestCase
fixtures :email_addresses if ActiveRecord::VERSION::MAJOR >= 4 fixtures :email_addresses if ActiveRecord::VERSION::MAJOR >= 4
RedmineQuestions::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_questions).directory + '/test/fixtures/', RedmineQuestions::TestCase.create_fixtures(Redmine::Plugin.find(:redmine_questions).directory + '/test/fixtures/', [:tags, :taggings, :comments])
[:tags, :taggings, :comments])
def setup def setup
RedmineQuestions::TestCase.prepare RedmineQuestions::TestCase.prepare
@ -77,6 +76,34 @@ class QuestionsControllerTest < ActionController::TestCase
assert_select 'p.breadcrumb' assert_select 'p.breadcrumb'
end 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 def test_post_create
@request.session[:user_id] = 1 @request.session[:user_id] = 1
ActionMailer::Base.deliveries.clear ActionMailer::Base.deliveries.clear
@ -118,7 +145,7 @@ class QuestionsControllerTest < ActionController::TestCase
assert_select 'div#reply' assert_select 'div#reply'
assert_select 'a.icon-del' assert_select 'a.icon-del'
assert_select 'a.add-comment-link' 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.permissions << :add_answers
@dev_role.save @dev_role.save
@request.session[:user_id] = 3 @request.session[:user_id] = 3
@ -174,11 +201,8 @@ class QuestionsControllerTest < ActionController::TestCase
:content => "Previewed question", :content => "Previewed question",
} }
assert_response :success assert_response :success
assert_select 'fieldset' do
assert_select 'legend', :text => 'Preview'
assert_select 'p', :text => 'Previewed question' assert_select 'p', :text => 'Previewed question'
end end
end
def test_update_question def test_update_question
@request.session[:user_id] = 1 @request.session[:user_id] = 1

View file

@ -3,7 +3,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -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

View file

@ -3,7 +3,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -3,7 +3,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify
@ -74,7 +74,7 @@ class RedmineQuestions::TestCase
end end
def self.prepare def self.prepare
Role.where(:id => [1, 3]).each do |r| Role.where(:id => 1).each do |r|
# user_2 # user_2
r.permissions << :view_questions r.permissions << :view_questions
r.permissions << :global_view_questions r.permissions << :global_view_questions
@ -103,11 +103,6 @@ class RedmineQuestions::TestCase
r.save r.save
end 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| Project.where(:id => [1, 2, 3, 4, 5]).each do |project|
EnabledModule.create(:project => project, :name => 'questions') EnabledModule.create(:project => project, :name => 'questions')
end end

View file

@ -3,7 +3,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -3,7 +3,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify

View file

@ -3,7 +3,7 @@
# This file is a part of Redmine Q&A (redmine_questions) plugin, # This file is a part of Redmine Q&A (redmine_questions) plugin,
# Q&A plugin for Redmine # Q&A plugin for Redmine
# #
# Copyright (C) 2011-2018 RedmineUP # Copyright (C) 2011-2020 RedmineUP
# http://www.redmineup.com/ # http://www.redmineup.com/
# #
# redmine_questions is free software: you can redistribute it and/or modify # redmine_questions is free software: you can redistribute it and/or modify