mirror of
https://github.com/wahyd4/gitlabhq.git
synced 2026-08-20 10:06:04 +10:00
Merge branch 'issue_14423' into 'master'
Put issuable owner and participating people first on mention suggestions Closes #14423 **Merge Requests** Author and people who participated are first now <img src="/uploads/dd75937627c61b5efe631b4a35f274c6/Screen_Shot_2016-03-29_at_6.41.29_PM.png" width="235" /> **Issues** Author showing first and no people have participated <img src="/uploads/e17aa96ffe7d46a7dbe293318e999e1d/Screen_Shot_2016-03-29_at_6.41.44_PM.png" width="279" /> See merge request !3448
This commit is contained in:
@@ -74,6 +74,7 @@ v 8.7.0 (unreleased)
|
||||
- Selected diff rows highlight
|
||||
- Fix emoji categories in the emoji picker
|
||||
- Add encrypted credentials for imported projects and migrate old ones
|
||||
- Author and participants are displayed first on users autocompletion
|
||||
|
||||
v 8.6.6
|
||||
- Expire the exists cache before deletion to ensure project dir actually exists (Stan Hu). !3413
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
window.GitLab ?= {}
|
||||
GitLab.GfmAutoComplete =
|
||||
dataLoading: false
|
||||
|
||||
dataSource: ''
|
||||
|
||||
# Emoji
|
||||
@@ -17,17 +19,41 @@ GitLab.GfmAutoComplete =
|
||||
template: '<li><small>${id}</small> ${title}</li>'
|
||||
|
||||
# Add GFM auto-completion to all input fields, that accept GFM input.
|
||||
setup: ->
|
||||
input = $('.js-gfm-input')
|
||||
setup: (wrap) ->
|
||||
@input = $('.js-gfm-input')
|
||||
|
||||
# destroy previous instances
|
||||
@destroyAtWho()
|
||||
|
||||
# set up instances
|
||||
@setupAtWho()
|
||||
|
||||
if @dataSource
|
||||
if !@dataLoading
|
||||
@dataLoading = true
|
||||
|
||||
# We should wait until initializations are done
|
||||
# and only trigger the last .setup since
|
||||
# The previous .dataSource belongs to the previous issuable
|
||||
# and the last one will have the **proper** .dataSource property
|
||||
# TODO: Make this a singleton and turn off events when moving to another page
|
||||
setTimeout( =>
|
||||
fetch = @fetchData(@dataSource)
|
||||
fetch.done (data) =>
|
||||
@dataLoading = false
|
||||
@loadData(data)
|
||||
, 1000)
|
||||
|
||||
|
||||
setupAtWho: ->
|
||||
# Emoji
|
||||
input.atwho
|
||||
@input.atwho
|
||||
at: ':'
|
||||
displayTpl: @Emoji.template
|
||||
insertTpl: ':${name}:'
|
||||
|
||||
# Team Members
|
||||
input.atwho
|
||||
@input.atwho
|
||||
at: '@'
|
||||
displayTpl: @Members.template
|
||||
insertTpl: '${atwho-at}${username}'
|
||||
@@ -42,7 +68,7 @@ GitLab.GfmAutoComplete =
|
||||
title: sanitize(title)
|
||||
search: sanitize("#{m.username} #{m.name}")
|
||||
|
||||
input.atwho
|
||||
@input.atwho
|
||||
at: '#'
|
||||
alias: 'issues'
|
||||
searchKey: 'search'
|
||||
@@ -55,7 +81,7 @@ GitLab.GfmAutoComplete =
|
||||
title: sanitize(i.title)
|
||||
search: "#{i.iid} #{i.title}"
|
||||
|
||||
input.atwho
|
||||
@input.atwho
|
||||
at: '!'
|
||||
alias: 'mergerequests'
|
||||
searchKey: 'search'
|
||||
@@ -68,13 +94,18 @@ GitLab.GfmAutoComplete =
|
||||
title: sanitize(m.title)
|
||||
search: "#{m.iid} #{m.title}"
|
||||
|
||||
if @dataSource
|
||||
$.getJSON(@dataSource).done (data) ->
|
||||
# load members
|
||||
input.atwho 'load', '@', data.members
|
||||
# load issues
|
||||
input.atwho 'load', 'issues', data.issues
|
||||
# load merge requests
|
||||
input.atwho 'load', 'mergerequests', data.mergerequests
|
||||
# load emojis
|
||||
input.atwho 'load', ':', data.emojis
|
||||
destroyAtWho: ->
|
||||
@input.atwho('destroy')
|
||||
|
||||
fetchData: (dataSource) ->
|
||||
$.getJSON(dataSource)
|
||||
|
||||
loadData: (data) ->
|
||||
# load members
|
||||
@input.atwho 'load', '@', data.members
|
||||
# load issues
|
||||
@input.atwho 'load', 'issues', data.issues
|
||||
# load merge requests
|
||||
@input.atwho 'load', 'mergerequests', data.mergerequests
|
||||
# load emojis
|
||||
@input.atwho 'load', ':', data.emojis
|
||||
|
||||
@@ -1,28 +1,37 @@
|
||||
module Projects
|
||||
class ParticipantsService < BaseService
|
||||
def execute(note_type, note_id)
|
||||
participating =
|
||||
if note_type && note_id
|
||||
participants_in(note_type, note_id)
|
||||
else
|
||||
[]
|
||||
end
|
||||
def execute(noteable_type, noteable_id)
|
||||
@noteable_type = noteable_type
|
||||
@noteable_id = noteable_id
|
||||
project_members = sorted(project.team.members)
|
||||
participants = all_members + groups + project_members + participating
|
||||
participants = target_owner + participants_in_target + all_members + groups + project_members
|
||||
participants.uniq
|
||||
end
|
||||
|
||||
def participants_in(type, id)
|
||||
target =
|
||||
case type
|
||||
def target
|
||||
@target ||=
|
||||
case @noteable_type
|
||||
when "Issue"
|
||||
project.issues.find_by_iid(id)
|
||||
project.issues.find_by_iid(@noteable_id)
|
||||
when "MergeRequest"
|
||||
project.merge_requests.find_by_iid(id)
|
||||
project.merge_requests.find_by_iid(@noteable_id)
|
||||
when "Commit"
|
||||
project.commit(id)
|
||||
project.commit(@noteable_id)
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def target_owner
|
||||
return [] unless target && target.author.present?
|
||||
|
||||
[{
|
||||
name: target.author.name,
|
||||
username: target.author.username
|
||||
}]
|
||||
end
|
||||
|
||||
def participants_in_target
|
||||
return [] unless target
|
||||
|
||||
users = target.participants(current_user)
|
||||
@@ -30,13 +39,13 @@ module Projects
|
||||
end
|
||||
|
||||
def sorted(users)
|
||||
users.uniq.to_a.compact.sort_by(&:username).map do |user|
|
||||
users.uniq.to_a.compact.sort_by(&:username).map do |user|
|
||||
{ username: user.username, name: user.name }
|
||||
end
|
||||
end
|
||||
|
||||
def groups
|
||||
current_user.authorized_groups.sort_by(&:path).map do |group|
|
||||
current_user.authorized_groups.sort_by(&:path).map do |group|
|
||||
count = group.users.count
|
||||
{ username: group.path, name: group.name, count: count }
|
||||
end
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
require 'spec_helper'
|
||||
|
||||
feature 'Member autocomplete', feature: true do
|
||||
let(:project) { create(:project, :public) }
|
||||
let(:user) { create(:user) }
|
||||
let(:participant) { create(:user) }
|
||||
let(:author) { create(:user) }
|
||||
|
||||
before do
|
||||
allow_any_instance_of(Commit).to receive(:author).and_return(author)
|
||||
login_as user
|
||||
end
|
||||
|
||||
shared_examples "open suggestions" do
|
||||
it 'suggestions are displayed' do
|
||||
expect(page).to have_selector('.atwho-view', visible: true)
|
||||
end
|
||||
|
||||
it 'author is suggested' do
|
||||
page.within('.atwho-view', visible: true) do
|
||||
expect(page).to have_content(author.username)
|
||||
end
|
||||
end
|
||||
|
||||
it 'participant is suggested' do
|
||||
page.within('.atwho-view', visible: true) do
|
||||
expect(page).to have_content(participant.username)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'adding a new note on a Issue', js: true do
|
||||
before do
|
||||
issue = create(:issue, author: author, project: project)
|
||||
create(:note, note: 'Ultralight Beam', noteable: issue, author: participant)
|
||||
visit_issue(project, issue)
|
||||
end
|
||||
|
||||
context 'when typing @' do
|
||||
include_examples "open suggestions"
|
||||
before do
|
||||
open_member_suggestions
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'adding a new note on a Merge Request ', js: true do
|
||||
before do
|
||||
merge = create(:merge_request, source_project: project, target_project: project, author: author)
|
||||
create(:note, note: 'Ultralight Beam', noteable: merge, author: participant)
|
||||
visit_merge_request(project, merge)
|
||||
end
|
||||
|
||||
context 'when typing @' do
|
||||
include_examples "open suggestions"
|
||||
before do
|
||||
open_member_suggestions
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'adding a new note on a Commit ', js: true do
|
||||
let(:commit) { project.commit }
|
||||
|
||||
before do
|
||||
allow(commit).to receive(:author).and_return(author)
|
||||
create(:note_on_commit, author: participant, project: project, commit_id: project.repository.commit.id, note: 'No More Parties in LA')
|
||||
visit_commit(project, commit)
|
||||
end
|
||||
|
||||
context 'when typing @' do
|
||||
include_examples "open suggestions"
|
||||
before do
|
||||
open_member_suggestions
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def open_member_suggestions
|
||||
sleep 1
|
||||
page.within('.new-note') do
|
||||
sleep 1
|
||||
find('#note_note').native.send_keys('@')
|
||||
end
|
||||
end
|
||||
|
||||
def visit_issue(project, issue)
|
||||
visit namespace_project_issue_path(project.namespace, project, issue)
|
||||
end
|
||||
|
||||
def visit_merge_request(project, merge)
|
||||
visit namespace_project_merge_request_path(project.namespace, project, merge)
|
||||
end
|
||||
|
||||
def visit_commit(project, commit)
|
||||
visit namespace_project_commit_path(project.namespace, project, commit)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user