Commit f0f88390c1309b0d5a8cead701477e21c2174f05

Authored by Dmitriy Zaporozhets
1 parent 1d48904a

project_user selectbox with ajax autocomplete

Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
app/assets/javascripts/api.js.coffee
... ... @@ -3,6 +3,7 @@
3 3 user_path: "/api/:version/users/:id.json"
4 4 notes_path: "/api/:version/projects/:id/notes.json"
5 5 namespaces_path: "/api/:version/namespaces.json"
  6 + project_users_path: "/api/:version/projects/:id/users.json"
6 7  
7 8 # Get 20 (depends on api) recent notes
8 9 # and sort the ascending from oldest to newest
... ... @@ -50,6 +51,23 @@
50 51 ).done (users) ->
51 52 callback(users)
52 53  
  54 + # Return project users list. Filtered by query
  55 + # Only active users retrieved
  56 + projectUsers: (project_id, query, callback) ->
  57 + url = Api.buildUrl(Api.project_users_path)
  58 + url = url.replace(':id', project_id)
  59 +
  60 + $.ajax(
  61 + url: url
  62 + data:
  63 + private_token: gon.api_token
  64 + search: query
  65 + per_page: 20
  66 + active: true
  67 + dataType: "json"
  68 + ).done (users) ->
  69 + callback(users)
  70 +
53 71 # Return namespaces list. Filtered by query
54 72 namespaces: (query, callback) ->
55 73 url = Api.buildUrl(Api.namespaces_path)
... ...
app/assets/javascripts/project_users_select.js.coffee 0 → 100644
... ... @@ -0,0 +1,43 @@
  1 +$ ->
  2 + projectUserFormatResult = (user) ->
  3 + if user.avatar_url
  4 + avatar = user.avatar_url
  5 + else if gon.gravatar_enabled
  6 + avatar = gon.gravatar_url
  7 + avatar = avatar.replace('%{hash}', md5(user.email))
  8 + avatar = avatar.replace('%{size}', '24')
  9 + else
  10 + avatar = gon.relative_url_root + "/assets/no_avatar.png"
  11 +
  12 + "<div class='user-result'>
  13 + <div class='user-image'><img class='avatar s24' src='#{avatar}'></div>
  14 + <div class='user-name'>#{user.name}</div>
  15 + <div class='user-username'>#{user.username}</div>
  16 + </div>"
  17 +
  18 + projectUserFormatSelection = (user) ->
  19 + user.name
  20 +
  21 + $('.ajax-project-users-select').each (i, select) ->
  22 + project_id = $('body').data('project-id')
  23 + $(select).select2
  24 + placeholder: "Search for a user"
  25 + multiple: $(select).hasClass('multiselect')
  26 + minimumInputLength: 0
  27 + query: (query) ->
  28 + Api.projectUsers project_id, query.term, (users) ->
  29 + data = { results: users }
  30 + query.callback(data)
  31 +
  32 + initSelection: (element, callback) ->
  33 + id = $(element).val()
  34 + if id isnt ""
  35 + Api.user(id, callback)
  36 +
  37 +
  38 + formatResult: projectUserFormatResult
  39 + formatSelection: projectUserFormatSelection
  40 + dropdownCssClass: "ajax-project-users-dropdown"
  41 + dropdownAutoWidth: true
  42 + escapeMarkup: (m) -> # we do not want to escape markup since we are displaying html in results
  43 + m
... ...
app/assets/stylesheets/generic/selects.scss
... ... @@ -79,6 +79,8 @@ select {
79 79 margin-right: 10px;
80 80 }
81 81  
82   -.ajax-users-dropdown .select2-search {
83   - padding-top: 4px;
  82 +.ajax-users-dropdown, .ajax-project-users-dropdown {
  83 + .select2-search {
  84 + padding-top: 4px;
  85 + }
84 86 }
... ...
app/helpers/application_helper.rb
... ... @@ -162,15 +162,6 @@ module ApplicationHelper
162 162  
163 163 alias_method :url_to_image, :image_url
164 164  
165   - def users_select_tag(id, opts = {})
166   - css_class = "ajax-users-select "
167   - css_class << "multiselect " if opts[:multiple]
168   - css_class << (opts[:class] || '')
169   - value = opts[:selected] || ''
170   -
171   - hidden_field_tag(id, value, class: css_class)
172   - end
173   -
174 165 def body_data_page
175 166 path = controller.controller_path.split('/')
176 167 namespace = path.first if path.second
... ...
app/helpers/selects_helper.rb 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +module SelectsHelper
  2 + def users_select_tag(id, opts = {})
  3 + css_class = "ajax-users-select "
  4 + css_class << "multiselect " if opts[:multiple]
  5 + css_class << (opts[:class] || '')
  6 + value = opts[:selected] || ''
  7 +
  8 + hidden_field_tag(id, value, class: css_class)
  9 + end
  10 +
  11 + def project_users_select_tag(id, opts = {})
  12 + css_class = "ajax-project-users-select "
  13 + css_class << "multiselect " if opts[:multiple]
  14 + css_class << (opts[:class] || '')
  15 + value = opts[:selected] || ''
  16 +
  17 + hidden_field_tag(id, value, class: css_class)
  18 + end
  19 +end
... ...
app/views/projects/issues/_issues.html.haml
... ... @@ -6,7 +6,7 @@
6 6 = form_tag bulk_update_project_issues_path(@project), method: :post do
7 7 %span Update selected issues with &nbsp;
8 8 = select_tag('update[status]', options_for_select(['open', 'closed']), prompt: "Status")
9   - = select_tag('update[assignee_id]', bulk_update_assignee_options, prompt: "Assignee")
  9 + = project_users_select_tag('update[assignee_id]')
10 10 = select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone")
11 11 = hidden_field_tag 'update[issues_ids]', []
12 12 = hidden_field_tag :status, params[:status]
... ...
lib/api/projects.rb
... ... @@ -11,7 +11,7 @@ module API
11 11 end
12 12 not_found!
13 13 end
14   -
  14 +
15 15 def map_public_to_visibility_level(attrs)
16 16 publik = attrs.delete(:public)
17 17 publik = [ true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON' ].include?(publik)
... ... @@ -308,6 +308,18 @@ module API
308 308 projects = Project.where("(id in (?) OR visibility_level in (?)) AND (name LIKE (?))", ids, visibility_levels, "%#{params[:query]}%")
309 309 present paginate(projects), with: Entities::Project
310 310 end
  311 +
  312 +
  313 + # Get a users list
  314 + #
  315 + # Example Request:
  316 + # GET /users
  317 + get ':id/users' do
  318 + @users = User.where(id: user_project.team.users.map(&:id))
  319 + @users = @users.search(params[:search]) if params[:search].present?
  320 + @users = paginate @users
  321 + present @users, with: Entities::User
  322 + end
311 323 end
312 324 end
313 325 end
... ...