From deca5ef200a0b6d5d965214ad71d13e359b03e77 Mon Sep 17 00:00:00 2001
From: Phil Hughes <me@iamphill.com>
Date: Tue, 7 Jun 2016 14:40:21 +0100
Subject: [PATCH] Refs dropdown is now loaded async

---
 app/assets/javascripts/gl_dropdown.js.coffee  | 12 ++++---
 app/assets/javascripts/project.js.coffee      | 35 +++++++++++++++++++
 app/assets/stylesheets/framework/selects.scss |  5 ---
 app/assets/stylesheets/pages/projects.scss    |  6 ++++
 app/controllers/projects_controller.rb        | 16 +++++++++
 app/views/shared/_ref_switcher.html.haml      |  9 ++++-
 config/routes.rb                              |  1 +
 7 files changed, 73 insertions(+), 11 deletions(-)

diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee
index 2a8a1f05b35..f8a2db6d42c 100644
--- a/app/assets/javascripts/gl_dropdown.js.coffee
+++ b/app/assets/javascripts/gl_dropdown.js.coffee
@@ -58,7 +58,7 @@ class GitLabDropdownFilter
   filter: (search_text) ->
     data = @options.data()
 
-    if data?
+    if data? and not @options.filterByText
       results = data
 
       if search_text isnt ''
@@ -102,10 +102,11 @@ class GitLabDropdownFilter
           $el = $(@)
           matches = fuzzaldrinPlus.match($el.text().trim(), search_text)
 
-          if matches.length
-            $el.show()
-          else
-            $el.hide()
+          if $el.is(':not(.dropdown-header)')
+            if matches.length
+              $el.show()
+            else
+              $el.hide()
       else
         elements.show()
 
@@ -191,6 +192,7 @@ class GitLabDropdown
     if @options.filterable
       @filter = new GitLabDropdownFilter @filterInput,
         filterInputBlur: @filterInputBlur
+        filterByText: @options.filterByText
         remote: @options.filterRemote
         query: @options.data
         keys: searchFields
diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee
index d12bad97a05..3ef5fcc636c 100644
--- a/app/assets/javascripts/project.js.coffee
+++ b/app/assets/javascripts/project.js.coffee
@@ -19,6 +19,7 @@ class @Project
       $('.clone').text(url)
 
     # Ref switcher
+    @initRefSwitcher()
     $('.project-refs-select').on 'change', ->
       $(@).parents('form').submit()
 
@@ -50,3 +51,37 @@ class @Project
 
   changeProject: (url) ->
     window.location = url
+
+  initRefSwitcher: ->
+    $('.js-project-refs-dropdown').each ->
+      $dropdown = $(@)
+      selected = $dropdown.data('selected')
+
+      $dropdown.glDropdown(
+        data: (term, callback) ->
+          $.ajax(
+            url: $dropdown.data('refs-url')
+          ).done (refs) ->
+            callback(refs)
+        selectable: true
+        filterable: true
+        filterByText: true
+        fieldName: 'ref'
+        renderRow: (ref) ->
+          if ref.header?
+            "<li class='dropdown-header'>#{ref.header}</li>"
+          else
+            isActiveClass = if ref is selected then 'is-active' else ''
+
+            "<li>
+              <a href='#' data-ref='#{ref}' class='#{isActiveClass}'>
+                #{ref}
+              </a>
+            </li>"
+        id: (obj, $el) ->
+          $el.data('ref')
+        toggleLabel: (obj, $el) ->
+          $el.text().trim()
+        clicked: (e) ->
+          $dropdown.closest('form').submit()
+      )
diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss
index f242706ebe4..21d87cc9d34 100644
--- a/app/assets/stylesheets/framework/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -165,11 +165,6 @@
   background-size: 16px 16px !important;
 }
 
-/** Branch/tag selector **/
-.project-refs-form .select2-container {
-  width: 160px !important;
-}
-
 .select2-results .select2-no-results,
 .select2-results .select2-searching,
 .select2-results .select2-ajax-error,
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index f138a2f5387..093d5e18516 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -616,3 +616,9 @@ pre.light-well {
     color: $gl-text-green;
   }
 }
+
+.project-refs-form {
+  .dropdown-menu {
+    width: 300px;
+  }
+}
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 8044c637825..0391d4a2442 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -251,6 +251,22 @@ class ProjectsController < Projects::ApplicationController
     }
   end
 
+  def refs
+    repository = @project.repository
+
+    options = {
+      'Branches' => repository.branch_names,
+      'Tags' => VersionSorter.rsort(repository.tag_names)
+    }
+
+    # If reference is commit id - we should add it to branch/tag selectbox
+    if @ref && !options.flatten.include?(@ref) && @ref =~ /\A[0-9a-zA-Z]{6,52}\z/
+      options << {'Commits' => @ref}
+    end
+
+    render json: options.to_json
+  end
+
   private
 
   def determine_layout
diff --git a/app/views/shared/_ref_switcher.html.haml b/app/views/shared/_ref_switcher.html.haml
index eb2e1919e19..a84e53ea642 100644
--- a/app/views/shared/_ref_switcher.html.haml
+++ b/app/views/shared/_ref_switcher.html.haml
@@ -1,7 +1,14 @@
 = form_tag switch_namespace_project_refs_path(@project.namespace, @project), method: :get, class: "project-refs-form" do
-  = select_tag "ref", grouped_options_refs, class: "project-refs-select select2 select2-sm"
   = hidden_field_tag :destination, destination
   - if defined?(path)
     = hidden_field_tag :path, path
   - @options && @options.each do |key, value|
     = hidden_field_tag key, value, id: nil
+  .dropdown
+    = dropdown_toggle @ref || @project.default_branch, { toggle: "dropdown", selected: @ref || @project.default_branch, refs_url: refs_namespace_project_path(@project.namespace, @project) }, { toggle_class: "js-project-refs-dropdown" }
+    .dropdown-menu.dropdown-menu-selectable
+      = dropdown_title "Switch branch/tag"
+      = dropdown_filter "Search branches and tags"
+      = dropdown_content
+      = dropdown_loading
+    -# = select_tag "ref", grouped_options_refs, class: "project-refs-select select2 select2-sm"
diff --git a/config/routes.rb b/config/routes.rb
index de6094fa0ed..a22559ebabc 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -479,6 +479,7 @@ Rails.application.routes.draw do
         get :download_export
         get :autocomplete_sources
         get :activity
+        get :refs
       end
 
       scope module: :projects do
-- 
GitLab