Commit 60b4c88e3a175fa8b1fdebede4a5c5f73df0eee5

Authored by Dmitriy Zaporozhets
2 parents a100c578 4d843d2c

Merge pull request #1664 from riyad/auto-complete-everywhere

Cleanup auto-completion and add it to all GFM inputs
app/assets/javascripts/gfm_auto_complete.js.coffee 0 → 100644
... ... @@ -0,0 +1,57 @@
  1 +
  2 +###
  3 + Creates the variables for setting up GFM auto-completion
  4 +###
  5 +# Emoji
  6 +window.autocompleteEmojiData = [];
  7 +window.autocompleteEmojiTemplate = "<li data-value='${insert}'>${name} <img alt='${name}' height='20' src='${image}' width='20' /></li>";
  8 +
  9 +# Team Members
  10 +window.autocompleteMembersUrl = "";
  11 +window.autocompleteMembersParams =
  12 + private_token: ""
  13 + page: 1
  14 +window.autocompleteMembersData = [];
  15 +
  16 +
  17 +
  18 +###
  19 + Add GFM auto-completion to all input fields, that accept GFM input.
  20 +###
  21 +window.setupGfmAutoComplete = ->
  22 + ###
  23 + Emoji
  24 + ###
  25 + $('.gfm-input').atWho ':',
  26 + data: autocompleteEmojiData,
  27 + tpl: autocompleteEmojiTemplate
  28 +
  29 + ###
  30 + Team Members
  31 + ###
  32 + $('.gfm-input').atWho '@', (query, callback) ->
  33 + (getMoreMembers = ->
  34 + $.getJSON(autocompleteMembersUrl, autocompleteMembersParams)
  35 + .success (members) ->
  36 + # pick the data we need
  37 + newMembersData = $.map members, (m) -> m.name
  38 +
  39 + # add the new page of data to the rest
  40 + $.merge autocompleteMembersData, newMembersData
  41 +
  42 + # show the pop-up with a copy of the current data
  43 + callback autocompleteMembersData[..]
  44 +
  45 + # are we past the last page?
  46 + if newMembersData.length == 0
  47 + # set static data and stop callbacks
  48 + $('.gfm-input').atWho '@',
  49 + data: autocompleteMembersData
  50 + callback: null
  51 + else
  52 + # get next page
  53 + getMoreMembers()
  54 +
  55 + # so the next request gets the next page
  56 + autocompleteMembersParams.page += 1;
  57 + ).call();
0 58 \ No newline at end of file
... ...
app/assets/javascripts/issues.js
... ... @@ -6,6 +6,7 @@ function switchToNewIssue(form){
6 6 $("#new_issue_dialog").show("fade", { direction: "right" }, 150);
7 7 $('.top-tabs .add_new').hide();
8 8 disableButtonIfEmptyField("#issue_title", ".save-btn");
  9 + setupGfmAutoComplete();
9 10 });
10 11 }
11 12  
... ... @@ -17,6 +18,7 @@ function switchToEditIssue(form){
17 18 $("#edit_issue_dialog").show("fade", { direction: "right" }, 150);
18 19 $('.add_new').hide();
19 20 disableButtonIfEmptyField("#issue_title", ".save-btn");
  21 + setupGfmAutoComplete();
20 22 });
21 23 }
22 24  
... ...
app/helpers/application_helper.rb
... ... @@ -98,6 +98,12 @@ module ApplicationHelper
98 98 [projects, default_nav, project_nav].flatten.to_json
99 99 end
100 100  
  101 + def emoji_autocomplete_source
  102 + # should be an array of strings
  103 + # so to_s can be called, because it is sufficient and to_json is too slow
  104 + Emoji::NAMES.to_s
  105 + end
  106 +
101 107 def ldap_enable?
102 108 Devise.omniauth_providers.include?(:ldap)
103 109 end
... ...
app/helpers/notes_helper.rb
... ... @@ -14,10 +14,4 @@ module NotesHelper
14 14 "vote downvote"
15 15 end
16 16 end
17   -
18   - def emoji_for_completion
19   - # should be an array of strings
20   - # so to_s can be called, because it is sufficient and to_json is too slow
21   - Emoji::NAMES
22   - end
23 17 end
... ...
app/views/issues/_form.html.haml
... ... @@ -12,7 +12,7 @@
12 12 = f.label :title do
13 13 %strong= "Subject *"
14 14 .input
15   - = f.text_field :title, maxlength: 255, class: "xxlarge"
  15 + = f.text_field :title, maxlength: 255, class: "xxlarge gfm-input"
16 16 .issue_middle_block
17 17 .issue_assignee
18 18 = f.label :assignee_id do
... ... @@ -37,7 +37,7 @@
37 37 .clearfix
38 38 = f.label :description, "Details"
39 39 .input
40   - = f.text_area :description, maxlength: 2000, class: "xxlarge", rows: 14
  40 + = f.text_area :description, maxlength: 2000, class: "xxlarge gfm-input", rows: 14
