Commit a44a5fd4 authored by Jacob Schatz's avatar Jacob Schatz

Merge branch 'template_dropdown' into 'master'

Implements TemplateDropdown class to create custom template dropdowns

## What does this MR do?
Refactorize template dropdowns. This MR creates a base TemplateSelector class so it can be reused for multiple types of templates.

## Does this MR meet the acceptance criteria?

- [ ] [CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added
- [ ] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md)
- [ ] API support added
- [ ] Tests
  - [ ] Added for this feature/bug
  - [x] All builds are passing
- [ ] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides)
- [x] Branch has no merge conflicts with `master` (if you do - rebase it please)
- [x] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)

See merge request !4697
parents 666b5651 e8a467e0
class @BlobGitignoreSelector #= require blob/template_selector
constructor: (opts) ->
{
@dropdown
@editor
@$wrapper = @dropdown.closest('.gitignore-selector')
@$filenameInput = $('#file_name')
@data = @dropdown.data('filenames')
} = opts
@dropdown.glDropdown( class @BlobGitignoreSelector extends TemplateSelector
data: @data, requestFile: (query) ->
filterable: true, Api.gitignoreText query.name, @requestFileSuccess.bind(@)
selectable: true,
search:
fields: ['name']
clicked: @onClick
text: (gitignore) ->
gitignore.name
)
@toggleGitignoreSelector()
@bindEvents()
bindEvents: ->
@$filenameInput
.on 'keyup blur', (e) =>
@toggleGitignoreSelector()
toggleGitignoreSelector: ->
filename = @$filenameInput.val() or $('.editor-file-name').text().trim()
@$wrapper.toggleClass 'hidden', filename isnt '.gitignore'
onClick: (item, el, e) =>
e.preventDefault()
@requestIgnoreFile(item.name)
requestIgnoreFile: (name) ->
Api.gitignoreText name, @requestIgnoreFileSuccess.bind(@)
requestIgnoreFileSuccess: (gitignore) ->
@editor.setValue(gitignore.content, 1)
@editor.focus()
class @BlobGitignoreSelectors
constructor: (opts) ->
{
@$dropdowns = $('.js-gitignore-selector')
@editor
} = opts
@$dropdowns.each (i, dropdown) =>
$dropdown = $(dropdown)
new BlobGitignoreSelector(
dropdown: $dropdown,
editor: @editor
)
class @BlobGitignoreSelectors
constructor: (opts) ->
{
@$dropdowns = $('.js-gitignore-selector')
@editor
} = opts
@$dropdowns.each (i, dropdown) =>
$dropdown = $(dropdown)
new BlobGitignoreSelector(
pattern: /(.gitignore)/,
data: $dropdown.data('data'),
wrapper: $dropdown.closest('.js-gitignore-selector-wrap'),
dropdown: $dropdown,
editor: @editor
)
class @BlobLicenseSelector #= require blob/template_selector
licenseRegex: /^(.+\/)?(licen[sc]e|copying)($|\.)/i
constructor: (editor) -> class @BlobLicenseSelector extends TemplateSelector
@$licenseSelector = $('.js-license-selector') requestFile: (query) ->
$fileNameInput = $('#file_name')
initialFileNameValue = if $fileNameInput.length
$fileNameInput.val()
else if $('.editor-file-name').length
$('.editor-file-name').text().trim()
@toggleLicenseSelector(initialFileNameValue)
if $fileNameInput
$fileNameInput.on 'keyup blur', (e) =>
@toggleLicenseSelector($(e.target).val())
$('select.license-select').on 'change', (e) ->
data = data =
project: $(this).data('project') project: @dropdown.data('project')
fullname: $(this).data('fullname') fullname: @dropdown.data('fullname')
Api.licenseText $(this).val(), data, (license) ->
editor.setValue(license.content, -1)
toggleLicenseSelector: (fileName) => Api.licenseText query.id, data, @requestFileSuccess.bind(@)
if @licenseRegex.test(fileName)
@$licenseSelector.show()
else
@$licenseSelector.hide()
class @BlobLicenseSelectors
constructor: (opts) ->
{
@$dropdowns = $('.js-license-selector')
@editor
} = opts
@$dropdowns.each (i, dropdown) =>
$dropdown = $(dropdown)
new BlobLicenseSelector(
pattern: /^(.+\/)?(licen[sc]e|copying)($|\.)/i,
data: $dropdown.data('data'),
wrapper: $dropdown.closest('.js-license-selector-wrap'),
dropdown: $dropdown,
editor: @editor
)
...@@ -12,8 +12,9 @@ class @EditBlob ...@@ -12,8 +12,9 @@ class @EditBlob
$("#file-content").val(@editor.getValue()) $("#file-content").val(@editor.getValue())
@initModePanesAndLinks() @initModePanesAndLinks()
new BlobLicenseSelector(@editor)
new BlobGitignoreSelectors(editor: @editor) new BlobLicenseSelectors { @editor }
new BlobGitignoreSelectors { @editor }
initModePanesAndLinks: -> initModePanesAndLinks: ->
@$editModePanes = $(".js-edit-mode-pane") @$editModePanes = $(".js-edit-mode-pane")
......
class @TemplateSelector
constructor: (opts = {}) ->
{
@dropdown,
@data,
@pattern,
@wrapper,
@editor,
@fileEndpoint,
@$input = $('#file_name')
} = opts
@buildDropdown()
@bindEvents()
@onFilenameUpdate()
buildDropdown: ->
@dropdown.glDropdown(
data: @data,
filterable: true,
selectable: true,
search:
fields: ['name']
clicked: @onClick
text: (item) ->
item.name
)
bindEvents: ->
@$input.on('keyup blur', (e) =>
@onFilenameUpdate()
)
onFilenameUpdate: ->
return unless @$input.length
filenameMatches = @pattern.test(@$input.val().trim())
if not filenameMatches
@wrapper.addClass('hidden')
return
@wrapper.removeClass('hidden')
onClick: (item, el, e) =>
e.preventDefault()
@requestFile(item)
requestFile: (item) ->
# To be implemented on the extending class
# e.g.
# Api.gitignoreText item.name, @requestFileSuccess.bind(@)
requestFileSuccess: (file) ->
@editor.setValue(file.content, 1)
@editor.focus()
...@@ -66,8 +66,7 @@ ...@@ -66,8 +66,7 @@
font-family: $regular_font; font-family: $regular_font;
} }
.gitignore-selector { .gitignore-selector, .license-selector {
.dropdown { .dropdown {
line-height: 21px; line-height: 21px;
} }
......
...@@ -180,8 +180,8 @@ module BlobHelper ...@@ -180,8 +180,8 @@ module BlobHelper
licenses = Licensee::License.all licenses = Licensee::License.all
@licenses_for_select = { @licenses_for_select = {
Popular: licenses.select(&:featured).map { |license| [license.name, license.key] }, Popular: licenses.select(&:featured).map { |license| { name: license.name, id: license.key } },
Other: licenses.reject(&:featured).map { |license| [license.name, license.key] } Other: licenses.reject(&:featured).map { |license| { name: license.name, id: license.key } }
} }
end end
......
...@@ -13,12 +13,10 @@ ...@@ -13,12 +13,10 @@
required: true, class: 'form-control new-file-name' required: true, class: 'form-control new-file-name'
.pull-right .pull-right
.license-selector.js-license-selector.hide .license-selector.js-license-selector-wrap.hidden
= 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} = dropdown_tag("Choose a License template", options: { toggle_class: 'js-license-selector', title: "Choose a license", filter: true, placeholder: "Filter", data: { data: licenses_for_select, project: @project.name, fullname: @project.namespace.human_name } } )
.gitignore-selector.js-gitignore-selector-wrap.hidden
.gitignore-selector.hidden = dropdown_tag("Choose a .gitignore template", options: { toggle_class: 'js-gitignore-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitignore_names } } )
= dropdown_tag("Choose a .gitignore template", options: { toggle_class: 'js-gitignore-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { filenames: gitignore_names } } )
.encoding-selector .encoding-selector
= select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2' = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2'
......
require 'spec_helper' require 'spec_helper'
feature 'project owner creates a license file', feature: true, js: true do feature 'project owner creates a license file', feature: true, js: true do
include Select2Helper include WaitForAjax
let(:project_master) { create(:user) } let(:project_master) { create(:user) }
let(:project) { create(:project) } let(:project) { create(:project) }
...@@ -21,7 +21,7 @@ feature 'project owner creates a license file', feature: true, js: true do ...@@ -21,7 +21,7 @@ feature 'project owner creates a license file', feature: true, js: true do
expect(page).to have_selector('.license-selector') expect(page).to have_selector('.license-selector')
select2('mit', from: '#license_type') select_template('MIT License')
file_content = find('.file-content') file_content = find('.file-content')
expect(file_content).to have_content('The MIT License (MIT)') expect(file_content).to have_content('The MIT License (MIT)')
...@@ -44,7 +44,7 @@ feature 'project owner creates a license file', feature: true, js: true do ...@@ -44,7 +44,7 @@ feature 'project owner creates a license file', feature: true, js: true do
expect(find('#file_name').value).to eq('LICENSE') expect(find('#file_name').value).to eq('LICENSE')
expect(page).to have_selector('.license-selector') expect(page).to have_selector('.license-selector')
select2('mit', from: '#license_type') select_template('MIT License')
file_content = find('.file-content') file_content = find('.file-content')
expect(file_content).to have_content('The MIT License (MIT)') expect(file_content).to have_content('The MIT License (MIT)')
...@@ -58,4 +58,12 @@ feature 'project owner creates a license file', feature: true, js: true do ...@@ -58,4 +58,12 @@ feature 'project owner creates a license file', feature: true, js: true do
expect(page).to have_content('The MIT License (MIT)') expect(page).to have_content('The MIT License (MIT)')
expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}") expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
end end
def select_template(template)
page.within('.js-license-selector-wrap') do
click_button 'Choose a License template'
click_link template
wait_for_ajax
end
end
end end
require 'spec_helper' require 'spec_helper'
feature 'project owner sees a link to create a license file in empty project', feature: true, js: true do feature 'project owner sees a link to create a license file in empty project', feature: true, js: true do
include Select2Helper include WaitForAjax
let(:project_master) { create(:user) } let(:project_master) { create(:user) }
let(:project) { create(:empty_project) } let(:project) { create(:empty_project) }
...@@ -20,7 +20,7 @@ feature 'project owner sees a link to create a license file in empty project', f ...@@ -20,7 +20,7 @@ feature 'project owner sees a link to create a license file in empty project', f
expect(find('#file_name').value).to eq('LICENSE') expect(find('#file_name').value).to eq('LICENSE')
expect(page).to have_selector('.license-selector') expect(page).to have_selector('.license-selector')
select2('mit', from: '#license_type') select_template('MIT License')
file_content = find('.file-content') file_content = find('.file-content')
expect(file_content).to have_content('The MIT License (MIT)') expect(file_content).to have_content('The MIT License (MIT)')
...@@ -36,4 +36,12 @@ feature 'project owner sees a link to create a license file in empty project', f ...@@ -36,4 +36,12 @@ feature 'project owner sees a link to create a license file in empty project', f
expect(page).to have_content('The MIT License (MIT)') expect(page).to have_content('The MIT License (MIT)')
expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}") expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
end end
def select_template(template)
page.within('.js-license-selector-wrap') do
click_button 'Choose a License template'
click_link template
wait_for_ajax
end
end
end end
...@@ -77,6 +77,7 @@ feature 'Prioritize labels', feature: true do ...@@ -77,6 +77,7 @@ feature 'Prioritize labels', feature: true do
end end
visit current_url visit current_url
wait_for_ajax
page.within('.prioritized-labels') do page.within('.prioritized-labels') do
expect(first('li')).to have_content('wontfix') expect(first('li')).to have_content('wontfix')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment