Feature #1554 » 0001-add-private-messages.patch
app/controllers/activities_controller.rb | ||
---|---|---|
38 | 38 |
@activity.scope_select {|t| !params["show_#{t}"].nil?} |
39 | 39 |
@activity.scope = (@author.nil? ? :default : :all) if @activity.scope.empty? |
40 | 40 | |
41 |
events.delete_if { |e| e.is_a?(Journal) && e.private && !User.current.allowed_to?(:view_private_messages, @project) } |
|
41 | 42 |
events = @activity.events(@date_from, @date_to) |
42 | 43 | |
43 | 44 |
if events.empty? || stale?(:etag => [@activity.scope, @date_to, @date_from, @with_subprojects, @author, events.first, User.current, current_language]) |
app/controllers/issues_controller.rb | ||
---|---|---|
360 | 360 |
@time_entry.attributes = params[:time_entry] |
361 | 361 | |
362 | 362 |
@notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil) |
363 |
@issue.init_journal(User.current, @notes) |
|
363 |
@private_message = params[:private_message] || false |
|
364 |
@issue.init_journal(User.current, @notes, @private_message) |
|
364 | 365 | |
365 | 366 |
issue_attributes = params[:issue] |
366 | 367 |
if issue_attributes && params[:conflict_resolution] |
app/controllers/journals_controller.rb | ||
---|---|---|
82 | 82 |
def edit |
83 | 83 |
(render_403; return false) unless @journal.editable_by?(User.current) |
84 | 84 |
if request.post? |
85 |
@journal.update_attributes(:notes => params[:notes]) if params[:notes]
|
|
85 |
@journal.update_attributes(:private => params[:private_message] || false)
|
|
86 | 86 |
@journal.destroy if @journal.details.empty? && @journal.notes.blank? |
87 | 87 |
call_hook(:controller_journals_edit_post, { :journal => @journal, :params => params}) |
88 | 88 |
respond_to do |format| |
app/helpers/journals_helper.rb | ||
---|---|---|
41 | 41 |
onclick = "new Ajax.Request('#{url_for(url)}', {asynchronous:true, evalScripts:true, method:'get'}); return false;" |
42 | 42 |
link_to text, '#', options.merge(:onclick => onclick) |
43 | 43 |
end |
44 | ||
45 |
def only_private_messages?(journals) |
|
46 |
journals.each do |journal| |
|
47 |
return false if ! journal.private |
|
48 |
end |
|
49 | ||
50 |
true |
|
51 |
end |
|
44 | 52 |
end |
app/models/issue.rb | ||
---|---|---|
444 | 444 |
end |
445 | 445 |
end |
446 | 446 | |
447 |
def init_journal(user, notes = "") |
|
448 |
@current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes) |
|
447 |
def init_journal(user, notes = "", private = false)
|
|
448 |
@current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes, :private => private)
|
|
449 | 449 |
if new_record? |
450 | 450 |
@current_journal.notify = false |
451 | 451 |
else |
app/models/mail_handler.rb | ||
---|---|---|
190 | 190 |
issue.safe_attributes = issue_attributes_from_keywords(issue) |
191 | 191 |
issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)} |
192 | 192 |
journal.notes = cleaned_up_text_body |
193 |
journal.private = 1 if !email.subject.to_s.index('[PRIVATE]').nil? |
|
193 | 194 |
add_attachments(issue) |
194 | 195 |
issue.save! |
195 | 196 |
if logger && logger.info |
app/models/mailer.rb | ||
---|---|---|
57 | 57 |
# Mailer.deliver_issue_edit(journal) => sends an email to issue recipients |
58 | 58 |
def issue_edit(journal) |
59 | 59 |
issue = journal.journalized.reload |
60 |
private = journal[:private] |
|
60 | 61 |
redmine_headers 'Project' => issue.project.identifier, |
61 | 62 |
'Issue-Id' => issue.id, |
62 | 63 |
'Issue-Author' => issue.author.login |
... | ... | |
64 | 65 |
message_id journal |
65 | 66 |
references issue |
66 | 67 |
@author = journal.user |
67 |
recipients issue.recipients |
|
68 |
@recipients ||= [] |
|
69 |
watchers = issue.watcher_recipients - @recipients |
|
70 | ||
71 |
processed_recipients = prepare_receivers issue.recipients, issue.project, private |
|
72 |
processed_watchers = prepare_receivers watchers, issue.project, private |
|
73 | ||
74 |
recipients processed_recipients |
|
68 | 75 |
# Watchers in cc |
69 |
cc(issue.watcher_recipients - @recipients)
|
|
76 |
cc(processed_watchers)
|
|
70 | 77 |
s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] " |
71 | 78 |
s << "(#{issue.status.name}) " if journal.new_value_for('status_id') |
79 |
s << "[PRIVATE] " if journal.private |
|
72 | 80 |
s << issue.subject |
73 | 81 |
subject s |
74 | 82 |
body :issue => issue, |
... | ... | |
487 | 495 |
def mylogger |
488 | 496 |
Rails.logger |
489 | 497 |
end |
498 | ||
499 |
# Method for recipients or watchers preparation |
|
500 |
def prepare_receivers(receivers, project, private) |
|
501 |
processed_receivers = Array.new() |
|
502 | ||
503 |
receivers.each do |recepient| |
|
504 |
current_user = User.find_by_mail(recepient) |
|
505 |
can_see_private_messages = current_user.allowed_to?(:view_private_messages, project) |
|
506 | ||
507 |
if private |
|
508 |
next if ! can_see_private_messages |
|
509 |
end |
|
510 | ||
511 |
processed_receivers << recepient |
|
512 |
end |
|
513 | ||
514 |
processed_receivers |
|
515 |
end |
|
516 | ||
490 | 517 |
end |
491 | 518 | |
492 | 519 |
# Patch TMail so that message_id is not overwritten |
app/views/issues/_edit.html.erb | ||
---|---|---|
1 | 1 |
<% labelled_form_for @issue, :html => {:id => 'issue-form', :multipart => true} do |f| %> |
2 | 2 |
<%= error_messages_for 'issue', 'time_entry' %> |
3 | ||
4 |
<% view_private = User.current.allowed_to?(:view_private_messages, @project) %> |
|
5 | ||
3 | 6 |
<%= render :partial => 'conflict' if @conflict %> |
4 | 7 |
<div class="box"> |
5 | 8 |
<% if @edit_allowed || !@allowed_statuses.empty? %> |
... | ... | |
31 | 34 |
<%= wikitoolbar_for 'notes' %> |
32 | 35 |
<%= call_hook(:view_issues_edit_notes_bottom, { :issue => @issue, :notes => @notes, :form => f }) %> |
33 | 36 | |
37 |
<% if view_private %> |
|
38 |
<%= check_box_tag :private_message, true, false %> |
|
39 |
<%= label_tag :private_message, 'Private message', :style => 'font-weight:bold;' %> |
|
40 |
<% end %> |
|
41 | ||
34 | 42 |
<p><%=l(:label_attachment_plural)%><br /><%= render :partial => 'attachments/form', :locals => {:container => @issue} %></p> |
35 | 43 |
</fieldset> |
36 | 44 |
</div> |
app/views/issues/_history.html.erb | ||
---|---|---|
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><%= link_to "##{journal.indice}", {:anchor => "note-#{journal.indice}"}, :class => "journal-link" %> |
|
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.html.erb | ||
---|---|---|
112 | 112 |
<% end %> |
113 | 113 | |
114 | 114 |
<% if @journals.present? %> |
115 |
<div id="history"> |
|
116 |
<h3><%=l(:label_history)%></h3> |
|
117 |
<%= render :partial => 'history', :locals => { :issue => @issue, :journals => @journals } %> |
|
118 |
</div> |
|
115 |
<% view_private = User.current.allowed_to?(:view_private_messages, @project) %> |
|
116 |
<% if ! only_private_messages?(@journals) || view_private %> |
|
117 |
<div id="history"> |
|
118 |
<h3><%=l(:label_history)%></h3> |
|
119 |
<%= render :partial => 'history', :locals => { :issue => @issue, :journals => @journals } %> |
|
120 |
</div> |
|
121 |
<% end %> |
|
119 | 122 |
<% end %> |
120 | 123 | |
121 | 124 |
app/views/journals/_notes_form.html.erb | ||
---|---|---|
17 | 17 |
<%= link_to l(:button_cancel), '#', :onclick => "Element.remove('journal-#{@journal.id}-form'); " + |
18 | 18 |
"Element.show('journal-#{@journal.id}-notes'); return false;" %></p> |
19 | 19 | |
20 |
<%= check_box_tag :private_message, true, @journal.private, :id => "private_message_#{@journal.id}" %> |
|
21 |
<%= label_tag "private_message_#{@journal.id}", 'Private message', :style => 'font-weight:bold;' %> |
|
22 | ||
20 | 23 |
<div id="journal_<%= @journal.id %>_preview" class="wiki"></div> |
21 | 24 |
<% end %> |
22 | 25 |
<%= wikitoolbar_for "journal_#{@journal.id}_notes" %> |
db/migrate/20110820092133_add_private_to_journals.rb | ||
---|---|---|
1 |
class AddPrivateToJournals < ActiveRecord::Migration |
|
2 |
def self.up |
|
3 |
add_column :journals, :private, :boolean, :default => false |
|
4 |
end |
|
5 | ||
6 |
def self.down |
|
7 |
remove_column :journals, :private |
|
8 |
end |
|
9 |
end |
lib/redmine.rb | ||
---|---|---|
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| |