diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index ca3309c4..defc0a11 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -19,7 +19,7 @@ class IssuesController < ApplicationController
layout 'base'
menu_item :new_issue, :only => :new
- before_filter :find_issue, :only => [:show, :edit, :destroy_attachment]
+ before_filter :find_issue, :only => [:show, :edit, :reply, :destroy_attachment]
before_filter :find_issues, :only => [:bulk_edit, :move, :destroy]
before_filter :find_project, :only => [:new, :update_form, :preview]
before_filter :authorize, :except => [:index, :changes, :preview, :update_form, :context_menu]
@@ -208,6 +208,26 @@ class IssuesController < ApplicationController
flash.now[:error] = l(:notice_locking_conflict)
end
+ def reply
+ journal = Journal.find(params[:journal_id]) if params[:journal_id]
+ if journal
+ user = journal.user
+ text = journal.notes
+ else
+ user = @issue.author
+ text = @issue.description
+ end
+ content = "#{ll(Setting.default_language, :text_user_wrote, user)}\n> "
+ content << text.to_s.strip.gsub(%r{
((.|\s)*?)
}m, '[...]').gsub("\n", "\n> ") + "\n\n"
+ render(:update) { |page|
+ page.replace_html "notes", content
+ page.show 'update'
+ page << "Form.Element.focus('notes');"
+ page << "Element.scrollTo('update');"
+ page << "$('notes').scrollTop = $('notes').scrollHeight - $('notes').clientHeight;"
+ }
+ end
+
# Bulk edit a set of issues
def bulk_edit
if request.post?
diff --git a/app/helpers/journals_helper.rb b/app/helpers/journals_helper.rb
index 234bfabc..92d6e559 100644
--- a/app/helpers/journals_helper.rb
+++ b/app/helpers/journals_helper.rb
@@ -19,13 +19,16 @@ module JournalsHelper
def render_notes(journal, options={})
content = ''
editable = journal.editable_by?(User.current)
- if editable && !journal.notes.blank?
- links = []
+ links = []
+ if !journal.notes.blank?
links << link_to_in_place_notes_editor(image_tag('edit.png'), "journal-#{journal.id}-notes",
{ :controller => 'journals', :action => 'edit', :id => journal },
- :title => l(:button_edit))
- content << content_tag('div', links.join(' '), :class => 'contextual')
+ :title => l(:button_edit)) if editable
+ links << link_to_remote(image_tag('comment.png'),
+ { :url => {:controller => 'issues', :action => 'reply', :id => journal.journalized, :journal_id => journal} },
+ :title => l(:button_reply)) if options[:reply_links]
end
+ content << content_tag('div', links.join(' '), :class => 'contextual') unless links.empty?
content << textilizable(journal, :notes)
content_tag('div', content, :id => "journal-#{journal.id}-notes", :class => (editable ? 'wiki editable' : 'wiki'))
end
diff --git a/app/views/issues/_history.rhtml b/app/views/issues/_history.rhtml
index f29a44da..b8efdb40 100644
--- a/app/views/issues/_history.rhtml
+++ b/app/views/issues/_history.rhtml
@@ -1,3 +1,4 @@
+<% reply_links = authorize_for('issues', 'edit') -%>
<% for journal in journals %>
<%= link_to "##{journal.indice}", :anchor => "note-#{journal.indice}" %>
@@ -8,6 +9,6 @@
<%= show_detail(detail) %>
<% end %>
- <%= render_notes(journal) unless journal.notes.blank? %>
+ <%= render_notes(journal, :reply_links => reply_links) unless journal.notes.blank? %>
<% end %>
diff --git a/app/views/issues/show.rhtml b/app/views/issues/show.rhtml
index f788d0ec..f1c8a82c 100644
--- a/app/views/issues/show.rhtml
+++ b/app/views/issues/show.rhtml
@@ -56,6 +56,12 @@ end %>
+
+<%= link_to_remote(image_tag('comment.png'),
+ { :url => {:controller => 'issues', :action => 'reply', :id => @issue} },
+ :title => l(:button_reply)) if authorize_for('issues', 'edit') %>
+
+
<%=l(:field_description)%>
<%= textilizable @issue, :description, :attachments => @issue.attachments %>
diff --git a/lang/bg.yml b/lang/bg.yml
index 10198bce..05a0b0d6 100644
--- a/lang/bg.yml
+++ b/lang/bg.yml
@@ -621,3 +621,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/cs.yml b/lang/cs.yml
index f90068b3..829f4449 100644
--- a/lang/cs.yml
+++ b/lang/cs.yml
@@ -626,3 +626,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/da.yml b/lang/da.yml
index ca4ddeb4..92df87e3 100644
--- a/lang/da.yml
+++ b/lang/da.yml
@@ -623,3 +623,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/de.yml b/lang/de.yml
index fa33e1c7..1351d194 100644
--- a/lang/de.yml
+++ b/lang/de.yml
@@ -622,3 +622,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/en.yml b/lang/en.yml
index f9e07d21..4184a917 100644
--- a/lang/en.yml
+++ b/lang/en.yml
@@ -596,6 +596,7 @@ text_destroy_time_entries_question: %.02f hours were reported on the issues you
text_destroy_time_entries: Delete reported hours
text_assign_time_entries_to_project: Assign reported hours to the project
text_reassign_time_entries: 'Reassign reported hours to this issue:'
+text_user_wrote: '%s wrote:'
default_role_manager: Manager
default_role_developper: Developer
diff --git a/lang/es.yml b/lang/es.yml
index 3d8c0a93..ea479630 100644
--- a/lang/es.yml
+++ b/lang/es.yml
@@ -624,3 +624,4 @@ text_subprojects_destroy_warning: 'Sus subprojectos: %s también se eliminarán'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/fi.yml b/lang/fi.yml
index 60428bb4..b3b88862 100644
--- a/lang/fi.yml
+++ b/lang/fi.yml
@@ -621,3 +621,4 @@ text_subprojects_destroy_warning: 'Tämän alaprojekti(t): %s tullaan myös pois
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/fr.yml b/lang/fr.yml
index 8b002bbf..a802a44c 100644
--- a/lang/fr.yml
+++ b/lang/fr.yml
@@ -596,6 +596,7 @@ text_destroy_time_entries_question: %.02f heures ont été enregistrées sur les
text_destroy_time_entries: Supprimer les heures
text_assign_time_entries_to_project: Reporter les heures sur le projet
text_reassign_time_entries: 'Reporter les heures sur cette demande:'
+text_user_wrote: '%s a écrit:'
default_role_manager: Manager
default_role_developper: Développeur
diff --git a/lang/he.yml b/lang/he.yml
index f972ef62..c4d69ebb 100644
--- a/lang/he.yml
+++ b/lang/he.yml
@@ -621,3 +621,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/hu.yml b/lang/hu.yml
index f6d312ce..fd7bf9f5 100644
--- a/lang/hu.yml
+++ b/lang/hu.yml
@@ -622,3 +622,4 @@ enumeration_doc_categories: Dokumentum kategóriák
enumeration_activities: Tevékenységek (idő rögzítés)
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/it.yml b/lang/it.yml
index a8646644..519dcd01 100644
--- a/lang/it.yml
+++ b/lang/it.yml
@@ -621,3 +621,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/ja.yml b/lang/ja.yml
index d119cf55..714539c7 100644
--- a/lang/ja.yml
+++ b/lang/ja.yml
@@ -622,3 +622,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/ko.yml b/lang/ko.yml
index 98dde9e0..81656040 100644
--- a/lang/ko.yml
+++ b/lang/ko.yml
@@ -621,3 +621,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/lt.yml b/lang/lt.yml
index 6b791d87..89e607a8 100644
--- a/lang/lt.yml
+++ b/lang/lt.yml
@@ -623,3 +623,4 @@ label_and_its_subprojects: %s projektas ir jo subprojektai
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/nl.yml b/lang/nl.yml
index c36eaecd..eebc7d99 100644
--- a/lang/nl.yml
+++ b/lang/nl.yml
@@ -622,3 +622,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/no.yml b/lang/no.yml
index 5e788dc5..3f6ef6de 100644
--- a/lang/no.yml
+++ b/lang/no.yml
@@ -622,3 +622,4 @@ enumeration_doc_categories: Dokument-kategorier
enumeration_activities: Aktiviteter (tidssporing)
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/pl.yml b/lang/pl.yml
index 4476c216..81a7a0db 100644
--- a/lang/pl.yml
+++ b/lang/pl.yml
@@ -621,3 +621,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/pt-br.yml b/lang/pt-br.yml
index 9b3d2315..47e80a14 100644
--- a/lang/pt-br.yml
+++ b/lang/pt-br.yml
@@ -621,3 +621,4 @@ label_age: Age
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/pt.yml b/lang/pt.yml
index c56b76a0..002a1b7f 100644
--- a/lang/pt.yml
+++ b/lang/pt.yml
@@ -621,3 +621,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/ro.yml b/lang/ro.yml
index 30464569..6bcd55a5 100644
--- a/lang/ro.yml
+++ b/lang/ro.yml
@@ -621,3 +621,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/ru.yml b/lang/ru.yml
index f4fd9203..fa8fd69a 100644
--- a/lang/ru.yml
+++ b/lang/ru.yml
@@ -625,3 +625,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/sr.yml b/lang/sr.yml
index 53e4f9f2..9a4adf21 100644
--- a/lang/sr.yml
+++ b/lang/sr.yml
@@ -622,3 +622,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/sv.yml b/lang/sv.yml
index 248f3dcb..1ab11e98 100644
--- a/lang/sv.yml
+++ b/lang/sv.yml
@@ -622,3 +622,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/th.yml b/lang/th.yml
index 444316aa..751aac74 100644
--- a/lang/th.yml
+++ b/lang/th.yml
@@ -624,3 +624,4 @@ enumeration_activities: กิจกรรม (ใช้ในการติด
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/uk.yml b/lang/uk.yml
index 3cc60ef4..3ab4462e 100644
--- a/lang/uk.yml
+++ b/lang/uk.yml
@@ -623,3 +623,4 @@ text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.'
label_and_its_subprojects: %s and its subprojects
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/zh-tw.yml b/lang/zh-tw.yml
index 3926113b..3b7808aa 100644
--- a/lang/zh-tw.yml
+++ b/lang/zh-tw.yml
@@ -622,3 +622,4 @@ enumeration_doc_categories: 文件分類
enumeration_activities: 活動 (時間追蹤)
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
mail_subject_reminder: "%d issue(s) due in the next days"
+text_user_wrote: '%s wrote:'
diff --git a/lang/zh.yml b/lang/zh.yml
index 55516e03..b5ecace8 100644
--- a/lang/zh.yml
+++ b/lang/zh.yml
@@ -622,3 +622,4 @@ enumeration_doc_categories: 文档类别
enumeration_activities: 活动(时间跟踪)
mail_subject_reminder: "%d issue(s) due in the next days"
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:"
+text_user_wrote: '%s wrote:'
diff --git a/lib/redmine.rb b/lib/redmine.rb
index b21f5716..7b9832d6 100644
--- a/lib/redmine.rb
+++ b/lib/redmine.rb
@@ -32,9 +32,9 @@ Redmine::AccessControl.map do |map|
:queries => :index,
:reports => :issue_report}, :public => true
map.permission :add_issues, {:issues => :new}
- map.permission :edit_issues, {:issues => [:edit, :bulk_edit, :destroy_attachment]}
+ map.permission :edit_issues, {:issues => [:edit, :reply, :bulk_edit, :destroy_attachment]}
map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
- map.permission :add_issue_notes, {:issues => :edit}
+ map.permission :add_issue_notes, {:issues => [:edit, :reply]}
map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
map.permission :move_issues, {:issues => :move}, :require => :loggedin
diff --git a/public/images/comment.png b/public/images/comment.png
new file mode 100644
index 00000000..7bc9233e
Binary files /dev/null and b/public/images/comment.png differ
diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb
index c4389fed..7c7d44e5 100644
--- a/test/functional/issues_controller_test.rb
+++ b/test/functional/issues_controller_test.rb
@@ -263,6 +263,22 @@ class IssuesControllerTest < Test::Unit::TestCase
:content => 'Urgent',
:attributes => { :selected => 'selected' } }
end
+
+ def test_reply_to_issue
+ @request.session[:user_id] = 2
+ get :reply, :id => 1
+ assert_response :success
+ assert_select_rjs :show, "update"
+ assert_select_rjs :replace_html, "notes"
+ end
+
+ def test_reply_to_note
+ @request.session[:user_id] = 2
+ get :reply, :id => 1, :journal_id => 2
+ assert_response :success
+ assert_select_rjs :show, "update"
+ assert_select_rjs :replace_html, "notes"
+ end
def test_post_edit
@request.session[:user_id] = 2