From 2e89eb6a494fa44d254939ea22c20cc557105ee2 Mon Sep 17 00:00:00 2001 From: Winnie Hellmann Date: Tue, 16 May 2017 10:32:53 +0000 Subject: [PATCH] Replace broken autocomplete field for new tags with dropdown --- app/assets/javascripts/dispatcher.js | 2 + app/assets/javascripts/new_branch_form.js | 47 ++----------------- app/assets/javascripts/ref_select_dropdown.js | 46 ++++++++++++++++++ app/views/projects/tags/new.html.haml | 19 ++++---- spec/features/tags/master_creates_tag_spec.rb | 16 ++++++- 5 files changed, 76 insertions(+), 54 deletions(-) create mode 100644 app/assets/javascripts/ref_select_dropdown.js diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 1a791395d6f..22d01c484d3 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -52,6 +52,7 @@ import Pipelines from './pipelines'; import BlobViewer from './blob/viewer/index'; import AutoWidthDropdownSelect from './issuable/auto_width_dropdown_select'; import UsersSelect from './users_select'; +import RefSelectDropdown from './ref_select_dropdown'; const ShortcutsBlob = require('./shortcuts_blob'); @@ -212,6 +213,7 @@ const ShortcutsBlob = require('./shortcuts_blob'); case 'projects:tags:new': new ZenMode(); new gl.GLForm($('.tag-form')); + new RefSelectDropdown($('.js-branch-select'), window.gl.availableRefs); break; case 'projects:releases:edit': new ZenMode(); diff --git a/app/assets/javascripts/new_branch_form.js b/app/assets/javascripts/new_branch_form.js index 9d614cdee3a..39fb302b644 100644 --- a/app/assets/javascripts/new_branch_form.js +++ b/app/assets/javascripts/new_branch_form.js @@ -1,4 +1,6 @@ /* eslint-disable func-names, space-before-function-paren, no-var, one-var, prefer-rest-params, max-len, vars-on-top, wrap-iife, consistent-return, comma-dangle, one-var-declaration-per-line, quotes, no-return-assign, prefer-arrow-callback, prefer-template, no-shadow, no-else-return, max-len, object-shorthand */ +import RefSelectDropdown from '~/ref_select_dropdown'; + (function() { this.NewBranchForm = (function() { function NewBranchForm(form, availableRefs) { @@ -6,7 +8,7 @@ this.branchNameError = form.find('.js-branch-name-error'); this.name = form.find('.js-branch-name'); this.ref = form.find('#ref'); - this.setupAvailableRefs(availableRefs); + new RefSelectDropdown($('.js-branch-select'), availableRefs); // eslint-disable-line no-new this.setupRestrictions(); this.addBinding(); this.init(); @@ -22,49 +24,6 @@ } }; - NewBranchForm.prototype.setupAvailableRefs = function(availableRefs) { - var $branchSelect = $('.js-branch-select'); - - $branchSelect.glDropdown({ - data: availableRefs, - filterable: true, - filterByText: true, - remote: false, - fieldName: $branchSelect.data('field-name'), - filterInput: 'input[type="search"]', - selectable: true, - isSelectable: function(branch, $el) { - return !$el.hasClass('is-active'); - }, - text: function(branch) { - return branch; - }, - id: function(branch) { - return branch; - }, - toggleLabel: function(branch) { - if (branch) { - return branch; - } - } - }); - - const $dropdownContainer = $branchSelect.closest('.dropdown'); - const $fieldInput = $(`input[name="${$branchSelect.data('field-name')}"]`, $dropdownContainer); - const $filterInput = $('input[type="search"]', $dropdownContainer); - - $filterInput.on('keyup', (e) => { - const keyCode = e.keyCode || e.which; - if (keyCode !== 13) return; - - const text = $filterInput.val(); - $fieldInput.val(text); - $('.dropdown-toggle-text', $branchSelect).text(text); - - $dropdownContainer.removeClass('open'); - }); - }; - NewBranchForm.prototype.setupRestrictions = function() { var endsWith, invalid, single, startsWith; startsWith = { diff --git a/app/assets/javascripts/ref_select_dropdown.js b/app/assets/javascripts/ref_select_dropdown.js new file mode 100644 index 00000000000..215cd6fbdfd --- /dev/null +++ b/app/assets/javascripts/ref_select_dropdown.js @@ -0,0 +1,46 @@ +class RefSelectDropdown { + constructor($dropdownButton, availableRefs) { + $dropdownButton.glDropdown({ + data: availableRefs, + filterable: true, + filterByText: true, + remote: false, + fieldName: $dropdownButton.data('field-name'), + filterInput: 'input[type="search"]', + selectable: true, + isSelectable(branch, $el) { + return !$el.hasClass('is-active'); + }, + text(branch) { + return branch; + }, + id(branch) { + return branch; + }, + toggleLabel(branch) { + return branch; + }, + }); + + const $dropdownContainer = $dropdownButton.closest('.dropdown'); + const $fieldInput = $(`input[name="${$dropdownButton.data('field-name')}"]`, $dropdownContainer); + const $filterInput = $('input[type="search"]', $dropdownContainer); + + $filterInput.on('keyup', (e) => { + const keyCode = e.keyCode || e.which; + if (keyCode !== 13) return; + + const ref = $filterInput.val().trim(); + if (ref === '') { + return; + } + + $fieldInput.val(ref); + $('.dropdown-toggle-text', $dropdownButton).text(ref); + + $dropdownContainer.removeClass('open'); + }); + } +} + +export default RefSelectDropdown; diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index cbf841762b7..52af295bddd 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -1,4 +1,5 @@ - page_title "New Tag" +- default_ref = params[:ref] || @project.default_branch - if @error .alert.alert-danger @@ -16,9 +17,13 @@ = text_field_tag :tag_name, params[:tag_name], required: true, tabindex: 1, autofocus: true, class: 'form-control' .form-group = label_tag :ref, 'Create from', class: 'control-label' - .col-sm-10 - = text_field_tag :ref, params[:ref] || @project.default_branch, required: true, tabindex: 2, class: 'form-control' - .help-block Branch name or commit SHA + .col-sm-10.create-from + .dropdown + = hidden_field_tag :ref, default_ref + = button_tag type: 'button', title: default_ref, class: 'dropdown-menu-toggle wide form-control js-branch-select', required: true, data: { toggle: 'dropdown', selected: default_ref, field_name: 'ref' } do + .text-left.dropdown-toggle-text= default_ref + = render 'shared/ref_dropdown', dropdown_class: 'wide' + .help-block Existing branch name, tag, or commit SHA .form-group = label_tag :message, nil, class: 'control-label' .col-sm-10 @@ -37,9 +42,5 @@ = link_to 'Cancel', namespace_project_tags_path(@project.namespace, @project), class: 'btn btn-cancel' :javascript - var availableRefs = #{@project.repository.ref_names.to_json}; - - $("#ref").autocomplete({ - source: availableRefs, - minLength: 1 - }); + window.gl = window.gl || { }; + window.gl.availableRefs = #{@project.repository.ref_names.to_json}; diff --git a/spec/features/tags/master_creates_tag_spec.rb b/spec/features/tags/master_creates_tag_spec.rb index ca25c696f75..af25eebed13 100644 --- a/spec/features/tags/master_creates_tag_spec.rb +++ b/spec/features/tags/master_creates_tag_spec.rb @@ -51,10 +51,24 @@ feature 'Master creates tag', feature: true do end end + scenario 'opens dropdown for ref', js: true do + click_link 'New tag' + ref_row = find('.form-group:nth-of-type(2) .col-sm-10') + page.within ref_row do + ref_input = find('[name="ref"]', visible: false) + expect(ref_input.value).to eq 'master' + expect(find('.dropdown-toggle-text')).to have_content 'master' + + find('.js-branch-select').trigger('click') + + expect(find('.dropdown-menu')).to have_content 'empty-branch' + end + end + def create_tag_in_form(tag:, ref:, message: nil, desc: nil) click_link 'New tag' fill_in 'tag_name', with: tag - fill_in 'ref', with: ref + find('#ref', visible: false).set(ref) fill_in 'message', with: message unless message.nil? fill_in 'release_description', with: desc unless desc.nil? click_button 'Create tag'