Adds a Reply link to each issue note (#739). Reply is pre-filled with the quoted note.

git-svn-id: http://redmine.rubyforge.org/svn/trunk@1480 e93f8b46-1217-0410-a6f0-8f06a7374b81
pull/351/head
Jean-Philippe Lang 17 years ago
parent 88dea1a06d
commit 5d2abb84bd
  1. 22
      app/controllers/issues_controller.rb
  2. 11
      app/helpers/journals_helper.rb
  3. 3
      app/views/issues/_history.rhtml
  4. 6
      app/views/issues/show.rhtml
  5. 1
      lang/bg.yml
  6. 1
      lang/cs.yml
  7. 1
      lang/da.yml
  8. 1
      lang/de.yml
  9. 1
      lang/en.yml
  10. 1
      lang/es.yml
  11. 1
      lang/fi.yml
  12. 1
      lang/fr.yml
  13. 1
      lang/he.yml
  14. 1
      lang/hu.yml
  15. 1
      lang/it.yml
  16. 1
      lang/ja.yml
  17. 1
      lang/ko.yml
  18. 1
      lang/lt.yml
  19. 1
      lang/nl.yml
  20. 1
      lang/no.yml
  21. 1
      lang/pl.yml
  22. 1
      lang/pt-br.yml
  23. 1
      lang/pt.yml
  24. 1
      lang/ro.yml
  25. 1
      lang/ru.yml
  26. 1
      lang/sr.yml
  27. 1
      lang/sv.yml
  28. 1
      lang/th.yml
  29. 1
      lang/uk.yml
  30. 1
      lang/zh-tw.yml
  31. 1
      lang/zh.yml
  32. 4
      lib/redmine.rb
  33. BIN
      public/images/comment.png
  34. 16
      test/functional/issues_controller_test.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{<pre>((.|\s)*?)</pre>}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?

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

@ -1,3 +1,4 @@
<% reply_links = authorize_for('issues', 'edit') -%>
<% for journal in journals %>
<div id="change-<%= journal.id %>" class="journal">
<h4><div style="float:right;"><%= link_to "##{journal.indice}", :anchor => "note-#{journal.indice}" %></div>
@ -8,6 +9,6 @@
<li><%= show_detail(detail) %></li>
<% end %>
</ul>
<%= render_notes(journal) unless journal.notes.blank? %>
<%= render_notes(journal, :reply_links => reply_links) unless journal.notes.blank? %>
</div>
<% end %>

@ -56,6 +56,12 @@ end %>
</table>
<hr />
<div class="contextual">
<%= link_to_remote(image_tag('comment.png'),
{ :url => {:controller => 'issues', :action => 'reply', :id => @issue} },
:title => l(:button_reply)) if authorize_for('issues', 'edit') %>
</div>
<p><strong><%=l(:field_description)%></strong></p>
<div class="wiki">
<%= textilizable @issue, :description, :attachments => @issue.attachments %>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

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

Loading…
Cancel
Save