From 1f5fcb638d6b432d76a639ccc35acc94d8ae6ac7 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Wed, 11 May 2016 19:38:43 -0500 Subject: [PATCH] Dropdown implementation --- CHANGELOG | 2 + .../blob/blob_gitignore_selector.js.coffee | 3 +- app/assets/javascripts/gl_dropdown.js.coffee | 67 +++++++++++++++---- app/assets/stylesheets/pages/editor.scss | 2 +- app/helpers/blob_helper.rb | 8 ++- app/views/projects/blob/_editor.html.haml | 4 +- .../projects/files/gitignore_dropdown_spec.rb | 30 +++++++++ 7 files changed, 96 insertions(+), 20 deletions(-) create mode 100644 spec/features/projects/files/gitignore_dropdown_spec.rb diff --git a/CHANGELOG b/CHANGELOG index 457af51605c..683f1b1a650 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -71,6 +71,8 @@ v 8.7.6 - Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko) - Fix import from GitLab.com to a private instance failure. !4181 - Fix external imports not finding the import data. !4106 + - Fix import from gitlab.com to a private instance failure + - When creating a .gitignore file a dropdown with templates will be provided v 8.7.5 - Fix relative links in wiki pages. !4050 diff --git a/app/assets/javascripts/blob/blob_gitignore_selector.js.coffee b/app/assets/javascripts/blob/blob_gitignore_selector.js.coffee index b413f31da00..2112f5c855a 100644 --- a/app/assets/javascripts/blob/blob_gitignore_selector.js.coffee +++ b/app/assets/javascripts/blob/blob_gitignore_selector.js.coffee @@ -29,7 +29,8 @@ class @BlobGitIgnoreSelector filename = @fileNameInput.val() or $('.editor-file-name').text().trim() @wrapper.toggleClass 'hidden', filename isnt '.gitignore' - onClick: (item) -> + onClick: (item, el, e) -> + e.preventDefault() @requestIgnoreFile(item.text) requestIgnoreFile: (name) -> diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee index 1d1bfeb2e77..0f2ac664ac8 100644 --- a/app/assets/javascripts/gl_dropdown.js.coffee +++ b/app/assets/javascripts/gl_dropdown.js.coffee @@ -60,9 +60,23 @@ class GitLabDropdownFilter results = data if search_text isnt '' - results = fuzzaldrinPlus.filter(data, search_text, - key: @options.keys - ) + # handle groups + if _.isArray(data) + results = fuzzaldrinPlus.filter(data, search_text, + key: @options.keys + ) + else if _.isObject(data) + results = {} + for key, group of data + tmp = fuzzaldrinPlus.filter(group, search_text, + key: @options.keys + ) + + if tmp.length + results[key] = [] + + tmp.map (item) -> + results[key].push item @options.callback results else @@ -141,8 +155,9 @@ class GitLabDropdown searchFields = if @options.search then @options.search.fields else []; if @options.data - # If data is an array - if _.isArray @options.data + # If we provided data + # data could be an array of objects or a group of arrays + if _.isObject(@options.data) and not _.isFunction(@options.data) @fullData = @options.data @parseData @options.data else @@ -230,19 +245,33 @@ class GitLabDropdown parseData: (data) -> @renderedData = data - # Render each row - html = $.map data, (obj) => - return @renderItem(obj) - if @options.filterable and data.length is 0 # render no matching results html = [@noResults()] + else + # Handle array groups + if String(data) is "[object Object]" + html = [] + for name, groupData of data + # Add header for each group + html.push(@renderItem(header: name, name)) + + @renderData(groupData, name) + .map (item) -> + html.push item + else + # Render each row + html = @renderData(data) # Render the full menu full_html = @renderMenu(html.join("")) @appendMenu(full_html) + renderData: (data, group = false) -> + $.map data, (obj, index) => + return @renderItem(obj, group, index) + shouldPropagate: (e) => if @options.multiSelect $target = $(e.target) @@ -299,11 +328,10 @@ class GitLabDropdown selector = '.dropdown-content' if @dropdown.find(".dropdown-toggle-page").length selector = ".dropdown-page-one .dropdown-content" - $(selector, @dropdown).html html # Render the row - renderItem: (data) -> + renderItem: (data, group = false, index = false) -> html = "" # Divider @@ -346,8 +374,13 @@ class GitLabDropdown if @highlight text = @highlightTextMatches(text, @filterInput.val()) + if group + groupAttrs = "data-group='#{group}' data-index='#{index}'" + else + groupAttrs = '' + html = "
  • - + #{text}
  • " @@ -377,9 +410,15 @@ class GitLabDropdown rowClicked: (el) -> fieldName = @options.fieldName - selectedIndex = el.parent().index() if @renderedData - selectedObject = @renderedData[selectedIndex] + groupName = el.data('group') + if groupName + selectedIndex = el.data('index') + selectedObject = @renderedData[groupName][selectedIndex] + else + selectedIndex = el.parent().index() + selectedObject = @renderedData[selectedIndex] + value = if @options.id then @options.id(selectedObject, el) else selectedObject.id field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']") if el.hasClass(ACTIVE_CLASS) diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index 3030da4e6b2..22679c764dc 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -72,7 +72,7 @@ line-height: 21px; } - .dropdown-menu-toggle{ + .dropdown-menu-toggle { vertical-align: top; width: 220px; } diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index fb1b7649465..a3723d2c349 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -186,6 +186,12 @@ module BlobHelper end def gitignores_for_select - @gitignores_for_select ||= Gitlab::Gitignore.all + return @gitignores_for_select if defined?(@gitignores_for_select) + + @gitignores_for_select = { + Global: Gitlab::Gitignore.global.map{ |v| { text: v.name } }, + # Note that the key here doesn't cover it really + Languages: Gitlab::Gitignore.languages_frameworks.map{ |v| { text: v.name } } + } end end diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml index 5efec92cf6b..678eadafe15 100644 --- a/app/views/projects/blob/_editor.html.haml +++ b/app/views/projects/blob/_editor.html.haml @@ -17,9 +17,7 @@ = select_tag :license_type, grouped_options_for_select(licenses_for_select, @project.repository.license_key), include_blank: true, class: 'select2 license-select', data: {placeholder: 'Choose a license template', project: @project.name, fullname: @project.namespace.human_name} .gitignore-selector.hidden - = dropdown_tag("Choose a .gitignore template", options: { toggle_class: 'js-gitignore-selector', title: "Choose a template", filter: true, placeholder: "Filter projects", data: { filenames: Gitlab::Gitignore.all.map.with_index{ |v| {text: v.name} } } } ) - - -# = select_tag :gitignore_template, options_for_select(Gitlab::Gitignore.all.map(&:name)), include_blank: true, class: 'select2 gitignore-select', data: {placeholder: 'Choose a .gitignore template'} + = dropdown_tag("Choose a .gitignore template", options: { toggle_class: 'js-gitignore-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { filenames: gitignores_for_select } } ) .encoding-selector = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2' diff --git a/spec/features/projects/files/gitignore_dropdown_spec.rb b/spec/features/projects/files/gitignore_dropdown_spec.rb new file mode 100644 index 00000000000..073a83b6896 --- /dev/null +++ b/spec/features/projects/files/gitignore_dropdown_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +feature 'User wants to add a .gitignore file', feature: true do + include WaitForAjax + + before do + user = create(:user) + project = create(:project) + project.team << [user, :master] + login_as user + visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: '.gitignore') + end + + scenario 'user can see .gitignore dropdown' do + expect(page).to have_css('.gitignore-selector') + end + + scenario 'user can pick a .gitignore file from the dropdown', js: true do + find('.js-gitignore-selector').click + wait_for_ajax + within '.gitignore-selector' do + find('.dropdown-input-field').set('rails') + find('.dropdown-content li', text: 'Rails').click + end + wait_for_ajax + + expect(page).to have_content('/.bundle') + expect(page).to have_content('# Gemfile.lock, .ruby-version, .ruby-gemset') + end +end