Commit d41940d36ee8ff693a3c22d6c317e864b53792f0

Authored by Dmitriy Zaporozhets
2 parents 106764ab 884498c5

Merge branch 'master' into 6-0-dev

Conflicts:
	app/views/projects/issues/show.html.haml
	db/fixtures/development/09_issues.rb
	db/fixtures/development/10_merge_requests.rb
app/assets/javascripts/dispatcher.js.coffee
1 1 $ ->
2 2 new Dispatcher()
3   -
  3 +
4 4 class Dispatcher
5 5 constructor: () ->
6 6 @initSearch()
... ...
app/assets/stylesheets/sections/issues.scss
... ... @@ -106,3 +106,7 @@ input.check_all_issues {
106 106 #update_status {
107 107 width: 100px;
108 108 }
  109 +
  110 +.participants {
  111 + margin-bottom: 10px;
  112 +}
... ...
app/helpers/projects_helper.rb
... ... @@ -17,7 +17,7 @@ module ProjectsHelper
17 17 end
18 18  
19 19 def link_to_member(project, author, opts = {})
20   - default_opts = { avatar: true }
  20 + default_opts = { avatar: true, name: true, size: 16 }
21 21 opts = default_opts.merge(opts)
22 22  
23 23 return "(deleted)" unless author
... ... @@ -25,10 +25,10 @@ module ProjectsHelper
25 25 author_html = ""
26 26  
27 27 # Build avatar image tag
28   - author_html << image_tag(gravatar_icon(author.try(:email)), width: 16, class: "avatar avatar-inline s16") if opts[:avatar]
  28 + 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]
29 29  
30 30 # Build name span tag
31   - author_html << content_tag(:span, sanitize(author.name), class: 'author')
  31 + author_html << content_tag(:span, sanitize(author.name), class: 'author') if opts[:name]
32 32  
33 33 author_html = author_html.html_safe
34 34  
... ...
app/models/concerns/issuable.rb
... ... @@ -6,6 +6,7 @@
6 6 #
7 7 module Issuable
8 8 extend ActiveSupport::Concern
  9 + include Mentionable
9 10  
10 11 included do
11 12 belongs_to :project
... ... @@ -96,4 +97,18 @@ module Issuable
96 97 def votes_count
97 98 upvotes + downvotes
98 99 end
  100 +
  101 + # Return all users participating on the discussion
  102 + def participants
  103 + users = []
  104 + users << author
  105 + users << assignee if is_assigned?
  106 + mentions = []
  107 + mentions << self.mentioned_users
  108 + notes.each do |note|
  109 + users << note.author
  110 + mentions << note.mentioned_users
  111 + end
  112 + users.concat(mentions.reduce([], :|)).uniq
  113 + end
99 114 end
... ...
app/models/concerns/mentionable.rb 0 → 100644
... ... @@ -0,0 +1,37 @@
  1 +# == Mentionable concern
  2 +#
  3 +# Contains common functionality shared between Issues and Notes
  4 +#
  5 +# Used by Issue, Note
  6 +#
  7 +module Mentionable
  8 + extend ActiveSupport::Concern
  9 +
  10 + def mentioned_users
  11 + users = []
  12 + return users if mentionable_text.blank?
  13 + has_project = self.respond_to? :project
  14 + matches = mentionable_text.scan(/@[a-zA-Z][a-zA-Z0-9_\-\.]*/)
  15 + matches.each do |match|
  16 + identifier = match.delete "@"
  17 + if has_project
  18 + id = project.users_projects.joins(:user).where(users: { username: identifier }).pluck(:user_id).first
  19 + else
  20 + id = User.where(username: identifier).pluck(:id).first
  21 + end
  22 + users << User.find(id) unless id.blank?
  23 + end
  24 + users.uniq
  25 + end
  26 +
  27 + def mentionable_text
  28 + if self.class == Issue
  29 + description
  30 + elsif self.class == Note
  31 + note
  32 + else
  33 + nil
  34 + end
  35 + end
  36 +
  37 +end
... ...
app/models/note.rb
... ... @@ -19,6 +19,8 @@ require &#39;carrierwave/orm/activerecord&#39;
19 19 require 'file_size_validator'
20 20  
21 21 class Note < ActiveRecord::Base
  22 + include Mentionable
  23 +
22 24 attr_accessible :note, :noteable, :noteable_id, :noteable_type, :project_id,
23 25 :attachment, :line_code, :commit_id
24 26  
... ...
app/services/notification_service.rb
... ... @@ -110,9 +110,11 @@ class NotificationService
110 110 else
111 111 opts.merge!(noteable_id: note.noteable_id)
112 112 target = note.noteable
113   - recipients = []
114   - recipients << target.assignee if target.respond_to?(:assignee)
115   - recipients << target.author if target.respond_to?(:author)
  113 + if target.respond_to?(:participants)
  114 + recipients = target.participants
  115 + else
  116 + recipients = []
  117 + end
116 118 end
117 119  
118 120 # Get users who left comment in thread
... ... @@ -190,7 +192,12 @@ class NotificationService
190 192 end
191 193  
192 194 def new_resource_email(target, method)
193   - recipients = reject_muted_users([target.assignee], target.project)
  195 + if target.respond_to?(:participants)
  196 + recipients = target.participants
  197 + else
  198 + recipients = []
  199 + end
  200 + recipients = reject_muted_users(recipients, target.project)
194 201 recipients = recipients.concat(project_watchers(target.project)).uniq
195 202 recipients.delete(target.author)
196 203  
... ...
app/views/projects/issues/show.html.haml
... ... @@ -65,4 +65,9 @@
65 65 - else
66 66 = 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"
67 67  
  68 +.participants
  69 + %cite.cgray #{@issue.participants.count} participants
  70 + - @issue.participants.each do |participant|
  71 + = link_to_member(@project, participant, name: false, size: 24)
  72 +
68 73 .voting_notes#notes= render "projects/notes/notes_with_form"
... ...
db/fixtures/development/09_issues.rb
... ... @@ -11,6 +11,7 @@ Gitlab::Seeder.quiet do
11 11 next unless user
12 12  
13 13 user_id = user.id
  14 + Thread.current[:current_user] = user
14 15  
15 16 Issue.seed(:id, [{
16 17 id: i,
... ...
db/fixtures/development/10_merge_requests.rb
... ... @@ -17,6 +17,8 @@ Gitlab::Seeder.quiet do
17 17 next if branches.uniq.size < 2
18 18  
19 19 user_id = user.id
  20 + Thread.current[:current_user] = user
  21 +
20 22 MergeRequest.seed(:id, [{
21 23 id: i,
22 24 source_branch: branches.first,
... ...
doc/update/5.0-to-5.1.md
... ... @@ -41,6 +41,7 @@ sudo -u git -H cp config/puma.rb.example config/puma.rb
41 41 sudo -u git -H bundle install --without development test postgres --deployment
42 42 sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
43 43 sudo -u git -H bundle exec rake migrate_merge_requests RAILS_ENV=production
  44 +sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
44 45 ```
45 46  
46 47 ### 5. Update init.d script with a new one
... ...
doc/update/5.2-to-5.3.md
... ... @@ -38,8 +38,8 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
38 38  
39 39 ### 4. Update config files
40 40  
41   -* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/5-2-stable/config/gitlab.yml.example but with your settings.
42   -* Make `/home/git/gitlab/config/puma.rb` same as https://github.com/gitlabhq/gitlabhq/blob/5-2-stable/config/puma.rb.example but with your settings.
  41 +* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/5-3-stable/config/gitlab.yml.example but with your settings.
  42 +* Make `/home/git/gitlab/config/puma.rb` same as https://github.com/gitlabhq/gitlabhq/blob/5-3-stable/config/puma.rb.example but with your settings.
43 43  
44 44 ### 5. Update Init script
45 45  
... ...
spec/services/notification_service_spec.rb
... ... @@ -19,7 +19,7 @@ describe NotificationService do
19 19 describe 'Notes' do
20 20 context 'issue note' do
21 21 let(:issue) { create(:issue, assignee: create(:user)) }
22   - let(:note) { create(:note_on_issue, noteable: issue, project_id: issue.project_id) }
  22 + let(:note) { create(:note_on_issue, noteable: issue, project_id: issue.project_id, note: '@mention referenced') }
23 23  
24 24 before do
25 25 build_team(note.project)
... ... @@ -30,6 +30,7 @@ describe NotificationService do
30 30 should_email(@u_watcher.id)
31 31 should_email(note.noteable.author_id)
32 32 should_email(note.noteable.assignee_id)
  33 + should_email(@u_mentioned.id)
33 34 should_not_email(note.author_id)
34 35 should_not_email(@u_participating.id)
35 36 should_not_email(@u_disabled.id)
... ... @@ -235,9 +236,11 @@ describe NotificationService do
235 236 @u_watcher = create(:user, notification_level: Notification::N_WATCH)
236 237 @u_participating = create(:user, notification_level: Notification::N_PARTICIPATING)
237 238 @u_disabled = create(:user, notification_level: Notification::N_DISABLED)
  239 + @u_mentioned = create(:user, username: 'mention', notification_level: Notification::N_WATCH)
238 240  
239 241 project.team << [@u_watcher, :master]
240 242 project.team << [@u_participating, :master]
241 243 project.team << [@u_disabled, :master]
  244 + project.team << [@u_mentioned, :master]
242 245 end
243 246 end
... ...