Patch #43990 » 0001-Add-detailed-issue-notifications.patch
| app/assets/stylesheets/application.css | ||
|---|---|---|
| 1344 | 1344 | |
| 1345 | 1345 |
fieldset.settings label { display: block; }
|
| 1346 | 1346 |
fieldset#notified_events .parent { padding-inline-start: 20px; }
|
| 1347 |
fieldset#notified_events .notification-details { padding-inline-start: 40px; border: 0px;}
|
|
| 1347 | 1348 | |
| 1348 | 1349 |
span.required {color: var(--oc-red-9);}
|
| 1349 | 1350 |
.summary {font-style: italic;}
|
| app/helpers/settings_helper.rb | ||
|---|---|---|
| 122 | 122 | |
| 123 | 123 |
# Renders a notification field for a Redmine::Notifiable option |
| 124 | 124 |
def notification_field(notifiable) |
| 125 |
checked = setting_value('notified_events').include?(notifiable.name)
|
|
| 125 | 126 |
tag_data = |
| 126 | 127 |
if notifiable.parent.present? |
| 127 |
{:parent_notifiable => notifiable.parent}
|
|
| 128 |
{:parent_notifiable => notifiable.parent,
|
|
| 129 |
:disables => "fieldset[data-parent-notifiable=#{notifiable.name}]"}
|
|
| 128 | 130 |
else |
| 129 | 131 |
{:disables => "input[data-parent-notifiable=#{notifiable.name}]"}
|
| 130 | 132 |
end |
| 131 | 133 |
tag = check_box_tag('settings[notified_events][]',
|
| 132 | 134 |
notifiable.name, |
| 133 |
setting_value('notified_events').include?(notifiable.name),
|
|
| 135 |
checked,
|
|
| 134 | 136 |
:id => nil, |
| 135 | 137 |
:data => tag_data) |
| 136 | 138 |
text = l_or_humanize(notifiable.name, :prefix => 'label_') |
| ... | ... | |
| 138 | 140 |
if notifiable.parent.present? |
| 139 | 141 |
options[:class] = "parent" |
| 140 | 142 |
end |
| 141 |
content_tag(:label, tag + text, options) |
|
| 143 |
label = content_tag(:label, tag + text, options) |
|
| 144 | ||
| 145 |
if detailed_notifiable?(notifiable) |
|
| 146 |
label + notification_details_fieldset(notifiable, checked) |
|
| 147 |
else |
|
| 148 |
label + "<br />".html_safe |
|
| 149 |
end |
|
| 142 | 150 |
end |
| 143 | 151 | |
| 144 | 152 |
def session_lifetime_options |
| ... | ... | |
| 248 | 256 |
['Retro', 'retro'], |
| 249 | 257 |
['Robohash', 'robohash']] |
| 250 | 258 |
end |
| 259 | ||
| 260 |
def issue_attribute_options(except: []) |
|
| 261 |
attrs = Issue.new.safe_attribute_names |
|
| 262 |
options = attrs.filter_map do |attr| |
|
| 263 |
next if except.include?(attr) |
|
| 264 | ||
| 265 |
label = l("field_#{attr.gsub(/_id$/, '')}", default: nil)
|
|
| 266 |
[label, attr] if label.present? |
|
| 267 |
end |
|
| 268 |
options << [l(:label_subtask_plural), 'child_id'] |
|
| 269 |
options << [l(:field_parent_issue), 'parent_id'] |
|
| 270 |
options.sort_by(&:first) |
|
| 271 |
end |
|
| 272 | ||
| 273 |
def issue_custom_field_options |
|
| 274 |
IssueCustomField |
|
| 275 |
.sorted |
|
| 276 |
.map { |cf| [cf.name, cf.id.to_s] }
|
|
| 277 |
end |
|
| 278 | ||
| 279 |
def issue_relation_options |
|
| 280 |
IssueRelation::TYPES.map do |name, _| |
|
| 281 |
[l("label_relation_#{name}", default: nil) ||
|
|
| 282 |
l("label_#{name}_to", default: nil) ||
|
|
| 283 |
l("label_#{name}_by", default: nil) ||
|
|
| 284 |
l("label_#{name}", default: nil) || name, name]
|
|
| 285 |
end |
|
| 286 |
end |
|
| 287 | ||
| 288 |
def notification_details_fieldset(notifiable, checked) |
|
| 289 |
notifiable_setting_key = "notified_event_#{notifiable.name}_details"
|
|
| 290 |
content_tag( |
|
| 291 |
:fieldset, |
|
| 292 |
class: 'notification-details', |
|
| 293 |
disabled: checked, |
|
| 294 |
data: { parent_notifiable: notifiable.name }
|
|
| 295 |
) do |
|
| 296 |
select_tag( |
|
| 297 |
"settings[#{notifiable_setting_key}][]",
|
|
| 298 |
options_for_select( |
|
| 299 |
notifiable_field_options(notifiable), |
|
| 300 |
setting_value(notifiable_setting_key) |
|
| 301 |
), |
|
| 302 |
multiple: true, |
|
| 303 |
size: 6, |
|
| 304 |
class: 'multiselect wide' |
|
| 305 |
) + |
|
| 306 |
hidden_field_tag("settings[#{notifiable_setting_key}][]", "", id: nil)
|
|
| 307 |
end |
|
| 308 |
end |
|
| 309 | ||
| 310 |
def notifiable_field_options(notifiable) |
|
| 311 |
case notifiable.name |
|
| 312 |
when 'issue_attr_updated' |
|
| 313 |
issue_attribute_options(except: %w[notes]) |
|
| 314 |
when 'issue_relation_updated' |
|
| 315 |
issue_relation_options |
|
| 316 |
when 'issue_cf_updated' |
|
| 317 |
issue_custom_field_options |
|
| 318 |
else |
|
| 319 |
[] |
|
| 320 |
end |
|
| 321 |
end |
|
| 322 | ||
| 323 |
def detailed_notifiable?(notifiable) |
|
| 324 |
notifiable_field_options(notifiable).present? |
|
| 325 |
end |
|
| 251 | 326 |
end |
| app/models/journal.rb | ||
|---|---|---|
| 378 | 378 |
( |
| 379 | 379 |
Setting.notified_events.include?('issue_updated') ||
|
| 380 | 380 |
(Setting.notified_events.include?('issue_note_added') && notes.present?) ||
|
| 381 |
(Setting.notified_events.include?('issue_status_updated') && new_status.present?) ||
|
|
| 382 |
(Setting.notified_events.include?('issue_assigned_to_updated') && detail_for_attribute('assigned_to_id').present?) ||
|
|
| 383 |
(Setting.notified_events.include?('issue_priority_updated') && new_value_for('priority_id').present?) ||
|
|
| 384 |
(Setting.notified_events.include?('issue_fixed_version_updated') && detail_for_attribute('fixed_version_id').present?) ||
|
|
| 385 |
(Setting.notified_events.include?('issue_attachment_added') && details.any? {|d| d.property == 'attachment' && d.value })
|
|
| 381 |
(Setting.notified_events.include?('issue_attachment_added') && details.any? {|d| d.property == 'attachment' && d.value }) ||
|
|
| 382 |
notify_by_details?(Setting.notified_events.include?('issue_attr_updated'), 'attr', Setting.notified_event_issue_attr_updated_details) ||
|
|
| 383 |
notify_by_details?(Setting.notified_events.include?('issue_relation_updated'), 'relation', Setting.notified_event_issue_relation_updated_details) ||
|
|
| 384 |
notify_by_details?(Setting.notified_events.include?('issue_cf_updated'), 'cf', Setting.notified_event_issue_cf_updated_details)
|
|
| 386 | 385 |
) |
| 387 | 386 |
Mailer.deliver_issue_edit(self) |
| 388 | 387 |
end |
| ... | ... | |
| 394 | 393 |
end |
| 395 | 394 |
notified |
| 396 | 395 |
end |
| 396 | ||
| 397 |
def notify_by_details?(notify_all, property, prop_keys) |
|
| 398 |
return false unless notify_all || prop_keys.present? |
|
| 399 | ||
| 400 |
relevant_details = details.select { |d| d.property == property }
|
|
| 401 |
return false if relevant_details.empty? |
|
| 402 |
return true if notify_all |
|
| 403 | ||
| 404 |
allowed = Array(prop_keys).map(&:to_s) |
|
| 405 |
relevant_details.any? do |detail| |
|
| 406 |
allowed.include?(detail.prop_key.to_s) |
|
| 407 |
end |
|
| 408 |
end |
|
| 397 | 409 |
end |
| app/views/settings/_notifications.html.erb | ||
|---|---|---|
| 13 | 13 |
<%= hidden_field_tag 'settings[notified_events][]', '' %> |
| 14 | 14 |
<% @notifiables.each do |notifiable| %> |
| 15 | 15 |
<%= notification_field notifiable %> |
| 16 |
<br /> |
|
| 17 | 16 |
<% end %> |
| 18 | 17 |
<p><%= check_all_links('notified_events') %></p>
|
| 19 | 18 |
</fieldset> |
| config/settings.yml | ||
|---|---|---|
| 203 | 203 |
default: |
| 204 | 204 |
- issue_added |
| 205 | 205 |
- issue_updated |
| 206 |
notified_event_issue_attr_updated_details: |
|
| 207 |
serialized: true |
|
| 208 |
default: [] |
|
| 209 |
notified_event_issue_relation_updated_details: |
|
| 210 |
serialized: true |
|
| 211 |
default: [] |
|
| 212 |
notified_event_issue_cf_updated_details: |
|
| 213 |
serialized: true |
|
| 214 |
default: [] |
|
| 206 | 215 |
mail_handler_body_delimiters: |
| 207 | 216 |
default: '' |
| 208 | 217 |
mail_handler_enable_regex_delimiters: |
| lib/redmine/notifiable.rb | ||
|---|---|---|
| 29 | 29 |
notifications << Notifiable.new('issue_added')
|
| 30 | 30 |
notifications << Notifiable.new('issue_updated')
|
| 31 | 31 |
notifications << Notifiable.new('issue_note_added', 'issue_updated')
|
| 32 |
notifications << Notifiable.new('issue_status_updated', 'issue_updated')
|
|
| 33 |
notifications << Notifiable.new('issue_assigned_to_updated', 'issue_updated')
|
|
| 34 |
notifications << Notifiable.new('issue_priority_updated', 'issue_updated')
|
|
| 35 |
notifications << Notifiable.new('issue_fixed_version_updated', 'issue_updated')
|
|
| 36 | 32 |
notifications << Notifiable.new('issue_attachment_added', 'issue_updated')
|
| 33 |
notifications << Notifiable.new('issue_attr_updated', 'issue_updated')
|
|
| 34 |
notifications << Notifiable.new('issue_relation_updated', 'issue_updated')
|
|
| 35 |
notifications << Notifiable.new('issue_cf_updated', 'issue_updated')
|
|
| 37 | 36 |
notifications << Notifiable.new('news_added')
|
| 38 | 37 |
notifications << Notifiable.new('news_comment_added')
|
| 39 | 38 |
notifications << Notifiable.new('document_added')
|