41 41 %p.hint Issues are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
42 42  
43 43  
... ...
app/views/layouts/_head_panel.html.haml
... ... @@ -28,6 +28,8 @@
28 28 My profile
29 29 = link_to 'Logout', destroy_user_session_path, class: "logout", method: :delete
30 30  
  31 += render "layouts/init_auto_complete"
  32 +
31 33 :javascript
32 34 $(function(){
33 35 $("#search").autocomplete({
... ...
app/views/layouts/_init_auto_complete.html.haml 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +:javascript
  2 + $(function() {
  3 + autocompleteMembersUrl = "#{ "/api/v2/projects/#{@project.code}/members" if @project }";
  4 + autocompleteMembersParams.private_token = "#{current_user.authentication_token}";
  5 +
  6 + autocompleteEmojiData = #{raw emoji_autocomplete_source};
  7 + // convert the list so that the items have the right format for completion
  8 + autocompleteEmojiData = $.map(autocompleteEmojiData, function(value) {
  9 + return {
  10 + name: value,
  11 + insert: value+':',
  12 + image: '#{image_path("emoji")}/'+value+'.png'
  13 + }
  14 + });
  15 +
  16 + setupGfmAutoComplete();
  17 + });
... ...
app/views/merge_requests/_form.html.haml
... ... @@ -38,7 +38,7 @@
38 38 .top_box_content
39 39 = f.label :title do
40 40 %strong= "Title *"
41   - .input= f.text_field :title, class: "input-xxlarge pad", maxlength: 255, rows: 5
  41 + .input= f.text_field :title, class: "input-xxlarge pad gfm-input", maxlength: 255, rows: 5
42 42 .middle_box_content
43 43 = f.label :assignee_id do
44 44 %i.icon-user
... ...
app/views/notes/_common_form.html.haml
... ... @@ -36,49 +36,3 @@
36 36 %a.file_upload.btn.small Upload File
37 37 = f.file_field :attachment, class: "input-file"
38 38 %span.hint Any file less than 10 MB
39   -
40   -:javascript
41   - $(function(){
42   - // init auto-completion of team members
43   - var membersUrl = "#{root_url}/api/v2/projects/#{@project.code}/members";
44   - var membersParams = {
45   - private_token: "#{current_user.authentication_token}",
46   - page: 1,
47   - };
48   - var membersData = [];
49   - $('.gfm-input').atWho('@', function(query, callback) {
50   - (function getMoreMembers() {
51   - $.getJSON(membersUrl, membersParams).
52   - success(function(members) {
53   - // pick the data we need
54   - var newMembersData = $.map(members, function(member) { return member.name });
55   -
56   - // add the new page of data to the rest
57   - $.merge(membersData, newMembersData);
58   -
59   - // show the pop-up with a copy of the current data
60   - callback(membersData.slice(0));
61   -
62   - // are we past the last page?
63   - if (newMembersData.length == 0) {
64   - // set static data and stop callbacks
65   - $('.gfm-input').atWho('@', { data: membersData, callback: null });
66   - } else {
67   - // get next page
68   - getMoreMembers();
69   - }
70   - });
71   - // next request will get the next page
72   - membersParams.page += 1;
73   - })();
74   - });
75   -
76   - // init auto-completion of emoji
77   - var emoji = #{emoji_for_completion};
78   - // convert the list so that the items have the right format for completion
79   - emoji = $.map(emoji, function(value) {return { key: value+':', name: value }});
80   - $('.gfm-input').atWho(':', {
81   - data: emoji,
82   - tpl: "<li data-value='${key}'>${name} #{escape_javascript image_tag('emoji/${name}.png', :size => '20x20')}</li>"
83   - });
84   - });
... ...
app/views/notes/_create_common_note.js.haml
... ... @@ -10,4 +10,5 @@
10 10 - else
11 11 :plain
12 12 $(".note-form-holder").replaceWith("#{escape_javascript(render 'form')}");
  13 + setupGfmAutoComplete();
13 14  
... ...
app/views/wikis/_form.html.haml
... ... @@ -21,7 +21,7 @@
21 21  
22 22 .bottom_box_content
23 23 = f.label :content
24   - .input= f.text_area :content, class: 'span8'
  24 + .input= f.text_area :content, class: 'span8 gfm-input'
25 25 .actions
26 26 = f.submit 'Save', class: "save-btn btn"
27 27 = link_to "Cancel", project_wiki_path(@project, :index), class: "btn cancel-btn"
... ...
spec/helpers/notes_helper_spec.rb
... ... @@ -1,10 +0,0 @@
1   -require 'spec_helper'
2   -
3   -describe NotesHelper do
4   - describe "#emoji_for_completion" do
5   - it "should be an Array of Strings" do
6   - emoji_for_completion.should be_a(Array)
7   - emoji_for_completion.each { |emoji| emoji.should be_a(String) }
8   - end
9   - end
10   -end