Feature #1554 » private_messages.patch
| app/helpers/journals_helper.rb (working copy) | ||
|---|---|---|
| 39 | 39 |     onclick = "new Ajax.Request('#{url_for(url)}', {asynchronous:true, evalScripts:true, method:'get'}); return false;" | 
| 40 | 40 | link_to text, '#', options.merge(:onclick => onclick) | 
| 41 | 41 | end | 
| 42 | ||
| 43 | def only_private_messages?(journals) | |
| 44 | journals.each do |journal| | |
| 45 | return false if ! journal.private | |
| 46 | end | |
| 47 |  | |
| 48 | true | |
| 49 | end | |
| 42 | 50 | end | 
| app/models/mailer.rb (working copy) | ||
|---|---|---|
| 58 | 58 | # Mailer.deliver_issue_edit(journal) => sends an email to issue recipients | 
| 59 | 59 | def issue_edit(journal) | 
| 60 | 60 | issue = journal.journalized.reload | 
| 61 | private = journal[:private] | |
| 61 | 62 | redmine_headers 'Project' => issue.project.identifier, | 
| 62 | 63 | 'Issue-Id' => issue.id, | 
| 63 | 64 | 'Issue-Author' => issue.author.login | 
| ... | ... | |
| 65 | 66 | message_id journal | 
| 66 | 67 | references issue | 
| 67 | 68 | @author = journal.user | 
| 68 | recipients issue.recipients | |
| 69 | ||
| 70 | @recipients ||= [] | |
| 71 | watchers = issue.watcher_recipients - @recipients | |
| 72 | ||
| 73 | processed_recipients = prepare_receivers issue.recipients, issue.project, private | |
| 74 | processed_watchers = prepare_receivers watchers, issue.project, private | |
| 75 | ||
| 76 | recipients processed_recipients | |
| 69 | 77 | # Watchers in cc | 
| 70 |     cc(issue.watcher_recipients - @recipients) | |
| 78 |     cc(processed_watchers) | |
| 71 | 79 |     s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] " | 
| 72 | 80 |     s << "(#{issue.status.name}) " if journal.new_value_for('status_id') | 
| 73 | 81 | s << issue.subject | 
| ... | ... | |
| 448 | 456 | def mylogger | 
| 449 | 457 | RAILS_DEFAULT_LOGGER | 
| 450 | 458 | end | 
| 459 | ||
| 460 | # Method for recipients or watchers preparation | |
| 461 | def prepare_receivers(receivers, project, private) | |
| 462 | processed_receivers = Array.new() | |
| 463 | ||
| 464 | receivers.each do |recepient| | |
| 465 | current_user = User.find_by_mail(recepient) | |
| 466 | can_see_private_messages = current_user.allowed_to?(:view_private_messages, project) | |
| 467 | ||
| 468 | if private | |
| 469 | next if ! can_see_private_messages | |
| 470 | end | |
| 471 | ||
| 472 | processed_receivers << recepient | |
| 473 | end | |
| 474 | ||
| 475 | processed_receivers | |
| 476 | end | |
| 477 | ||
| 451 | 478 | end | 
| 452 | 479 | |
| 453 | 480 | # Patch TMail so that message_id is not overwritten | 
| app/models/issue.rb (working copy) | ||
|---|---|---|
| 388 | 388 | end | 
| 389 | 389 | end | 
| 390 | 390 | |
| 391 | def init_journal(user, notes = "") | |
| 392 | @current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes) | |
| 391 |   def init_journal(user, notes = "", private = false) | |
| 392 |     @current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes, :private => private) | |
| 393 | 393 | @issue_before_change = self.clone | 
| 394 | 394 | @issue_before_change.status = self.status | 
| 395 | 395 |     @custom_values_before_change = {} | 
| app/controllers/issues_controller.rb (working copy) | ||
|---|---|---|
| 286 | 286 | @time_entry.attributes = params[:time_entry] | 
| 287 | 287 | |
| 288 | 288 | @notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil) | 
| 289 | @issue.init_journal(User.current, @notes) | |
| 289 | @private_message = params[:private_message] || false | |
| 290 | @issue.init_journal(User.current, @notes, @private_message) | |
| 290 | 291 | @issue.safe_attributes = params[:issue] | 
| 291 | 292 | end | 
| 292 | 293 | |
| app/controllers/journals_controller.rb (working copy) | ||
|---|---|---|
| 83 | 83 | (render_403; return false) unless @journal.editable_by?(User.current) | 
| 84 | 84 | if request.post? | 
| 85 | 85 | @journal.update_attributes(:notes => params[:notes]) if params[:notes] | 
| 86 | @journal.update_attributes(:private => params[:private_message] || false) | |
| 86 | 87 | @journal.destroy if @journal.details.empty? && @journal.notes.blank? | 
| 87 | 88 |       call_hook(:controller_journals_edit_post, { :journal => @journal, :params => params}) | 
| 88 | 89 | respond_to do |format| | 
| app/views/journals/_notes_form.rhtml (working copy) | ||
|---|---|---|
| 16 | 16 |     <%= link_to l(:button_cancel), '#', :onclick => "Element.remove('journal-#{@journal.id}-form'); " + | 
| 17 | 17 |                                                     "Element.show('journal-#{@journal.id}-notes'); return false;" %></p> | 
| 18 | 18 | |
| 19 |     <%= check_box_tag :private_message, true, @journal.private, :id => "private_message_#{@journal.id}" %> | |
| 20 |     <%= label_tag "private_message_#{@journal.id}", 'Private message', :style => 'font-weight:bold;' %> | |
| 21 |  | |
| 19 | 22 | <div id="journal_<%= @journal.id %>_preview" class="wiki"></div> | 
| 20 | 23 | <% end %> | 
| 21 | 24 | <%= wikitoolbar_for "journal_#{@journal.id}_notes" %> | 
| app/views/issues/_history.rhtml (working copy) | ||
|---|---|---|
| 1 | 1 | <% reply_links = authorize_for('issues', 'edit') -%> | 
| 2 | <% view_private = User.current.allowed_to?(:view_private_messages, @project) %> | |
| 3 | <% @skipped = 0 %> | |
| 4 | ||
| 2 | 5 | <% for journal in journals %> | 
| 3 | <div id="change-<%= journal.id %>" class="<%= journal.css_classes %>"> | |
| 4 |     <h4><div class="journal-link"><%= link_to "##{journal.indice}", :anchor => "note-#{journal.indice}" %></div> | |
| 6 | ||
| 7 | <% private = journal.private %> | |
| 8 | ||
| 9 | <% if private %> | |
| 10 | <% if ! view_private %> | |
| 11 | <% @skipped += 1 %> | |
| 12 | <% next %> | |
| 13 | <% end %> | |
| 14 | <% end %> | |
| 15 | ||
| 16 | <div id="change-<%= journal.id %>" class="<%= journal.css_classes %> <%= 'private' if journal.private %>"> | |
| 17 |     <h4><div class="journal-link"><%= link_to "##{journal.indice - @skipped}", :anchor => "note-#{journal.indice - @skipped}" %></div> | |
| 5 | 18 | <%= avatar(journal.user, :size => "24") %> | 
| 6 |     <%= content_tag('a', '', :name => "note-#{journal.indice}")%> | |
| 7 | <%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %></h4> | |
| 19 |     <%= content_tag('a', '', :name => "note-#{journal.indice - @skipped}")%> | |
| 20 | <%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %> | |
| 21 | <% if journal.private %> | |
| 22 | <span>(private)</span> | |
| 23 | <% end %> | |
| 24 | </h4> | |
| 8 | 25 |  | 
| 9 | 26 | <% if journal.details.any? %> | 
| 10 | 27 | <ul class="details"> | 
| app/views/issues/show.rhtml (working copy) | ||
|---|---|---|
| 90 | 90 | <% end %> | 
| 91 | 91 | |
| 92 | 92 | <% if @journals.present? %> | 
| 93 | <div id="history"> | |
| 94 | <h3><%=l(:label_history)%></h3> | |
| 95 | <%= render :partial => 'history', :locals => { :issue => @issue, :journals => @journals } %> | |
| 96 | </div> | |
| 93 | <% view_private = User.current.allowed_to?(:view_private_messages, @project) %> | |
| 94 | <% if ! only_private_messages?(@journals) || view_private %> | |
| 95 | <div id="history"> | |
| 96 | <h3><%=l(:label_history)%></h3> | |
| 97 |     <%= render :partial => 'history', :locals => { :issue => @issue, :journals => @journals } %> | |
| 98 | </div> | |
| 99 | <% end %> | |
| 97 | 100 | <% end %> | 
| 98 | 101 | |
| 99 | 102 | |
| app/views/issues/_edit.rhtml (working copy) | ||
|---|---|---|
| 5 | 5 | :method => :put, | 
| 6 | 6 | :multipart => true} do |f| %> | 
| 7 | 7 | <%= error_messages_for 'issue', 'time_entry' %> | 
| 8 | ||
| 9 | <% view_private = User.current.allowed_to?(:view_private_messages, @project) %> | |
| 10 | ||
| 8 | 11 | <div class="box"> | 
| 9 | 12 | <% if @edit_allowed || !@allowed_statuses.empty? %> | 
| 10 | 13 | <fieldset class="tabular"><legend><%= l(:label_change_properties) %> | 
| ... | ... | |
| 31 | 34 | <% end %> | 
| 32 | 35 | </fieldset> | 
| 33 | 36 | <% end %> | 
| 34 |  | |
| 37 | ||
| 35 | 38 | <fieldset><legend><%= l(:field_notes) %></legend> | 
| 36 | 39 | <%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %> | 
| 37 | 40 | <%= wikitoolbar_for 'notes' %> | 
| 38 | 41 |     <%= call_hook(:view_issues_edit_notes_bottom, { :issue => @issue, :notes => @notes, :form => f }) %> | 
| 39 |  | |
| 42 | ||
| 43 | <% if view_private %> | |
| 44 | <%= check_box_tag :private_message, true, false %> | |
| 45 | <%= label_tag :private_message, 'Private message', :style => 'font-weight:bold;' %> | |
| 46 | <% end %> | |
| 47 | ||
| 40 | 48 | <p><%=l(:label_attachment_plural)%><br /><%= render :partial => 'attachments/form' %></p> | 
| 41 | 49 | </fieldset> | 
| 42 | 50 | </div> | 
| 43 |  | |
| 51 | ||
| 44 | 52 | <%= f.hidden_field :lock_version %> | 
| 45 | 53 | <%= submit_tag l(:button_submit) %> | 
| 46 |     <%= link_to_remote l(:label_preview),  | |
| 54 | <%= link_to_remote l(:label_preview), | |
| 47 | 55 |                        { :url => preview_issue_path(:project_id => @project, :id => @issue), | 
| 48 | 56 | :method => 'post', | 
| 49 | 57 | :update => 'preview', | 
| ... | ... | |
| 52 | 60 | }, :accesskey => accesskey(:preview) %> | 
| 53 | 61 | <% end %> | 
| 54 | 62 | |
| 55 | <div id="preview" class="wiki"></div> | |
| 63 | <div id="preview" class="wiki"></div> | |
| lib/redmine.rb (working copy) | ||
|---|---|---|
| 85 | 85 |     map.permission :view_issue_watchers, {} | 
| 86 | 86 |     map.permission :add_issue_watchers, {:watchers => :new} | 
| 87 | 87 |     map.permission :delete_issue_watchers, {:watchers => :destroy} | 
| 88 | # Private messages | |
| 89 |     map.permission :view_private_messages, {} | |
| 88 | 90 | end | 
| 89 | 91 |  | 
| 90 | 92 | map.project_module :time_tracking do |map| |