Merge pull request #3898 from jacargentina/notifymentioned
Notify email to mentioned users; show participants ala github on issuables
This commit is contained in:
commit
20ed39e781
|
@ -106,3 +106,7 @@ input.check_all_issues {
|
||||||
#update_status {
|
#update_status {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.participants {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ module ProjectsHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def link_to_member(project, author, opts = {})
|
def link_to_member(project, author, opts = {})
|
||||||
default_opts = { avatar: true }
|
default_opts = { avatar: true, name: true, size: 16 }
|
||||||
opts = default_opts.merge(opts)
|
opts = default_opts.merge(opts)
|
||||||
|
|
||||||
return "(deleted)" unless author
|
return "(deleted)" unless author
|
||||||
|
@ -25,10 +25,10 @@ module ProjectsHelper
|
||||||
author_html = ""
|
author_html = ""
|
||||||
|
|
||||||
# Build avatar image tag
|
# Build avatar image tag
|
||||||
author_html << image_tag(gravatar_icon(author.try(:email)), width: 16, class: "avatar avatar-inline s16") if opts[:avatar]
|
author_html << image_tag(gravatar_icon(author.try(:email), opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}") if opts[:avatar]
|
||||||
|
|
||||||
# Build name span tag
|
# Build name span tag
|
||||||
author_html << content_tag(:span, sanitize(author.name), class: 'author')
|
author_html << content_tag(:span, sanitize(author.name), class: 'author') if opts[:name]
|
||||||
|
|
||||||
author_html = author_html.html_safe
|
author_html = author_html.html_safe
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#
|
#
|
||||||
module Issuable
|
module Issuable
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
include Mentionable
|
||||||
|
|
||||||
included do
|
included do
|
||||||
belongs_to :project
|
belongs_to :project
|
||||||
|
@ -97,4 +98,18 @@ module Issuable
|
||||||
def votes_count
|
def votes_count
|
||||||
upvotes + downvotes
|
upvotes + downvotes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Return all users participating on the discussion
|
||||||
|
def participants
|
||||||
|
users = []
|
||||||
|
users << author
|
||||||
|
users << assignee if is_assigned?
|
||||||
|
mentions = []
|
||||||
|
mentions << self.mentioned_users
|
||||||
|
notes.each do |note|
|
||||||
|
users << note.author
|
||||||
|
mentions << note.mentioned_users
|
||||||
|
end
|
||||||
|
users.concat(mentions.reduce([], :|)).uniq
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
# == Mentionable concern
|
||||||
|
#
|
||||||
|
# Contains common functionality shared between Issues and Notes
|
||||||
|
#
|
||||||
|
# Used by Issue, Note
|
||||||
|
#
|
||||||
|
module Mentionable
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
def mentioned_users
|
||||||
|
users = []
|
||||||
|
return users if mentionable_text.blank?
|
||||||
|
has_project = self.respond_to? :project
|
||||||
|
matches = mentionable_text.scan(/@[a-zA-Z][a-zA-Z0-9_\-\.]*/)
|
||||||
|
matches.each do |match|
|
||||||
|
identifier = match.delete "@"
|
||||||
|
if has_project
|
||||||
|
id = project.users_projects.joins(:user).where(users: { username: identifier }).pluck(:user_id).first
|
||||||
|
else
|
||||||
|
id = User.where(username: identifier).pluck(:id).first
|
||||||
|
end
|
||||||
|
users << User.find(id) unless id.blank?
|
||||||
|
end
|
||||||
|
users.uniq
|
||||||
|
end
|
||||||
|
|
||||||
|
def mentionable_text
|
||||||
|
if self.class == Issue
|
||||||
|
description
|
||||||
|
elsif self.class == Note
|
||||||
|
note
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -19,6 +19,8 @@ require 'carrierwave/orm/activerecord'
|
||||||
require 'file_size_validator'
|
require 'file_size_validator'
|
||||||
|
|
||||||
class Note < ActiveRecord::Base
|
class Note < ActiveRecord::Base
|
||||||
|
include Mentionable
|
||||||
|
|
||||||
attr_accessible :note, :noteable, :noteable_id, :noteable_type, :project_id,
|
attr_accessible :note, :noteable, :noteable_id, :noteable_type, :project_id,
|
||||||
:attachment, :line_code, :commit_id
|
:attachment, :line_code, :commit_id
|
||||||
|
|
||||||
|
|
|
@ -110,9 +110,11 @@ class NotificationService
|
||||||
else
|
else
|
||||||
opts.merge!(noteable_id: note.noteable_id)
|
opts.merge!(noteable_id: note.noteable_id)
|
||||||
target = note.noteable
|
target = note.noteable
|
||||||
recipients = []
|
if target.respond_to?(:participants)
|
||||||
recipients << target.assignee if target.respond_to?(:assignee)
|
recipients = target.participants
|
||||||
recipients << target.author if target.respond_to?(:author)
|
else
|
||||||
|
recipients = []
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Get users who left comment in thread
|
# Get users who left comment in thread
|
||||||
|
@ -181,7 +183,12 @@ class NotificationService
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_resource_email(target, method)
|
def new_resource_email(target, method)
|
||||||
recipients = reject_muted_users([target.assignee], target.project)
|
if target.respond_to?(:participants)
|
||||||
|
recipients = target.participants
|
||||||
|
else
|
||||||
|
recipients = []
|
||||||
|
end
|
||||||
|
recipients = reject_muted_users(recipients, target.project)
|
||||||
recipients = recipients.concat(project_watchers(target.project)).uniq
|
recipients = recipients.concat(project_watchers(target.project)).uniq
|
||||||
recipients.delete(target.author)
|
recipients.delete(target.author)
|
||||||
|
|
||||||
|
|
|
@ -65,4 +65,9 @@
|
||||||
- else
|
- else
|
||||||
= link_to 'Close Issue', project_issue_path(@project, @issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn grouped close_issue", title: "Close Issue"
|
= link_to 'Close Issue', project_issue_path(@project, @issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn grouped close_issue", title: "Close Issue"
|
||||||
|
|
||||||
|
.participants
|
||||||
|
%cite.cgray #{@issue.participants.count} participants
|
||||||
|
- @issue.participants.each do |participant|
|
||||||
|
= link_to_member(@project, participant, name: false, size: 24)
|
||||||
|
|
||||||
.voting_notes#notes= render "notes/notes_with_form"
|
.voting_notes#notes= render "notes/notes_with_form"
|
||||||
|
|
|
@ -19,7 +19,7 @@ describe NotificationService do
|
||||||
describe 'Notes' do
|
describe 'Notes' do
|
||||||
context 'issue note' do
|
context 'issue note' do
|
||||||
let(:issue) { create(:issue, assignee: create(:user)) }
|
let(:issue) { create(:issue, assignee: create(:user)) }
|
||||||
let(:note) { create(:note_on_issue, noteable: issue, project_id: issue.project_id) }
|
let(:note) { create(:note_on_issue, noteable: issue, project_id: issue.project_id, note: '@mention referenced') }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
build_team(note.project)
|
build_team(note.project)
|
||||||
|
@ -30,6 +30,7 @@ describe NotificationService do
|
||||||
should_email(@u_watcher.id)
|
should_email(@u_watcher.id)
|
||||||
should_email(note.noteable.author_id)
|
should_email(note.noteable.author_id)
|
||||||
should_email(note.noteable.assignee_id)
|
should_email(note.noteable.assignee_id)
|
||||||
|
should_email(@u_mentioned.id)
|
||||||
should_not_email(note.author_id)
|
should_not_email(note.author_id)
|
||||||
should_not_email(@u_participating.id)
|
should_not_email(@u_participating.id)
|
||||||
should_not_email(@u_disabled.id)
|
should_not_email(@u_disabled.id)
|
||||||
|
@ -235,9 +236,11 @@ describe NotificationService do
|
||||||
@u_watcher = create(:user, notification_level: Notification::N_WATCH)
|
@u_watcher = create(:user, notification_level: Notification::N_WATCH)
|
||||||
@u_participating = create(:user, notification_level: Notification::N_PARTICIPATING)
|
@u_participating = create(:user, notification_level: Notification::N_PARTICIPATING)
|
||||||
@u_disabled = create(:user, notification_level: Notification::N_DISABLED)
|
@u_disabled = create(:user, notification_level: Notification::N_DISABLED)
|
||||||
|
@u_mentioned = create(:user, username: 'mention', notification_level: Notification::N_WATCH)
|
||||||
|
|
||||||
project.team << [@u_watcher, :master]
|
project.team << [@u_watcher, :master]
|
||||||
project.team << [@u_participating, :master]
|
project.team << [@u_participating, :master]
|
||||||
project.team << [@u_disabled, :master]
|
project.team << [@u_disabled, :master]
|
||||||
|
project.team << [@u_mentioned, :master]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue