summaryrefslogtreecommitdiff
path: root/app/assets/javascripts
diff options
context:
space:
mode:
authorJames Lopez <james@jameslopez.es>2016-06-16 13:04:00 +0200
committerJames Lopez <james@jameslopez.es>2016-06-16 13:04:00 +0200
commit778d72664f386dfee45dab171f137395739958f6 (patch)
tree7f2c902f4b97ac29aa97e96e877da201130a33b3 /app/assets/javascripts
parent452c076a34cc11cc97f4b1c3113e86ce4367e055 (diff)
parentc369cc8bf42a680b2b0fc9721a9a7926dc5426f6 (diff)
downloadgitlab-ce-feature/project-export.tar.gz
Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into feature/project-exportfeature/project-export
# Conflicts: # app/models/ci/pipeline.rb
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r--app/assets/javascripts/LabelManager.js.coffee7
-rw-r--r--app/assets/javascripts/application.js.coffee35
-rw-r--r--app/assets/javascripts/awards_handler.coffee2
-rw-r--r--app/assets/javascripts/ci/build.coffee9
-rw-r--r--app/assets/javascripts/dispatcher.js.coffee22
-rw-r--r--app/assets/javascripts/due_date_select.js.coffee21
-rw-r--r--app/assets/javascripts/issuable.js.coffee57
-rw-r--r--app/assets/javascripts/issuable_form.js.coffee4
-rw-r--r--app/assets/javascripts/issues-bulk-assignment.js.coffee20
-rw-r--r--app/assets/javascripts/labels_select.js.coffee4
-rw-r--r--app/assets/javascripts/layout_nav.js.coffee39
-rw-r--r--app/assets/javascripts/lib/common_utils.js.coffee41
-rw-r--r--app/assets/javascripts/logo.js.coffee6
-rw-r--r--app/assets/javascripts/merged_buttons.js.coffee30
-rw-r--r--app/assets/javascripts/milestone_select.js.coffee10
-rw-r--r--app/assets/javascripts/network/application.js.coffee20
-rw-r--r--app/assets/javascripts/network/branch-graph.js.coffee (renamed from app/assets/javascripts/branch-graph.js.coffee)0
-rw-r--r--app/assets/javascripts/network/network.js.coffee (renamed from app/assets/javascripts/network.js.coffee)0
-rw-r--r--app/assets/javascripts/notes.js.coffee6
-rw-r--r--app/assets/javascripts/right_sidebar.js.coffee51
-rw-r--r--app/assets/javascripts/search_autocomplete.js.coffee56
-rw-r--r--app/assets/javascripts/shortcuts.js.coffee4
-rw-r--r--app/assets/javascripts/shortcuts_blob.coffee10
-rw-r--r--app/assets/javascripts/sidebar.js.coffee24
-rw-r--r--app/assets/javascripts/star.js.coffee2
-rw-r--r--app/assets/javascripts/users_select.js.coffee6
26 files changed, 363 insertions, 123 deletions
diff --git a/app/assets/javascripts/LabelManager.js.coffee b/app/assets/javascripts/LabelManager.js.coffee
index 365a062bb81..b06bcf0fcbf 100644
--- a/app/assets/javascripts/LabelManager.js.coffee
+++ b/app/assets/javascripts/LabelManager.js.coffee
@@ -42,10 +42,10 @@ class @LabelManager
$from = @prioritizedLabels
if $from.find('li').length is 1
- $from.find('.empty-message').show()
+ $from.find('.empty-message').removeClass('hidden')
if not $target.find('li').length
- $target.find('.empty-message').hide()
+ $target.find('.empty-message').addClass('hidden')
$label.detach().appendTo($target)
@@ -54,6 +54,9 @@ class @LabelManager
if action is 'remove'
xhr = $.ajax url: url, type: 'DELETE'
+
+ # Restore empty message
+ $from.find('.empty-message').removeClass('hidden') unless $from.find('li').length
else
xhr = @savePrioritySort($label, action)
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee
index 69d4c4f5dd3..2f9f6c3ef5b 100644
--- a/app/assets/javascripts/application.js.coffee
+++ b/app/assets/javascripts/application.js.coffee
@@ -32,10 +32,6 @@
#= require bootstrap/tooltip
#= require bootstrap/popover
#= require select2
-#= require raphael
-#= require g.raphael
-#= require g.bar
-#= require branch-graph
#= require ace/ace
#= require ace/ext-searchbox
#= require underscore
@@ -125,9 +121,10 @@ window.onload = ->
setTimeout shiftWindow, 100
$ ->
+ gl.utils.preventDisabledButtons()
bootstrapBreakpoint = bp.getBreakpointSize()
- $(".nicescroll").niceScroll(cursoropacitymax: '0.4', cursorcolor: '#FFF', cursorborder: "1px solid #FFF")
+ $(".nav-sidebar").niceScroll(cursoropacitymax: '0.4', cursorcolor: '#FFF', cursorborder: "1px solid #FFF")
# Click a .js-select-on-focus field, select the contents
$(".js-select-on-focus").on "focusin", ->
@@ -257,3 +254,31 @@ $ ->
gl.awardsHandler = new AwardsHandler()
checkInitialSidebarSize()
new Aside()
+
+ # Sidenav pinning
+ if $(window).width() < 1440 and $.cookie('pin_nav') is 'true'
+ $.cookie('pin_nav', 'false')
+ $('.page-with-sidebar')
+ .toggleClass('page-sidebar-collapsed page-sidebar-expanded')
+ .removeClass('page-sidebar-pinned')
+ $('.navbar-fixed-top').removeClass('header-pinned-nav')
+
+ $(document)
+ .off 'click', '.js-nav-pin'
+ .on 'click', '.js-nav-pin', (e) ->
+ e.preventDefault()
+
+ $(this).toggleClass 'is-active'
+
+ if $.cookie('pin_nav') is 'true'
+ $.cookie 'pin_nav', 'false'
+ $('.page-with-sidebar')
+ .removeClass('page-sidebar-pinned')
+ .toggleClass('page-sidebar-collapsed page-sidebar-expanded')
+ $('.navbar-fixed-top')
+ .removeClass('header-pinned-nav')
+ .toggleClass('header-collapsed header-expanded')
+ else
+ $.cookie 'pin_nav', 'true'
+ $('.page-with-sidebar').addClass('page-sidebar-pinned')
+ $('.navbar-fixed-top').addClass('header-pinned-nav')
diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee
index 136db8ee14d..030f1564862 100644
--- a/app/assets/javascripts/awards_handler.coffee
+++ b/app/assets/javascripts/awards_handler.coffee
@@ -40,7 +40,7 @@ class @AwardsHandler
$menu = $ '.emoji-menu'
if $addBtn.hasClass 'js-note-emoji'
- $addBtn.parents('.note').find('.js-awards-block').addClass 'current'
+ $addBtn.closest('.note').find('.js-awards-block').addClass 'current'
else
$addBtn.closest('.js-awards-block').addClass 'current'
diff --git a/app/assets/javascripts/ci/build.coffee b/app/assets/javascripts/ci/build.coffee
index f763ba96e33..2d515d7efa2 100644
--- a/app/assets/javascripts/ci/build.coffee
+++ b/app/assets/javascripts/ci/build.coffee
@@ -17,6 +17,8 @@ class @CiBuild
.off 'resize.build'
.on 'resize.build', @hideSidebar
+ @updateArtifactRemoveDate()
+
if $('#build-trace').length
@getInitialBuildTrace()
@initScrollButtonAffix()
@@ -103,3 +105,10 @@ class @CiBuild
$('.js-build-sidebar')
.removeClass 'right-sidebar-collapsed'
.addClass 'right-sidebar-expanded'
+
+ updateArtifactRemoveDate: ->
+ $date = $('.js-artifacts-remove')
+
+ if $date.length
+ date = $date.text()
+ $date.text $.timefor(new Date(date), ' ')
diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee
index 29ac0f70b30..b560500cce6 100644
--- a/app/assets/javascripts/dispatcher.js.coffee
+++ b/app/assets/javascripts/dispatcher.js.coffee
@@ -29,6 +29,7 @@ class Dispatcher
new Todos()
when 'projects:milestones:new', 'projects:milestones:edit'
new ZenMode()
+ new DueDateSelect()
new GLForm($('.milestone-form'))
when 'groups:milestones:new'
new ZenMode()
@@ -53,9 +54,13 @@ class Dispatcher
new Diff()
shortcut_handler = new ShortcutsIssuable(true)
new ZenMode()
+ new MergedButtons()
+ when 'projects:merge_requests:commits', 'projects:merge_requests:builds'
+ new MergedButtons()
when "projects:merge_requests:diffs"
new Diff()
new ZenMode()
+ new MergedButtons()
when 'projects:merge_requests:index'
shortcut_handler = new ShortcutsNavigation()
Issuable.init()
@@ -68,9 +73,7 @@ class Dispatcher
new Diff()
new ZenMode()
shortcut_handler = new ShortcutsNavigation()
- when 'projects:commits:show'
- shortcut_handler = new ShortcutsNavigation()
- when 'projects:activity'
+ when 'projects:commits:show', 'projects:activity'
shortcut_handler = new ShortcutsNavigation()
when 'projects:show'
shortcut_handler = new ShortcutsNavigation()
@@ -96,6 +99,7 @@ class Dispatcher
when 'projects:blob:show', 'projects:blame:show'
new LineHighlighter()
shortcut_handler = new ShortcutsNavigation()
+ new ShortcutsBlob true
when 'projects:labels:new', 'projects:labels:edit'
new Labels()
when 'projects:labels:index'
@@ -129,15 +133,11 @@ class Dispatcher
new Project()
new ProjectAvatar()
switch path[1]
- when 'compare'
- shortcut_handler = new ShortcutsNavigation()
when 'edit'
shortcut_handler = new ShortcutsNavigation()
new ProjectNew()
- when 'new'
+ when 'new', 'show'
new ProjectNew()
- when 'show'
- new ProjectShow()
when 'wikis'
new Wikis()
shortcut_handler = new ShortcutsNavigation()
@@ -146,9 +146,9 @@ class Dispatcher
when 'snippets'
shortcut_handler = new ShortcutsNavigation()
new ZenMode() if path[2] == 'show'
- when 'labels', 'graphs'
- shortcut_handler = new ShortcutsNavigation()
- when 'project_members', 'deploy_keys', 'hooks', 'services', 'protected_branches'
+ when 'labels', 'graphs', 'compare', 'pipelines', 'forks', \
+ 'milestones', 'project_members', 'deploy_keys', 'builds', \
+ 'hooks', 'services', 'protected_branches'
shortcut_handler = new ShortcutsNavigation()
# If we haven't installed a custom shortcut handler, install the default one
diff --git a/app/assets/javascripts/due_date_select.js.coffee b/app/assets/javascripts/due_date_select.js.coffee
index 3d009a96d05..d65c018dad5 100644
--- a/app/assets/javascripts/due_date_select.js.coffee
+++ b/app/assets/javascripts/due_date_select.js.coffee
@@ -1,5 +1,21 @@
class @DueDateSelect
constructor: ->
+ # Milestone edit/new form
+ $datePicker = $('.datepicker')
+
+ if $datePicker.length
+ $dueDate = $('#milestone_due_date')
+ $datePicker.datepicker
+ dateFormat: 'yy-mm-dd'
+ onSelect: (dateText, inst) ->
+ $dueDate.val(dateText)
+ .datepicker('setDate', $.datepicker.parseDate('yy-mm-dd', $dueDate.val()))
+
+ $('.js-clear-due-date').on 'click', (e) ->
+ e.preventDefault()
+ $.datepicker._clearDate($datePicker)
+
+ # Issuable sidebar
$loading = $('.js-issuable-update .due_date')
.find('.block-loading')
.hide()
@@ -32,7 +48,7 @@ class @DueDateSelect
date = new Date value.replace(new RegExp('-', 'g'), ',')
mediumDate = $.datepicker.formatDate 'M d, yy', date
else
- mediumDate = 'None'
+ mediumDate = 'No due date'
data = {}
data[abilityName] = {}
@@ -50,7 +66,8 @@ class @DueDateSelect
$selectbox.hide()
$value.css('display', '')
- $valueContent.html(mediumDate)
+ cssClass = if Date.parse(mediumDate) then 'bold' else 'no-value'
+ $valueContent.html("<span class='#{cssClass}'>#{mediumDate}</span>")
$sidebarValue.html(mediumDate)
if value isnt ''
diff --git a/app/assets/javascripts/issuable.js.coffee b/app/assets/javascripts/issuable.js.coffee
index c2447120033..d0901be1509 100644
--- a/app/assets/javascripts/issuable.js.coffee
+++ b/app/assets/javascripts/issuable.js.coffee
@@ -56,13 +56,6 @@ issuable_created = false
Issuable.filterResults $('.filter-form')
$('.js-label-select').trigger('update.label')
- toggleLabelFilters: ->
- $filteredLabels = $('.filtered-labels')
- if $filteredLabels.find('.label-row').length > 0
- $filteredLabels.removeClass('hidden')
- else
- $filteredLabels.addClass('hidden')
-
filterResults: (form) =>
formData = form.serialize()
@@ -71,58 +64,16 @@ issuable_created = false
issuesUrl = formAction
issuesUrl += ("#{if formAction.indexOf('?') < 0 then '?' else '&'}")
issuesUrl += formData
- $.ajax
- type: 'GET'
- url: formAction
- data: formData
- complete: ->
- $('.issues-holder, .merge-requests-holder').css('opacity', '1.0')
- success: (data) ->
- $('.issues-holder, .merge-requests-holder').html(data.html)
- # Change url so if user reload a page - search results are saved
- history.replaceState {page: issuesUrl}, document.title, issuesUrl
- Issuable.reload()
- Issuable.updateStateFilters()
- $filteredLabels = $('.filtered-labels')
-
- if typeof Issuable.labelRow is 'function'
- $filteredLabels.html(Issuable.labelRow(data))
- Issuable.toggleLabelFilters()
-
- dataType: "json"
-
- reload: ->
- if Issuable.created
- Issuable.initChecks()
-
- $('#filter_issue_search').val($('#issue_search').val())
+ Turbolinks.visit(issuesUrl);
initChecks: ->
- $('.check_all_issues').on 'click', ->
+ $('.check_all_issues').off('click').on('click', ->
$('.selected_issue').prop('checked', @checked)
Issuable.checkChanged()
+ )
- $('.selected_issue').on 'change', Issuable.checkChanged
-
- updateStateFilters: ->
- stateFilters = $('.issues-state-filters, .dropdown-menu-sort')
- newParams = {}
- paramKeys = ['author_id', 'milestone_title', 'assignee_id', 'issue_search', 'issue_search']
-
- for paramKey in paramKeys
- newParams[paramKey] = gl.utils.getParameterValues(paramKey)[0] or ''
-
- if stateFilters.length
- stateFilters.find('a').each ->
- initialUrl = gl.utils.removeParamQueryString($(this).attr('href'), 'label_name[]')
- labelNameValues = gl.utils.getParameterValues('label_name[]')
- if labelNameValues
- labelNameQueryString = ("label_name[]=#{value}" for value in labelNameValues).join('&')
- newUrl = "#{gl.utils.mergeUrlParams(newParams, initialUrl)}&#{labelNameQueryString}"
- else
- newUrl = gl.utils.mergeUrlParams(newParams, initialUrl)
- $(this).attr 'href', newUrl
+ $('.selected_issue').off('change').on('change', Issuable.checkChanged)
checkChanged: ->
checked_issues = $('.selected_issue:checked')
diff --git a/app/assets/javascripts/issuable_form.js.coffee b/app/assets/javascripts/issuable_form.js.coffee
index 898506fde32..5b7a4831dfc 100644
--- a/app/assets/javascripts/issuable_form.js.coffee
+++ b/app/assets/javascripts/issuable_form.js.coffee
@@ -102,6 +102,10 @@ class @IssuableForm
return {
results: data
}
+ data: (query) ->
+ {
+ search: query
+ }
formatResult: (project) ->
project.name_with_namespace
formatSelection: (project) ->
diff --git a/app/assets/javascripts/issues-bulk-assignment.js.coffee b/app/assets/javascripts/issues-bulk-assignment.js.coffee
index 16d023dd391..b454f9389dd 100644
--- a/app/assets/javascripts/issues-bulk-assignment.js.coffee
+++ b/app/assets/javascripts/issues-bulk-assignment.js.coffee
@@ -9,6 +9,9 @@ class @IssuableBulkActions
@bindEvents()
+ # Fixes bulk-assign not working when navigating through pages
+ Issuable.initChecks();
+
getElement: (selector) ->
@container.find selector
@@ -97,13 +100,22 @@ class @IssuableBulkActions
$labels = @form.find('.labels-filter input[name="update[label_ids][]"]')
$labels.each (k, label) ->
- labelIds.push $(label).val() if label
+ labelIds.push parseInt($(label).val()) if label
labelIds
###*
- * Just an alias of @getUnmarkedIndeterminedLabels
- * @return {Array} Array of labels
+ * Returns Label IDs that will be removed from issue selection
+ * @return {Array} Array of labels IDs
###
getLabelsToRemove: ->
- @getUnmarkedIndeterminedLabels()
+ result = []
+ indeterminatedLabels = @getUnmarkedIndeterminedLabels()
+ labelsToApply = @getLabelsToApply()
+
+ indeterminatedLabels.map (id) ->
+ # We need to exclude label IDs that will be applied
+ # By not doing this will cause issues from selection to not add labels at all
+ result.push(id) if labelsToApply.indexOf(id) is -1
+
+ result
diff --git a/app/assets/javascripts/labels_select.js.coffee b/app/assets/javascripts/labels_select.js.coffee
index 9ca88f1226e..d350a7c0e7f 100644
--- a/app/assets/javascripts/labels_select.js.coffee
+++ b/app/assets/javascripts/labels_select.js.coffee
@@ -39,7 +39,7 @@ class @LabelsSelect
</a>
<% }); %>'
)
- labelNoneHTMLTemplate = _.template('<div class="light">None</div>')
+ labelNoneHTMLTemplate = '<span class="no-value">None</span>'
if newLabelField.length
@@ -145,7 +145,7 @@ class @LabelsSelect
template = labelHTMLTemplate(data)
labelCount = data.labels.length
else
- template = labelNoneHTMLTemplate()
+ template = labelNoneHTMLTemplate
$value
.removeAttr('style')
.html(template)
diff --git a/app/assets/javascripts/layout_nav.js.coffee b/app/assets/javascripts/layout_nav.js.coffee
index 6adac6dac97..f8f0aea427e 100644
--- a/app/assets/javascripts/layout_nav.js.coffee
+++ b/app/assets/javascripts/layout_nav.js.coffee
@@ -1,14 +1,25 @@
-class @LayoutNav
- $ ->
- $('.fade-left').addClass('end-scroll')
- $('.scrolling-tabs').on 'scroll', (event) ->
- $this = $(this)
- $el = $(event.target)
- currentPosition = $this.scrollLeft()
- size = bp.getBreakpointSize()
- controlBtnWidth = $('.controls').width()
- maxPosition = $this.get(0).scrollWidth - $this.parent().width()
- maxPosition += controlBtnWidth if size isnt 'xs' and $('.nav-control').length
-
- $el.find('.fade-left').toggleClass('end-scroll', currentPosition is 0)
- $el.find('.fade-right').toggleClass('end-scroll', currentPosition is maxPosition)
+hideEndFade = ($scrollingTabs) ->
+ $scrollingTabs.each ->
+ $this = $(@)
+
+ $this
+ .find('.fade-right')
+ .toggleClass('end-scroll', $this.width() is $this.prop('scrollWidth'))
+
+$ ->
+ $('.fade-left').addClass('end-scroll')
+
+ hideEndFade($('.scrolling-tabs'))
+
+ $(window)
+ .off 'resize.nav'
+ .on 'resize.nav', ->
+ hideEndFade($('.scrolling-tabs'))
+
+ $('.scrolling-tabs').on 'scroll', (event) ->
+ $this = $(this)
+ currentPosition = $this.scrollLeft()
+ maxPosition = $this.prop('scrollWidth') - $this.outerWidth()
+
+ $this.find('.fade-left').toggleClass('end-scroll', currentPosition is 0)
+ $this.find('.fade-right').toggleClass('end-scroll', currentPosition is maxPosition)
diff --git a/app/assets/javascripts/lib/common_utils.js.coffee b/app/assets/javascripts/lib/common_utils.js.coffee
index 0000e99a650..e39dcb2daa9 100644
--- a/app/assets/javascripts/lib/common_utils.js.coffee
+++ b/app/assets/javascripts/lib/common_utils.js.coffee
@@ -1,5 +1,46 @@
((w) ->
+ w.gl or= {}
+ w.gl.utils or= {}
+
+ w.gl.utils.isInGroupsPage = ->
+
+ return $('body').data('page').split(':')[0] is 'groups'
+
+
+ w.gl.utils.isInProjectPage = ->
+
+ return $('body').data('page').split(':')[0] is 'projects'
+
+
+ w.gl.utils.getProjectSlug = ->
+
+ return if @isInProjectPage() then $('body').data 'project' else null
+
+
+ w.gl.utils.getGroupSlug = ->
+
+ return if @isInGroupsPage() then $('body').data 'group' else null
+
+
+
+ gl.utils.updateTooltipTitle = ($tooltipEl, newTitle) ->
+
+ $tooltipEl
+ .tooltip 'destroy'
+ .attr 'title', newTitle
+ .tooltip 'fixTitle'
+
+
+ gl.utils.preventDisabledButtons = ->
+
+ $('.btn').click (e) ->
+ if $(this).hasClass 'disabled'
+ e.preventDefault()
+ e.stopImmediatePropagation()
+ return false
+
+
jQuery.timefor = (time, suffix, expiredLabel) ->
return '' unless time
diff --git a/app/assets/javascripts/logo.js.coffee b/app/assets/javascripts/logo.js.coffee
index 9fdc27a9787..dc2590a0355 100644
--- a/app/assets/javascripts/logo.js.coffee
+++ b/app/assets/javascripts/logo.js.coffee
@@ -42,9 +42,3 @@ work = ->
$(document).on('page:fetch', start)
$(document).on('page:change', stop)
-
-$ ->
- # Make logo clickable as part of a workaround for Safari visited
- # link behaviour (See !2690).
- $('#logo').on 'click', ->
- Turbolinks.visit('/')
diff --git a/app/assets/javascripts/merged_buttons.js.coffee b/app/assets/javascripts/merged_buttons.js.coffee
new file mode 100644
index 00000000000..4929295c10b
--- /dev/null
+++ b/app/assets/javascripts/merged_buttons.js.coffee
@@ -0,0 +1,30 @@
+class @MergedButtons
+ constructor: ->
+ @$removeBranchWidget = $('.remove_source_branch_widget')
+ @$removeBranchProgress = $('.remove_source_branch_in_progress')
+ @$removeBranchFailed = $('.remove_source_branch_widget.failed')
+
+ @cleanEventListeners()
+ @initEventListeners()
+
+ cleanEventListeners: ->
+ $(document).off 'click', '.remove_source_branch'
+ $(document).off 'ajax:success', '.remove_source_branch'
+ $(document).off 'ajax:error', '.remove_source_branch'
+
+ initEventListeners: ->
+ $(document).on 'click', '.remove_source_branch', @removeSourceBranch
+ $(document).on 'ajax:success', '.remove_source_branch', @removeBranchSuccess
+ $(document).on 'ajax:error', '.remove_source_branch', @removeBranchError
+
+ removeSourceBranch: =>
+ @$removeBranchWidget.hide()
+ @$removeBranchProgress.show()
+
+ removeBranchSuccess: ->
+ location.reload()
+
+ removeBranchError: ->
+ @$removeBranchWidget.hide()
+ @$removeBranchProgress.hide()
+ @$removeBranchFailed.show()
diff --git a/app/assets/javascripts/milestone_select.js.coffee b/app/assets/javascripts/milestone_select.js.coffee
index 648e1f3bde0..02480f3a025 100644
--- a/app/assets/javascripts/milestone_select.js.coffee
+++ b/app/assets/javascripts/milestone_select.js.coffee
@@ -24,14 +24,10 @@ class @MilestoneSelect
if issueUpdateURL
milestoneLinkTemplate = _.template(
- '<a href="/<%= namespace %>/<%= path %>/milestones/<%= iid %>">
- <span class="has-tooltip" data-container="body" title="<%= remaining %>">
- <%= _.escape(title) %>
- </span>
- </a>'
+ '<a href="/<%= namespace %>/<%= path %>/milestones/<%= iid %>" class="bold has-tooltip" data-container="body" title="<%= remaining %>"><%= _.escape(title) %></a>'
)
- milestoneLinkNoneTemplate = '<div class="light">None</div>'
+ milestoneLinkNoneTemplate = '<span class="no-value">None</span>'
collapsedSidebarLabelTemplate = _.template(
'<span class="has-tooltip" data-container="body" title="<%= remaining %>" data-placement="left">
@@ -116,7 +112,7 @@ class @MilestoneSelect
.val()
data = {}
data[abilityName] = {}
- data[abilityName].milestone_id = selected
+ data[abilityName].milestone_id = if selected? then selected else null
$loading
.fadeIn()
$dropdown.trigger('loading.gl.dropdown')
diff --git a/app/assets/javascripts/network/application.js.coffee b/app/assets/javascripts/network/application.js.coffee
new file mode 100644
index 00000000000..cb9eead855b
--- /dev/null
+++ b/app/assets/javascripts/network/application.js.coffee
@@ -0,0 +1,20 @@
+# This is a manifest file that'll be compiled into including all the files listed below.
+# Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
+# be included in the compiled file accessible from http://example.com/assets/application.js
+# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+# the compiled file.
+#
+#= require raphael
+#= require g.raphael
+#= require g.bar
+#= require_tree .
+
+$ ->
+ network_graph = new Network({
+ url: $(".network-graph").attr('data-url'),
+ commit_url: $(".network-graph").attr('data-commit-url'),
+ ref: $(".network-graph").attr('data-ref'),
+ commit_id: $(".network-graph").attr('data-commit-id')
+ })
+
+ new ShortcutsNetwork(network_graph.branch_graph)
diff --git a/app/assets/javascripts/branch-graph.js.coffee b/app/assets/javascripts/network/branch-graph.js.coffee
index f2fd2a775a4..f2fd2a775a4 100644
--- a/app/assets/javascripts/branch-graph.js.coffee
+++ b/app/assets/javascripts/network/branch-graph.js.coffee
diff --git a/app/assets/javascripts/network.js.coffee b/app/assets/javascripts/network/network.js.coffee
index f4ef07a50a7..f4ef07a50a7 100644
--- a/app/assets/javascripts/network.js.coffee
+++ b/app/assets/javascripts/network/network.js.coffee
diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee
index ad216910c8d..e2d3241437b 100644
--- a/app/assets/javascripts/notes.js.coffee
+++ b/app/assets/javascripts/notes.js.coffee
@@ -115,12 +115,14 @@ class @Notes
, @pollingInterval
refresh: =>
- return if @refreshing is true
- @refreshing = true
if not document.hidden and document.URL.indexOf(@noteable_url) is 0
@getContent()
getContent: ->
+ return if @refreshing
+
+ @refreshing = true
+
$.ajax
url: @notes_url
data: "last_fetched_at=" + @last_fetched_at
diff --git a/app/assets/javascripts/right_sidebar.js.coffee b/app/assets/javascripts/right_sidebar.js.coffee
index c9cb0f4bb32..8eb005b0a22 100644
--- a/app/assets/javascripts/right_sidebar.js.coffee
+++ b/app/assets/javascripts/right_sidebar.js.coffee
@@ -43,6 +43,55 @@ class @Sidebar
$('.right-sidebar')
.hasClass('right-sidebar-collapsed'), { path: '/' })
+ $(document)
+ .off 'click', '.js-issuable-todo'
+ .on 'click', '.js-issuable-todo', @toggleTodo
+
+ toggleTodo: (e) =>
+ $this = $(e.currentTarget)
+ $todoLoading = $('.js-issuable-todo-loading')
+ $btnText = $('.js-issuable-todo-text', $this)
+ ajaxType = if $this.attr('data-id') then 'PATCH' else 'POST'
+ ajaxUrlExtra = if $this.attr('data-id') then "/#{$this.attr('data-id')}" else ''
+
+ $.ajax(
+ url: "#{$this.data('url')}#{ajaxUrlExtra}"
+ type: ajaxType
+ dataType: 'json'
+ data:
+ issuable_id: $this.data('issuable')
+ issuable_type: $this.data('issuable-type')
+ beforeSend: =>
+ @beforeTodoSend($this, $todoLoading)
+ ).done (data) =>
+ @todoUpdateDone(data, $this, $btnText, $todoLoading)
+
+ beforeTodoSend: ($btn, $todoLoading) ->
+ $btn.disable()
+ $todoLoading.removeClass 'hidden'
+
+ todoUpdateDone: (data, $btn, $btnText, $todoLoading) ->
+ $todoPendingCount = $('.todos-pending-count')
+ $todoPendingCount.text data.count
+
+ $btn.enable()
+ $todoLoading.addClass 'hidden'
+
+ if data.count is 0
+ $todoPendingCount.addClass 'hidden'
+ else
+ $todoPendingCount.removeClass 'hidden'
+
+ if data.todo?
+ $btn
+ .attr 'aria-label', $btn.data('mark-text')
+ .attr 'data-id', data.todo.id
+ $btnText.text $btn.data('mark-text')
+ else
+ $btn
+ .attr 'aria-label', $btn.data('todo-text')
+ .removeAttr 'data-id'
+ $btnText.text $btn.data('todo-text')
sidebarDropdownLoading: (e) ->
$sidebarCollapsedIcon = $(@).closest('.block').find('.sidebar-collapsed-icon')
@@ -117,5 +166,3 @@ class @Sidebar
getBlock: (name) ->
@sidebar.find(".block.#{name}")
-
-
diff --git a/app/assets/javascripts/search_autocomplete.js.coffee b/app/assets/javascripts/search_autocomplete.js.coffee
index 5eb915a51ea..421328554b8 100644
--- a/app/assets/javascripts/search_autocomplete.js.coffee
+++ b/app/assets/javascripts/search_autocomplete.js.coffee
@@ -67,8 +67,12 @@ class @SearchAutocomplete
getData: (term, callback) ->
_this = @
- # Do not trigger request if input is empty
- return if @searchInput.val() is ''
+ unless term
+ if contents = @getCategoryContents()
+ @searchInput.data('glDropdown').filter.options.callback contents
+ @enableAutocomplete()
+
+ return
# Prevent multiple ajax calls
return if @loadingSuggestions
@@ -122,6 +126,37 @@ class @SearchAutocomplete
).always ->
_this.loadingSuggestions = false
+
+ getCategoryContents: ->
+
+ userId = gon.current_user_id
+ { utils, projectOptions, groupOptions, dashboardOptions } = gl
+
+ if utils.isInGroupsPage() and groupOptions
+ options = groupOptions[utils.getGroupSlug()]
+
+ else if utils.isInProjectPage() and projectOptions
+ options = projectOptions[utils.getProjectSlug()]
+
+ else if dashboardOptions
+ options = dashboardOptions
+
+ { issuesPath, mrPath, name } = options
+
+ items = [
+ { header: "#{name}" }
+ { text: 'Issues assigned to me', url: "#{issuesPath}/?assignee_id=#{userId}" }
+ { text: "Issues I've created", url: "#{issuesPath}/?author_id=#{userId}" }
+ 'separator'
+ { text: 'Merge requests assigned to me', url: "#{mrPath}/?assignee_id=#{userId}" }
+ { text: "Merge requests I've created", url: "#{mrPath}/?author_id=#{userId}" }
+ ]
+
+ items.splice 0, 1 unless name
+
+ return items
+
+
serializeState: ->
{
# Search Criteria
@@ -209,6 +244,12 @@ class @SearchAutocomplete
@isFocused = true
@wrap.addClass('search-active')
+ @getData() if @getValue() is ''
+
+
+ getValue: -> return @searchInput.val()
+
+
onClearInputClick: (e) =>
e.preventDefault()
@searchInput.val('').focus()
@@ -229,6 +270,10 @@ class @SearchAutocomplete
@locationBadgeEl.text(badgeText).show()
@wrap.addClass('has-location-badge')
+
+ hasLocationBadge: -> return @wrap.is '.has-location-badge'
+
+
restoreOriginalState: ->
inputs = Object.keys @originalState
@@ -257,13 +302,14 @@ class @SearchAutocomplete
@getElement("##{input}").val('')
+
removeLocationBadge: ->
- @locationBadgeEl.hide()
- # Reset state
+ @locationBadgeEl.hide()
@resetSearchState()
-
@wrap.removeClass('has-location-badge')
+ @disableAutocomplete()
+
disableAutocomplete: ->
@searchInput.addClass('disabled')
diff --git a/app/assets/javascripts/shortcuts.js.coffee b/app/assets/javascripts/shortcuts.js.coffee
index f3d66004138..c03877e9b06 100644
--- a/app/assets/javascripts/shortcuts.js.coffee
+++ b/app/assets/javascripts/shortcuts.js.coffee
@@ -1,7 +1,7 @@
class @Shortcuts
- constructor: ->
+ constructor: (skipResetBindings) ->
@enabledHelp = []
- Mousetrap.reset()
+ Mousetrap.reset() if not skipResetBindings
Mousetrap.bind('?', @onToggleHelp)
Mousetrap.bind('s', Shortcuts.focusSearch)
Mousetrap.bind(['ctrl+shift+p', 'command+shift+p'], @toggleMarkdownPreview)
diff --git a/app/assets/javascripts/shortcuts_blob.coffee b/app/assets/javascripts/shortcuts_blob.coffee
new file mode 100644
index 00000000000..6d21e5d1150
--- /dev/null
+++ b/app/assets/javascripts/shortcuts_blob.coffee
@@ -0,0 +1,10 @@
+#= require shortcuts
+
+class @ShortcutsBlob extends Shortcuts
+ constructor: (skipResetBindings) ->
+ super skipResetBindings
+ Mousetrap.bind('y', ShortcutsBlob.copyToClipboard)
+
+ @copyToClipboard: ->
+ clipboardButton = $('.btn-clipboard')
+ clipboardButton.click() if clipboardButton
diff --git a/app/assets/javascripts/sidebar.js.coffee b/app/assets/javascripts/sidebar.js.coffee
index 2ce63c16428..68009e58645 100644
--- a/app/assets/javascripts/sidebar.js.coffee
+++ b/app/assets/javascripts/sidebar.js.coffee
@@ -3,13 +3,33 @@ expanded = 'page-sidebar-expanded'
toggleSidebar = ->
$('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}")
- $('header').toggleClass("header-collapsed header-expanded")
+ $('.navbar-fixed-top').toggleClass("header-collapsed header-expanded")
+
+ if $.cookie('pin_nav') is 'true'
+ $('.navbar-fixed-top').toggleClass('header-pinned-nav')
+ $('.page-with-sidebar').toggleClass('page-sidebar-pinned')
setTimeout ( ->
- niceScrollBars = $('.nicescroll').niceScroll();
+ niceScrollBars = $('.nav-sidebar').niceScroll();
niceScrollBars.updateScrollBar();
), 300
+$(document)
+ .off 'click', 'body'
+ .on 'click', 'body', (e) ->
+ unless $.cookie('pin_nav') is 'true'
+ $target = $(e.target)
+ $nav = $target.closest('.sidebar-wrapper')
+ pageExpanded = $('.page-with-sidebar').hasClass('page-sidebar-expanded')
+ $toggle = $target.closest('.toggle-nav-collapse, .side-nav-toggle')
+
+ if $nav.length is 0 and pageExpanded and $toggle.length is 0
+ $('.page-with-sidebar')
+ .toggleClass('page-sidebar-collapsed page-sidebar-expanded')
+
+ $('.navbar-fixed-top')
+ .toggleClass('header-collapsed header-expanded')
+
$(document).on("click", '.toggle-nav-collapse, .side-nav-toggle', (e) ->
e.preventDefault()
diff --git a/app/assets/javascripts/star.js.coffee b/app/assets/javascripts/star.js.coffee
index f27780dda93..01b28171f72 100644
--- a/app/assets/javascripts/star.js.coffee
+++ b/app/assets/javascripts/star.js.coffee
@@ -9,9 +9,11 @@ class @Star
$this.parent().find('.star-count').text data.star_count
if isStarred
$starSpan.removeClass('starred').text 'Star'
+ gl.utils.updateTooltipTitle $this, 'Star project'
$starIcon.removeClass('fa-star').addClass 'fa-star-o'
else
$starSpan.addClass('starred').text 'Unstar'
+ gl.utils.updateTooltipTitle $this, 'Unstar project'
$starIcon.removeClass('fa-star-o').addClass 'fa-star'
return
diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee
index 88246b0feb8..2548efb2186 100644
--- a/app/assets/javascripts/users_select.js.coffee
+++ b/app/assets/javascripts/users_select.js.coffee
@@ -31,7 +31,7 @@ class @UsersSelect
assignTo = (selected) ->
data = {}
data[abilityName] = {}
- data[abilityName].assignee_id = selected
+ data[abilityName].assignee_id = if selected? then selected else null
$loading
.fadeIn()
$dropdown.trigger('loading.gl.dropdown')
@@ -72,7 +72,7 @@ class @UsersSelect
assigneeTemplate = _.template(
'<% if (username) { %>
- <a class="author_link " href="/u/<%= username %>">
+ <a class="author_link bold" href="/u/<%= username %>">
<% if( avatar ) { %>
<img width="32" class="avatar avatar-inline s32" alt="" src="<%= avatar %>">
<% } %>
@@ -82,7 +82,7 @@ class @UsersSelect
</span>
</a>
<% } else { %>
- <span class="assign-yourself">
+ <span class="no-value assign-yourself">
No assignee -
<a href="#" class="js-assign-yourself">
assign yourself