diff options
Diffstat (limited to 'app/assets/javascripts/gfm_auto_complete.js.coffee')
-rw-r--r-- | app/assets/javascripts/gfm_auto_complete.js.coffee | 185 |
1 files changed, 165 insertions, 20 deletions
diff --git a/app/assets/javascripts/gfm_auto_complete.js.coffee b/app/assets/javascripts/gfm_auto_complete.js.coffee index 4718bcf7a1e..190bb38504c 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.coffee +++ b/app/assets/javascripts/gfm_auto_complete.js.coffee @@ -2,6 +2,9 @@ window.GitLab ?= {} GitLab.GfmAutoComplete = + dataLoading: false + dataLoaded: false + dataSource: '' # Emoji @@ -12,29 +15,97 @@ GitLab.GfmAutoComplete = Members: template: '<li>${username} <small>${title}</small></li>' + Labels: + template: '<li><span class="dropdown-label-box" style="background: ${color}"></span> ${title}</li>' + # Issues and MergeRequests Issues: template: '<li><small>${id}</small> ${title}</li>' + # Milestones + Milestones: + template: '<li>${title}</li>' + + Loading: + template: '<li><i class="fa fa-refresh fa-spin"></i> Loading...</li>' + + DefaultOptions: + sorter: (query, items, searchKey) -> + return items if items[0].name? and items[0].name is 'loading' + + $.fn.atwho.default.callbacks.sorter(query, items, searchKey) + filter: (query, data, searchKey) -> + return data if data[0] is 'loading' + + $.fn.atwho.default.callbacks.filter(query, data, searchKey) + beforeInsert: (value) -> + if not GitLab.GfmAutoComplete.dataLoaded + @at + else + value + # 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 + displayTpl: (value) => + if value.path? + @Emoji.template + else + @Loading.template insertTpl: ':${name}:' + data: ['loading'] + callbacks: + sorter: @DefaultOptions.sorter + filter: @DefaultOptions.filter + beforeInsert: @DefaultOptions.beforeInsert # Team Members - input.atwho + @input.atwho at: '@' - displayTpl: @Members.template + displayTpl: (value) => + if value.username? + @Members.template + else + @Loading.template insertTpl: '${atwho-at}${username}' searchKey: 'search' + data: ['loading'] callbacks: + sorter: @DefaultOptions.sorter + filter: @DefaultOptions.filter + beforeInsert: @DefaultOptions.beforeInsert beforeSave: (members) -> $.map members, (m) -> + return m if not m.username? + title = m.name title += " (#{m.count})" if m.count @@ -42,39 +113,113 @@ GitLab.GfmAutoComplete = title: sanitize(title) search: sanitize("#{m.username} #{m.name}") - input.atwho + @input.atwho at: '#' alias: 'issues' searchKey: 'search' - displayTpl: @Issues.template + displayTpl: (value) => + if value.title? + @Issues.template + else + @Loading.template + data: ['loading'] insertTpl: '${atwho-at}${id}' callbacks: + sorter: @DefaultOptions.sorter + filter: @DefaultOptions.filter + beforeInsert: @DefaultOptions.beforeInsert beforeSave: (issues) -> $.map issues, (i) -> + return i if not i.title? + id: i.iid title: sanitize(i.title) search: "#{i.iid} #{i.title}" - input.atwho + @input.atwho + at: '%' + alias: 'milestones' + searchKey: 'search' + displayTpl: (value) => + if value.title? + @Milestones.template + else + @Loading.template + insertTpl: '${atwho-at}"${title}"' + data: ['loading'] + callbacks: + beforeSave: (milestones) -> + $.map milestones, (m) -> + return m if not m.title? + + id: m.iid + title: sanitize(m.title) + search: "#{m.title}" + + @input.atwho at: '!' alias: 'mergerequests' searchKey: 'search' - displayTpl: @Issues.template + displayTpl: (value) => + if value.title? + @Issues.template + else + @Loading.template + data: ['loading'] insertTpl: '${atwho-at}${id}' callbacks: + sorter: @DefaultOptions.sorter + filter: @DefaultOptions.filter + beforeInsert: @DefaultOptions.beforeInsert beforeSave: (merges) -> $.map merges, (m) -> + return m if not m.title? + id: m.iid 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 + @input.atwho + at: '~' + alias: 'labels' + searchKey: 'search' + displayTpl: @Labels.template + insertTpl: '${atwho-at}${title}' + callbacks: + beforeSave: (merges) -> + sanitizeLabelTitle = (title)-> + if /\w+\s+\w+/g.test(title) + "\"#{sanitize(title)}\"" + else + sanitize(title) + + $.map merges, (m) -> + title: sanitizeLabelTitle(m.title) + color: m.color + search: "#{m.title}" + + destroyAtWho: -> + @input.atwho('destroy') + + fetchData: (dataSource) -> + $.getJSON(dataSource) + + loadData: (data) -> + @dataLoaded = true + + # load members + @input.atwho 'load', '@', data.members + # load issues + @input.atwho 'load', 'issues', data.issues + # load milestones + @input.atwho 'load', 'milestones', data.milestones + # load merge requests + @input.atwho 'load', 'mergerequests', data.mergerequests + # load emojis + @input.atwho 'load', ':', data.emojis + # load labels + @input.atwho 'load', '~', data.labels + + # This trigger at.js again + # otherwise we would be stuck with loading until the user types + $(':focus').trigger('keyup') |