Commit ab96ca2b authored by Alfredo Sumaran's avatar Alfredo Sumaran

Dropdown implementation

parent 79620c50
...@@ -66,13 +66,12 @@ v 8.8.0 (unreleased) ...@@ -66,13 +66,12 @@ v 8.8.0 (unreleased)
- All Grape API helpers are now instrumented - All Grape API helpers are now instrumented
- Improve Issue formatting for the Slack Service (Jeroen van Baarsen) - Improve Issue formatting for the Slack Service (Jeroen van Baarsen)
- Fixed advice on invalid permissions on upload path !2948 (Ludovic Perrine) - Fixed advice on invalid permissions on upload path !2948 (Ludovic Perrine)
- When creating a .gitignore file a dropdown with templates will be provided
v 8.7.6 v 8.7.6
- Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko) - Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko)
- Fix import from GitLab.com to a private instance failure. !4181 - Fix import from GitLab.com to a private instance failure. !4181
- Fix external imports not finding the import data. !4106 - 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 v 8.7.5
- Fix relative links in wiki pages. !4050 - Fix relative links in wiki pages. !4050
......
@Api = @Api =
groups_path: "/api/:version/groups.json" groupsPath: "/api/:version/groups.json"
group_path: "/api/:version/groups/:id.json" groupPath: "/api/:version/groups/:id.json"
namespaces_path: "/api/:version/namespaces.json" namespacesPath: "/api/:version/namespaces.json"
group_projects_path: "/api/:version/groups/:id/projects.json" groupProjectsPath: "/api/:version/groups/:id/projects.json"
projects_path: "/api/:version/projects.json" projectsPath: "/api/:version/projects.json"
labels_path: "/api/:version/projects/:id/labels" labelsPath: "/api/:version/projects/:id/labels"
license_path: "/api/:version/licenses/:key" licensePath: "/api/:version/licenses/:key"
gitignoretext_path: "/api/:version/gitignores/:key" gitignorePath: "/api/:version/gitignores/:key"
group: (group_id, callback) -> group: (group_id, callback) ->
url = Api.buildUrl(Api.group_path) url = Api.buildUrl(Api.groupPath)
url = url.replace(':id', group_id) url = url.replace(':id', group_id)
$.ajax( $.ajax(
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
# Return groups list. Filtered by query # Return groups list. Filtered by query
# Only active groups retrieved # Only active groups retrieved
groups: (query, skip_ldap, callback) -> groups: (query, skip_ldap, callback) ->
url = Api.buildUrl(Api.groups_path) url = Api.buildUrl(Api.groupsPath)
$.ajax( $.ajax(
url: url url: url
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
# Return namespaces list. Filtered by query # Return namespaces list. Filtered by query
namespaces: (query, callback) -> namespaces: (query, callback) ->
url = Api.buildUrl(Api.namespaces_path) url = Api.buildUrl(Api.namespacesPath)
$.ajax( $.ajax(
url: url url: url
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
# Return projects list. Filtered by query # Return projects list. Filtered by query
projects: (query, order, callback) -> projects: (query, order, callback) ->
url = Api.buildUrl(Api.projects_path) url = Api.buildUrl(Api.projectsPath)
$.ajax( $.ajax(
url: url url: url
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
callback(projects) callback(projects)
newLabel: (project_id, data, callback) -> newLabel: (project_id, data, callback) ->
url = Api.buildUrl(Api.labels_path) url = Api.buildUrl(Api.labelsPath)
url = url.replace(':id', project_id) url = url.replace(':id', project_id)
data.private_token = gon.api_token data.private_token = gon.api_token
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
# Return group projects list. Filtered by query # Return group projects list. Filtered by query
groupProjects: (group_id, query, callback) -> groupProjects: (group_id, query, callback) ->
url = Api.buildUrl(Api.group_projects_path) url = Api.buildUrl(Api.groupProjectsPath)
url = url.replace(':id', group_id) url = url.replace(':id', group_id)
$.ajax( $.ajax(
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
# Return text for a specific license # Return text for a specific license
licenseText: (key, data, callback) -> licenseText: (key, data, callback) ->
url = Api.buildUrl(Api.license_path).replace(':key', key) url = Api.buildUrl(Api.licensePath).replace(':key', key)
$.ajax( $.ajax(
url: url url: url
...@@ -104,8 +104,8 @@ ...@@ -104,8 +104,8 @@
).done (license) -> ).done (license) ->
callback(license) callback(license)
gitIgnoreText: (key, callback) -> gitignoreText: (key, callback) ->
url = Api.buildUrl(Api.gitignoretext_path).replace(':key', key) url = Api.buildUrl(Api.gitignorePath).replace(':key', key)
$.get url, (gitignore) -> $.get url, (gitignore) ->
callback(gitignore) callback(gitignore)
......
class @BlobGitIgnoreSelector class @BlobGitignoreSelector
constructor: (opts) -> constructor: (opts) ->
{ {
@dropdown @dropdown
@editor @editor
@wrapper = @dropdown.parents('.gitignore-selector') @$wrapper = @dropdown.closest('.gitignore-selector')
@fileNameInput = $('#file_name') @$filenameInput = $('#file_name')
@data = @dropdown.data('filenames') @data = @dropdown.data('filenames')
} = opts } = opts
...@@ -13,51 +13,46 @@ class @BlobGitIgnoreSelector ...@@ -13,51 +13,46 @@ class @BlobGitIgnoreSelector
filterable: true, filterable: true,
selectable: true, selectable: true,
search: search:
fields: ['text'] fields: ['name']
clicked: @onClick.bind(@) clicked: @onClick
text: (gitignore) ->
gitignore.name
) )
@toggleGitIgnoreSelector() @toggleGitignoreSelector()
@bindEvents() @bindEvents()
bindEvents: -> bindEvents: ->
@fileNameInput @$filenameInput
.on 'keyup blur', (e) => .on 'keyup blur', (e) =>
@toggleGitIgnoreSelector() @toggleGitignoreSelector()
toggleGitIgnoreSelector: -> toggleGitignoreSelector: ->
filename = @fileNameInput.val() or $('.editor-file-name').text().trim() filename = @$filenameInput.val() or $('.editor-file-name').text().trim()
@wrapper.toggleClass 'hidden', filename isnt '.gitignore' @$wrapper.toggleClass 'hidden', filename isnt '.gitignore'
onClick: (item, el, e) -> onClick: (item, el, e) =>
e.preventDefault() e.preventDefault()
@requestIgnoreFile(item.text) @requestIgnoreFile(item.name)
requestIgnoreFile: (name) -> requestIgnoreFile: (name) ->
Api.gitIgnoreText name, @requestIgnoreFileSuccess.bind(@) Api.gitignoreText name, @requestIgnoreFileSuccess.bind(@)
requestIgnoreFileSuccess: (gitignore) -> requestIgnoreFileSuccess: (gitignore) ->
@editor.setValue(gitignore.content, -1) @editor.setValue(gitignore.content, 1)
# Move cursor position to end of file
row = @editor.session.getLength() - 1
column = @editor.session.getLine(row).length
@editor.gotoLine(row + 1, column)
@editor.focus() @editor.focus()
class @BlobGitIgnoreSelectors class @BlobGitignoreSelectors
constructor: (opts) -> constructor: (opts) ->
_this = @
{ {
@dropdowns = $('.js-gitignore-selector') @$dropdowns = $('.js-gitignore-selector')
@editor @editor
} = opts } = opts
@dropdowns.each -> @$dropdowns.each (i, dropdown) =>
$dropdown = $(@) $dropdown = $(dropdown)
new BlobGitIgnoreSelector( new BlobGitignoreSelector(
dropdown: $dropdown, dropdown: $dropdown,
editor: _this.editor editor: @editor
) )
...@@ -13,7 +13,7 @@ class @EditBlob ...@@ -13,7 +13,7 @@ class @EditBlob
@initModePanesAndLinks() @initModePanesAndLinks()
new BlobLicenseSelector(@editor) new BlobLicenseSelector(@editor)
new BlobGitIgnoreSelectors(editor: @editor) new BlobGitignoreSelectors(editor: @editor)
initModePanesAndLinks: -> initModePanesAndLinks: ->
@$editModePanes = $(".js-edit-mode-pane") @$editModePanes = $(".js-edit-mode-pane")
......
...@@ -60,23 +60,36 @@ class GitLabDropdownFilter ...@@ -60,23 +60,36 @@ class GitLabDropdownFilter
results = data results = data
if search_text isnt '' if search_text isnt ''
# handle groups # When data is an array of objects therefore [object Array] e.g.
# [
# { prop: 'foo' },
# { prop: 'baz' }
# ]
if _.isArray(data) if _.isArray(data)
results = fuzzaldrinPlus.filter(data, search_text, results = fuzzaldrinPlus.filter(data, search_text,
key: @options.keys key: @options.keys
) )
else if _.isObject(data) else
results = {} # If data is grouped therefore an [object Object]. e.g.
for key, group of data # {
tmp = fuzzaldrinPlus.filter(group, search_text, # groupName1: [
key: @options.keys # { prop: 'foo' },
) # { prop: 'baz' }
# ],
if tmp.length # groupName2: [
results[key] = [] # { prop: 'abc' },
# { prop: 'def' }
tmp.map (item) -> # ]
results[key].push item # }
if gl.utils.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) -> item
@options.callback results @options.callback results
else else
...@@ -250,7 +263,7 @@ class GitLabDropdown ...@@ -250,7 +263,7 @@ class GitLabDropdown
html = [@noResults()] html = [@noResults()]
else else
# Handle array groups # Handle array groups
if String(data) is "[object Object]" if gl.utils.isObject data
html = [] html = []
for name, groupData of data for name, groupData of data
# Add header for each group # Add header for each group
...@@ -269,7 +282,7 @@ class GitLabDropdown ...@@ -269,7 +282,7 @@ class GitLabDropdown
@appendMenu(full_html) @appendMenu(full_html)
renderData: (data, group = false) -> renderData: (data, group = false) ->
$.map data, (obj, index) => data.map (obj, index) =>
return @renderItem(obj, group, index) return @renderItem(obj, group, index)
shouldPropagate: (e) => shouldPropagate: (e) =>
...@@ -416,7 +429,7 @@ class GitLabDropdown ...@@ -416,7 +429,7 @@ class GitLabDropdown
selectedIndex = el.data('index') selectedIndex = el.data('index')
selectedObject = @renderedData[groupName][selectedIndex] selectedObject = @renderedData[groupName][selectedIndex]
else else
selectedIndex = el.parent().index() selectedIndex = el.closest('li').index()
selectedObject = @renderedData[selectedIndex] selectedObject = @renderedData[selectedIndex]
value = if @options.id then @options.id(selectedObject, el) else selectedObject.id value = if @options.id then @options.id(selectedObject, el) else selectedObject.id
......
((w) ->
w.gl ?= {}
w.gl.utils ?= {}
w.gl.utils.isObject = (obj) ->
obj? and (obj.constructor is Object)
) window
...@@ -185,13 +185,13 @@ module BlobHelper ...@@ -185,13 +185,13 @@ module BlobHelper
} }
end end
def gitignores_for_select def gitignore_names
return @gitignores_for_select if defined?(@gitignores_for_select) return @gitignore_names if defined?(@gitignore_names)
@gitignores_for_select = { @gitignore_names = {
Global: Gitlab::Gitignore.global.map{ |v| { text: v.name } }, Global: Gitlab::Gitignore.global.map { |gitignore| { name: gitignore.name } },
# Note that the key here doesn't cover it really # Note that the key here doesn't cover it really
Languages: Gitlab::Gitignore.languages_frameworks.map{ |v| { text: v.name } } Languages: Gitlab::Gitignore.languages_frameworks.map{ |gitignore| { name: gitignore.name } }
} }
end end
end end
...@@ -245,7 +245,7 @@ class Repository ...@@ -245,7 +245,7 @@ class Repository
def cache_keys def cache_keys
%i(size branch_names tag_names commit_count %i(size branch_names tag_names commit_count
readme version contribution_guide changelog readme version contribution_guide changelog
license_blob license_key) license_blob license_key gitignore)
end end
def build_cache def build_cache
...@@ -256,6 +256,10 @@ class Repository ...@@ -256,6 +256,10 @@ class Repository
end end
end end
def expire_gitignore
cache.expire(:gitignore)
end
def expire_tags_cache def expire_tags_cache
cache.expire(:tag_names) cache.expire(:tag_names)
@tags = nil @tags = nil
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +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} = 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 .gitignore-selector.hidden
= 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 } } ) = 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'
......
...@@ -12,15 +12,15 @@ module API ...@@ -12,15 +12,15 @@ module API
# Get the text for a specific gitignore # Get the text for a specific gitignore
# #
# Parameters: # Parameters:
# key (required) - The key of a license # name (required) - The name of a license
# #
# Example Request: # Example Request:
# GET /gitignores/elixir # GET /gitignores/Elixir
# #
get 'gitignores/:key' do get 'gitignores/:name' do
required_attributes! [:key] required_attributes! [:name]
gitignore = Gitlab::Gitignore.find(params[:key]) gitignore = Gitlab::Gitignore.find(params[:name])
not_found!('.gitignore') unless gitignore not_found!('.gitignore') unless gitignore
present gitignore, with: Entities::Gitignore present gitignore, with: Entities::Gitignore
......
#= require bootstrap #= require bootstrap
#= require select2 #= require select2
#= require lib/type_utility
#= require gl_dropdown #= require gl_dropdown
#= require api #= require api
#= require project_select #= require project_select
......
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