Merge branch 'functional-sidebar' into 'master'
Updates sidebar to use new dropdowns for issues and merge requests Fixes #12935, #13164 See merge request !3175
This commit is contained in:
commit
55df9a70bf
21 changed files with 479 additions and 166 deletions
|
@ -126,8 +126,10 @@ class GitLabDropdown
|
|||
@selectFirstRow()
|
||||
|
||||
# Event listeners
|
||||
|
||||
@dropdown.on "shown.bs.dropdown", @opened
|
||||
@dropdown.on "hidden.bs.dropdown", @hidden
|
||||
@dropdown.on "click", ".dropdown-menu, .dropdown-menu-close", @shouldPropagate
|
||||
|
||||
if @dropdown.find(".dropdown-toggle-page").length
|
||||
@dropdown.find(".dropdown-toggle-page, .dropdown-menu-back").on "click", (e) =>
|
||||
|
@ -143,10 +145,11 @@ class GitLabDropdown
|
|||
selector = ".dropdown-page-one .dropdown-content a"
|
||||
|
||||
@dropdown.on "click", selector, (e) ->
|
||||
e.preventDefault()
|
||||
self.rowClicked $(@)
|
||||
|
||||
if self.options.clicked
|
||||
self.options.clicked()
|
||||
self.options.clicked.call(@,e)
|
||||
|
||||
toggleLoading: ->
|
||||
$('.dropdown-menu', @dropdown).toggleClass LOADING_CLASS
|
||||
|
@ -176,6 +179,15 @@ class GitLabDropdown
|
|||
|
||||
@appendMenu(full_html)
|
||||
|
||||
shouldPropagate: (e) =>
|
||||
if @options.multiSelect
|
||||
$target = $(e.target)
|
||||
if not $target.hasClass('dropdown-menu-close') and not $target.hasClass('dropdown-menu-close-icon')
|
||||
e.stopPropagation()
|
||||
return false
|
||||
else
|
||||
return true
|
||||
|
||||
opened: =>
|
||||
contentHtml = $('.dropdown-content', @dropdown).html()
|
||||
if @remote && contentHtml is ""
|
||||
|
@ -184,7 +196,7 @@ class GitLabDropdown
|
|||
if @options.filterable
|
||||
@dropdown.find(".dropdown-input-field").focus()
|
||||
|
||||
hidden: =>
|
||||
hidden: (e) =>
|
||||
if @options.filterable
|
||||
@dropdown
|
||||
.find(".dropdown-input-field")
|
||||
|
@ -195,6 +207,9 @@ class GitLabDropdown
|
|||
if @dropdown.find(".dropdown-toggle-page").length
|
||||
$('.dropdown-menu', @dropdown).removeClass PAGE_TWO_CLASS
|
||||
|
||||
if @options.hidden
|
||||
@options.hidden.call(@,e)
|
||||
|
||||
|
||||
# Render the full menu
|
||||
renderMenu: (html) ->
|
||||
|
@ -226,6 +241,13 @@ class GitLabDropdown
|
|||
html = @options.renderRow(data)
|
||||
else
|
||||
selected = if @options.isSelected then @options.isSelected(data) else false
|
||||
if not selected
|
||||
value = if @options.id then @options.id(data) else data.id
|
||||
fieldName = @options.fieldName
|
||||
field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']")
|
||||
if field.length
|
||||
selected = true
|
||||
|
||||
url = if @options.url then @options.url(data) else "#"
|
||||
text = if @options.text then @options.text(data) else ""
|
||||
cssClass = "";
|
||||
|
@ -258,26 +280,28 @@ class GitLabDropdown
|
|||
|
||||
rowClicked: (el) ->
|
||||
fieldName = @options.fieldName
|
||||
field = @dropdown.parent().find("input[name='#{fieldName}']")
|
||||
|
||||
selectedIndex = el.parent().index()
|
||||
if @renderedData
|
||||
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)
|
||||
el.removeClass(ACTIVE_CLASS)
|
||||
field.remove()
|
||||
else
|
||||
fieldName = @options.fieldName
|
||||
selectedIndex = el.parent().index()
|
||||
if @renderedData
|
||||
selectedObject = @renderedData[selectedIndex]
|
||||
selectedObject.selected = true
|
||||
value = if @options.id then @options.id(selectedObject, el) else selectedObject.id
|
||||
|
||||
if !value?
|
||||
field.remove()
|
||||
|
||||
if @options.multiSelect
|
||||
oldValue = field.val()
|
||||
if oldValue
|
||||
value = "#{oldValue},#{value}"
|
||||
else
|
||||
if not @options.multiSelect
|
||||
@dropdown.find(".#{ACTIVE_CLASS}").removeClass ACTIVE_CLASS
|
||||
@dropdown.parent().find("input[name='#{fieldName}']").remove()
|
||||
|
||||
# Toggle active class for the tick mark
|
||||
el.toggleClass "is-active"
|
||||
|
@ -285,15 +309,15 @@ class GitLabDropdown
|
|||
# Toggle the dropdown label
|
||||
if @options.toggleLabel
|
||||
$(@el).find(".dropdown-toggle-text").text @options.toggleLabel(selectedObject)
|
||||
|
||||
if value?
|
||||
if !field.length
|
||||
# Create hidden input for form
|
||||
input = "<input type='hidden' name='#{fieldName}' />"
|
||||
input = "<input type='hidden' name='#{fieldName}' value='#{value}' />"
|
||||
if @options.inputId?
|
||||
input = $(input)
|
||||
.attr('id', @options.inputId)
|
||||
@dropdown.before input
|
||||
|
||||
@dropdown.parent().find("input[name='#{fieldName}']").val value
|
||||
|
||||
selectFirstRow: ->
|
||||
selector = '.dropdown-content li:first-child a'
|
||||
if @dropdown.find(".dropdown-toggle-page").length
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
class @IssuableContext
|
||||
constructor: ->
|
||||
constructor: (currentUser) ->
|
||||
@initParticipants()
|
||||
|
||||
new UsersSelect()
|
||||
new UsersSelect(currentUser)
|
||||
$('select.select2').select2({width: 'resolve', dropdownAutoWidth: true})
|
||||
|
||||
$(".issuable-sidebar .inline-update").on "change", "select", ->
|
||||
|
@ -11,10 +10,20 @@ class @IssuableContext
|
|||
$(this).submit()
|
||||
|
||||
$(document).on "click",".edit-link", (e) ->
|
||||
block = $(@).parents('.block')
|
||||
block.find('.selectbox').show()
|
||||
block.find('.value').hide()
|
||||
block.find('.js-select2').select2("open")
|
||||
$block = $(@).parents('.block')
|
||||
$selectbox = $block.find('.selectbox')
|
||||
if $selectbox.is(':visible')
|
||||
$selectbox.hide()
|
||||
$block.find('.value').show()
|
||||
else
|
||||
$selectbox.show()
|
||||
$block.find('.value').hide()
|
||||
|
||||
if $selectbox.is(':visible')
|
||||
setTimeout (->
|
||||
$block.find('.dropdown-menu-toggle').trigger 'click'
|
||||
), 0
|
||||
|
||||
|
||||
$(".right-sidebar").niceScroll()
|
||||
|
||||
|
|
|
@ -4,14 +4,20 @@ class @LabelsSelect
|
|||
$dropdown = $(dropdown)
|
||||
projectId = $dropdown.data('project-id')
|
||||
labelUrl = $dropdown.data('labels')
|
||||
issueUpdateURL = $dropdown.data('issueUpdate')
|
||||
selectedLabel = $dropdown.data('selected')
|
||||
if selectedLabel
|
||||
selectedLabel = selectedLabel.toString().split(',')
|
||||
if selectedLabel?
|
||||
selectedLabel = selectedLabel.split(',')
|
||||
newLabelField = $('#new_label_name')
|
||||
newColorField = $('#new_label_color')
|
||||
showNo = $dropdown.data('show-no')
|
||||
showAny = $dropdown.data('show-any')
|
||||
defaultLabel = $dropdown.data('default-label')
|
||||
abilityName = $dropdown.data('ability-name')
|
||||
$selectbox = $dropdown.closest('.selectbox')
|
||||
$block = $selectbox.closest('.block')
|
||||
$value = $block.find('.value')
|
||||
$loading = $block.find('.block-loading').fadeOut()
|
||||
|
||||
if newLabelField.length
|
||||
$newLabelCreateButton = $('.js-new-label-btn')
|
||||
|
@ -21,6 +27,22 @@ class @LabelsSelect
|
|||
|
||||
# Suggested colors in the dropdown to chose from pre-chosen colors
|
||||
$('.suggest-colors-dropdown a').on 'click', (e) ->
|
||||
|
||||
issueURLSplit = issueUpdateURL.split('/') if issueUpdateURL?
|
||||
if issueUpdateURL
|
||||
labelHTMLTemplate = _.template(
|
||||
'<% _.each(labels, function(label){ %>
|
||||
<a href="<%= ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name=<%= label.title %>">
|
||||
<span class="label color-label" style="background-color: <%= label.color %>;">
|
||||
<%= label.title %>
|
||||
</span>
|
||||
</a>
|
||||
<% }); %>'
|
||||
);
|
||||
labelNoneHTMLTemplate = _.template('<div class="light">None</div>')
|
||||
|
||||
if newLabelField.length and $dropdown.hasClass 'js-extra-options'
|
||||
$('.suggest-colors-dropdown a').on "click", (e) ->
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
newColorField
|
||||
|
@ -57,6 +79,23 @@ class @LabelsSelect
|
|||
# This allows us to enable the button when ready
|
||||
enableLabelCreateButton = ->
|
||||
if newLabelField.val() isnt '' and newColorField.val() isnt ''
|
||||
$newLabelError.hide()
|
||||
$('.js-new-label-btn').disable()
|
||||
|
||||
# Create new label with API
|
||||
Api.newLabel projectId, {
|
||||
name: newLabelField.val()
|
||||
color: newColorField.val()
|
||||
}, (label) ->
|
||||
$('.js-new-label-btn').enable()
|
||||
|
||||
if label.message?
|
||||
$newLabelError
|
||||
.text label.message
|
||||
.show()
|
||||
else
|
||||
$('.dropdown-menu-back', $dropdown.parent()).trigger 'click'
|
||||
|
||||
$newLabelCreateButton.enable()
|
||||
else
|
||||
$newLabelCreateButton.disable()
|
||||
|
@ -90,41 +129,78 @@ class @LabelsSelect
|
|||
else
|
||||
$('.dropdown-menu-back', $dropdown.parent()).trigger 'click'
|
||||
|
||||
saveLabelData = ->
|
||||
selected = $dropdown
|
||||
.closest('.selectbox')
|
||||
.find("input[name='#{$dropdown.data('field-name')}']")
|
||||
.map(->
|
||||
@value
|
||||
).get()
|
||||
data = {}
|
||||
data[abilityName] = {}
|
||||
data[abilityName].label_ids = selected
|
||||
if not selected.length
|
||||
data[abilityName].label_ids = ['']
|
||||
$loading.fadeIn()
|
||||
$.ajax(
|
||||
type: 'PUT'
|
||||
url: issueUpdateURL
|
||||
dataType: 'JSON'
|
||||
data: data
|
||||
).done (data) ->
|
||||
$loading.fadeOut()
|
||||
$selectbox.hide()
|
||||
data.issueURLSplit = issueURLSplit
|
||||
if not data.labels.length
|
||||
template = labelNoneHTMLTemplate()
|
||||
else
|
||||
template = labelHTMLTemplate(data)
|
||||
href = $value
|
||||
.show()
|
||||
.html(template)
|
||||
$value
|
||||
.find('a')
|
||||
.each((i) ->
|
||||
setTimeout(=>
|
||||
glAnimate($(@), 'pulse')
|
||||
,200 * i
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
$dropdown.glDropdown(
|
||||
data: (term, callback) ->
|
||||
$.ajax(
|
||||
url: labelUrl
|
||||
).done (data) ->
|
||||
if showNo
|
||||
data.unshift(
|
||||
id: 0
|
||||
title: 'No Label'
|
||||
)
|
||||
if $dropdown.hasClass 'js-extra-options'
|
||||
if showNo
|
||||
data.unshift(
|
||||
id: 0
|
||||
title: 'No Label'
|
||||
)
|
||||
|
||||
if showAny
|
||||
data.unshift(
|
||||
isAny: true
|
||||
title: 'Any Label'
|
||||
)
|
||||
|
||||
if data.length > 2
|
||||
data.splice 2, 0, 'divider'
|
||||
if showAny
|
||||
data.unshift(
|
||||
isAny: true
|
||||
title: 'Any Label'
|
||||
)
|
||||
|
||||
if data.length > 2
|
||||
data.splice 2, 0, 'divider'
|
||||
callback data
|
||||
|
||||
renderRow: (label) ->
|
||||
if $.isArray(selectedLabel)
|
||||
selected = ''
|
||||
$.each selectedLabel, (i, selectedLbl) ->
|
||||
selectedLbl = selectedLbl.trim()
|
||||
if selected is '' and label.title is selectedLbl
|
||||
selected = 'is-active'
|
||||
else
|
||||
selected = if label.title is selectedLabel then 'is-active' else ''
|
||||
selectedClass = ''
|
||||
if $selectbox.find("input[type='hidden']\
|
||||
[name='#{$dropdown.data('field-name')}']\
|
||||
[value='#{label.id}']").length
|
||||
selectedClass = 'is-active'
|
||||
|
||||
color = if label.color? then "<span class='dropdown-label-box' style='background-color: #{label.color}'></span>" else ""
|
||||
|
||||
"<li>
|
||||
<a href='#' class='#{selected}'>
|
||||
<a href='#' class='#{selectedClass}'>
|
||||
#{color}
|
||||
#{label.title}
|
||||
</a>
|
||||
|
@ -133,6 +209,7 @@ class @LabelsSelect
|
|||
search:
|
||||
fields: ['title']
|
||||
selectable: true
|
||||
|
||||
toggleLabel: (selected) ->
|
||||
if selected and selected.title isnt 'Any Label'
|
||||
selected.title
|
||||
|
@ -142,8 +219,19 @@ class @LabelsSelect
|
|||
id: (label) ->
|
||||
if label.isAny?
|
||||
''
|
||||
else
|
||||
else if $dropdown.hasClass "js-filter-submit"
|
||||
label.title
|
||||
else
|
||||
label.id
|
||||
|
||||
hidden: ->
|
||||
$selectbox.hide()
|
||||
$value.show()
|
||||
if $dropdown.hasClass 'js-multiselect'
|
||||
saveLabelData()
|
||||
|
||||
multiSelect: $dropdown.hasClass 'js-multiselect'
|
||||
|
||||
clicked: ->
|
||||
page = $('body').data 'page'
|
||||
isIssueIndex = page is 'projects:issues:index'
|
||||
|
@ -153,4 +241,9 @@ class @LabelsSelect
|
|||
Issues.filterResults $dropdown.closest('form')
|
||||
else if $dropdown.hasClass 'js-filter-submit'
|
||||
$dropdown.closest('form').submit()
|
||||
else
|
||||
if $dropdown.hasClass 'js-multiselect'
|
||||
return
|
||||
else
|
||||
saveLabelData()
|
||||
)
|
||||
|
|
13
app/assets/javascripts/lib/animate.js.coffee
Normal file
13
app/assets/javascripts/lib/animate.js.coffee
Normal file
|
@ -0,0 +1,13 @@
|
|||
((w) ->
|
||||
|
||||
w.glAnimate = ($el, animation, done) ->
|
||||
$el
|
||||
.removeClass()
|
||||
.addClass(animation + ' animated')
|
||||
.one 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', ->
|
||||
$(this).removeClass()
|
||||
return
|
||||
return
|
||||
return
|
||||
|
||||
) window
|
|
@ -1,35 +1,52 @@
|
|||
class @MilestoneSelect
|
||||
constructor: ->
|
||||
constructor: (currentProject) ->
|
||||
if currentProject?
|
||||
_this = @
|
||||
@currentProject = JSON.parse(currentProject)
|
||||
$('.js-milestone-select').each (i, dropdown) ->
|
||||
$dropdown = $(dropdown)
|
||||
projectId = $dropdown.data('project-id')
|
||||
milestonesUrl = $dropdown.data('milestones')
|
||||
issueUpdateURL = $dropdown.data('issueUpdate')
|
||||
selectedMilestone = $dropdown.data('selected')
|
||||
showNo = $dropdown.data('show-no')
|
||||
showAny = $dropdown.data('show-any')
|
||||
useId = $dropdown.data('use-id')
|
||||
defaultLabel = $dropdown.data('default-label')
|
||||
issuableId = $dropdown.data('issuable-id')
|
||||
abilityName = $dropdown.data('ability-name')
|
||||
$selectbox = $dropdown.closest('.selectbox')
|
||||
$block = $selectbox.closest('.block')
|
||||
$value = $block.find('.value')
|
||||
$loading = $block.find('.block-loading').fadeOut()
|
||||
|
||||
if issueUpdateURL
|
||||
milestoneLinkTemplate = _.template(
|
||||
'<a href="/<%= namespace %>/<%= path %>/milestones/<%= iid %>"><%= title %></a>'
|
||||
)
|
||||
|
||||
milestoneLinkNoneTemplate = '<div class="light">None</div>'
|
||||
|
||||
$dropdown.glDropdown(
|
||||
data: (term, callback) ->
|
||||
$.ajax(
|
||||
url: milestonesUrl
|
||||
).done (data) ->
|
||||
if showNo
|
||||
data.unshift(
|
||||
id: '0'
|
||||
title: 'No Milestone'
|
||||
)
|
||||
if $dropdown.hasClass "js-extra-options"
|
||||
if showNo
|
||||
data.unshift(
|
||||
id: '0'
|
||||
title: 'No Milestone'
|
||||
)
|
||||
|
||||
if showAny
|
||||
data.unshift(
|
||||
isAny: true
|
||||
title: 'Any Milestone'
|
||||
)
|
||||
|
||||
if data.length > 2
|
||||
data.splice 2, 0, 'divider'
|
||||
if showAny
|
||||
data.unshift(
|
||||
isAny: true
|
||||
title: 'Any Milestone'
|
||||
)
|
||||
|
||||
if data.length > 2
|
||||
data.splice 2, 0, 'divider'
|
||||
callback(data)
|
||||
filterable: true
|
||||
search:
|
||||
|
@ -53,13 +70,38 @@ class @MilestoneSelect
|
|||
milestone.id
|
||||
isSelected: (milestone) ->
|
||||
milestone.title is selectedMilestone
|
||||
clicked: ->
|
||||
page = $('body').data 'page'
|
||||
isIssueIndex = page is 'projects:issues:index'
|
||||
isMRIndex = page is page is 'projects:merge_requests:index'
|
||||
|
||||
if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex)
|
||||
Issues.filterResults $dropdown.closest('form')
|
||||
else if $dropdown.hasClass 'js-filter-submit'
|
||||
$dropdown.closest('form').submit()
|
||||
)
|
||||
hidden: ->
|
||||
$selectbox.hide()
|
||||
$value.show()
|
||||
clicked: (e) ->
|
||||
if $dropdown.hasClass 'js-filter-bulk-update'
|
||||
return
|
||||
|
||||
if $dropdown.hasClass 'js-filter-submit'
|
||||
$dropdown.parents('form').submit()
|
||||
else
|
||||
selected = $selectbox
|
||||
.find('input[type="hidden"]')
|
||||
.val()
|
||||
data = {}
|
||||
data[abilityName] = {}
|
||||
data[abilityName].milestone_id = selected
|
||||
$loading
|
||||
.fadeIn()
|
||||
$.ajax(
|
||||
type: 'PUT'
|
||||
url: issueUpdateURL
|
||||
data: data
|
||||
).done (data) ->
|
||||
$loading.fadeOut()
|
||||
$selectbox.hide()
|
||||
$milestoneLink = $value
|
||||
.show()
|
||||
.find('a')
|
||||
if data.milestone?
|
||||
data.milestone.namespace = _this.currentProject.namespace
|
||||
data.milestone.path = _this.currentProject.path
|
||||
$value.html(milestoneLinkTemplate(data.milestone))
|
||||
else
|
||||
$value.html(milestoneLinkNoneTemplate)
|
||||
)
|
|
@ -1,7 +1,9 @@
|
|||
class @UsersSelect
|
||||
constructor: ->
|
||||
constructor: (currentUser) ->
|
||||
@usersPath = "/autocomplete/users.json"
|
||||
@userPath = "/autocomplete/users/:id.json"
|
||||
if currentUser?
|
||||
@currentUser = JSON.parse(currentUser)
|
||||
|
||||
$('.js-user-search').each (i, dropdown) =>
|
||||
$dropdown = $(dropdown)
|
||||
|
@ -12,6 +14,67 @@ class @UsersSelect
|
|||
firstUser = $dropdown.data('first-user')
|
||||
selectedId = $dropdown.data('selected')
|
||||
defaultLabel = $dropdown.data('default-label')
|
||||
issueURL = $dropdown.data('issueUpdate')
|
||||
$selectbox = $dropdown.closest('.selectbox')
|
||||
$block = $selectbox.closest('.block')
|
||||
abilityName = $dropdown.data('ability-name')
|
||||
$value = $block.find('.value')
|
||||
$loading = $block.find('.block-loading').fadeOut()
|
||||
|
||||
$block.on('click', '.js-assign-yourself', (e) =>
|
||||
e.preventDefault()
|
||||
assignTo(@currentUser.id)
|
||||
)
|
||||
|
||||
assignTo = (selected) ->
|
||||
data = {}
|
||||
data[abilityName] = {}
|
||||
data[abilityName].assignee_id = selected
|
||||
$loading
|
||||
.fadeIn()
|
||||
$.ajax(
|
||||
type: 'PUT'
|
||||
dataType: 'json'
|
||||
url: issueURL
|
||||
data: data
|
||||
).done (data) ->
|
||||
$loading.fadeOut()
|
||||
$selectbox.hide()
|
||||
|
||||
if data.assignee
|
||||
user =
|
||||
name: data.assignee.name
|
||||
username: data.assignee.username
|
||||
avatar: data.assignee.avatar_url
|
||||
else
|
||||
user =
|
||||
name: 'Unassigned'
|
||||
username: ''
|
||||
avatar: ''
|
||||
|
||||
$value.html(noAssigneeTemplate(user))
|
||||
$value.find('a').attr('href')
|
||||
|
||||
noAssigneeTemplate = _.template(
|
||||
'<% if (username) { %>
|
||||
<a class="author_link " href="/u/<%= username %>">
|
||||
<% if( avatar ) { %>
|
||||
<img width="32" class="avatar avatar-inline s32" alt="" src="<%= avatar %>">
|
||||
<% } %>
|
||||
<span class="author"><%= name %></span>
|
||||
<span class="username">
|
||||
@<%= username %>
|
||||
</span>
|
||||
</a>
|
||||
<% } else { %>
|
||||
<span class="assign-yourself">
|
||||
No assignee -
|
||||
<a href="#" class="js-assign-yourself">
|
||||
assign yourself
|
||||
</a>
|
||||
</span>
|
||||
<% } %>'
|
||||
)
|
||||
|
||||
$dropdown.glDropdown(
|
||||
data: (term, callback) =>
|
||||
|
@ -57,20 +120,36 @@ class @UsersSelect
|
|||
fields: ['name', 'username']
|
||||
selectable: true
|
||||
fieldName: $dropdown.data('field-name')
|
||||
|
||||
toggleLabel: (selected) ->
|
||||
if selected && 'id' of selected
|
||||
selected.name
|
||||
else
|
||||
defaultLabel
|
||||
|
||||
inputId: 'issue_assignee_id'
|
||||
|
||||
hidden: (e) ->
|
||||
$selectbox.hide()
|
||||
$value.show()
|
||||
|
||||
clicked: ->
|
||||
page = $('body').data 'page'
|
||||
isIssueIndex = page is 'projects:issues:index'
|
||||
isMRIndex = page is page is 'projects:merge_requests:index'
|
||||
if $dropdown.hasClass('js-filter-bulk-update')
|
||||
return
|
||||
|
||||
if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex)
|
||||
Issues.filterResults $dropdown.closest('form')
|
||||
else if $dropdown.hasClass 'js-filter-submit'
|
||||
$dropdown.closest('form').submit()
|
||||
else
|
||||
selected = $dropdown
|
||||
.closest('.selectbox')
|
||||
.find("input[name='#{$dropdown.data('field-name')}']").val()
|
||||
assignTo(selected)
|
||||
|
||||
renderRow: (user) ->
|
||||
username = if user.username then "@#{user.username}" else ""
|
||||
avatar = if user.avatar_url then user.avatar_url else false
|
||||
|
@ -87,17 +166,25 @@ class @UsersSelect
|
|||
if avatar
|
||||
img = "<img src='#{avatar}' class='avatar avatar-inline' width='30' />"
|
||||
|
||||
"<li>
|
||||
<a href='#' class='dropdown-menu-user-link #{selected}'>
|
||||
#{img}
|
||||
<strong class='dropdown-menu-user-full-name'>
|
||||
#{user.name}
|
||||
</strong>
|
||||
<span class='dropdown-menu-user-username'>
|
||||
#{username}
|
||||
</span>
|
||||
</a>
|
||||
</li>"
|
||||
# split into three parts so we can remove the username section if nessesary
|
||||
listWithName = "<li>
|
||||
<a href='#' class='dropdown-menu-user-link #{selected}'>
|
||||
#{img}
|
||||
<strong class='dropdown-menu-user-full-name'>
|
||||
#{user.name}
|
||||
</strong>"
|
||||
|
||||
listWithUserName = "<span class='dropdown-menu-user-username'>
|
||||
#{username}
|
||||
</span>"
|
||||
listClosingTags = "</a>
|
||||
</li>"
|
||||
|
||||
|
||||
if username is ''
|
||||
listWithUserName = ''
|
||||
|
||||
listWithName + listWithUserName + listClosingTags
|
||||
)
|
||||
|
||||
$('.ajax-users-select').each (i, select) =>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
*= require dropzone/basic
|
||||
*= require cal-heatmap
|
||||
*= require cropper.css
|
||||
*= require animate
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
|
@ -117,7 +117,7 @@
|
|||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
color: $dropdown-link-color;
|
||||
line-height: 34px;
|
||||
line-height: 16px;
|
||||
text-overflow: ellipsis;
|
||||
border-radius: 2px;
|
||||
white-space: nowrap;
|
||||
|
@ -167,13 +167,13 @@
|
|||
}
|
||||
|
||||
.dropdown-menu-user-link {
|
||||
padding-top: 7px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 7px;
|
||||
}
|
||||
|
||||
.dropdown-menu-user-full-name {
|
||||
display: block;
|
||||
font-weight: 600;
|
||||
font-weight: 500;
|
||||
line-height: 16px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
}
|
||||
|
||||
.issuable-sidebar {
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.block {
|
||||
@include clearfix;
|
||||
padding: $gl-padding 0;
|
||||
|
@ -89,7 +93,7 @@
|
|||
}
|
||||
|
||||
.cross-project-reference {
|
||||
color: $gl-link-color;
|
||||
color: inherit;
|
||||
|
||||
span {
|
||||
white-space: nowrap;
|
||||
|
@ -133,6 +137,12 @@
|
|||
|
||||
.value {
|
||||
line-height: 1;
|
||||
|
||||
.assign-yourself {
|
||||
margin-top: 10px;
|
||||
font-weight: normal;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.bold {
|
||||
|
@ -252,6 +262,15 @@
|
|||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu-toggle {
|
||||
width: 100%;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.open .dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-default.gutter-toggle {
|
||||
|
|
|
@ -68,7 +68,13 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
@merge_requests = @issue.referenced_merge_requests(current_user)
|
||||
@related_branches = @issue.related_branches - @merge_requests.map(&:source_branch)
|
||||
|
||||
respond_with(@issue)
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json do
|
||||
render json: @issue.to_json(include: [:milestone, :labels])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -107,10 +113,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
end
|
||||
end
|
||||
format.json do
|
||||
render json: {
|
||||
saved: @issue.valid?,
|
||||
assignee_avatar_url: @issue.assignee.try(:avatar_url)
|
||||
}
|
||||
render json: @issue.to_json(include: [:milestone, :labels, assignee: { methods: :avatar_url }])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -154,10 +154,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
@merge_request.target_project, @merge_request])
|
||||
end
|
||||
format.json do
|
||||
render json: {
|
||||
saved: @merge_request.valid?,
|
||||
assignee_avatar_url: @merge_request.assignee.try(:avatar_url)
|
||||
}
|
||||
render json: @merge_request.to_json(include: [:milestone, :labels, :assignee])
|
||||
end
|
||||
end
|
||||
else
|
||||
|
|
|
@ -19,7 +19,6 @@ class Projects::MilestonesController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
@milestones = @milestones.includes(:project)
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
@milestones = @milestones.page(params[:page])
|
||||
|
|
|
@ -60,7 +60,7 @@ module DropdownsHelper
|
|||
title_output << content_tag(:span, title)
|
||||
|
||||
title_output << content_tag(:button, class: "dropdown-title-button dropdown-menu-close", aria: { label: "Close" }, type: "button") do
|
||||
icon('times')
|
||||
icon('times', class: 'dropdown-menu-close-icon')
|
||||
end
|
||||
|
||||
title_output.html_safe
|
||||
|
|
|
@ -16,6 +16,16 @@ module IssuablesHelper
|
|||
base_issuable_scope(issuable).where('iid > ?', issuable.iid).last
|
||||
end
|
||||
|
||||
def issuable_json_path(issuable)
|
||||
project = issuable.project
|
||||
|
||||
if issuable.kind_of?(MergeRequest)
|
||||
namespace_project_merge_request_path(project.namespace, project, issuable.iid, :json)
|
||||
else
|
||||
namespace_project_issue_path(project.namespace, project, issuable.iid, :json)
|
||||
end
|
||||
end
|
||||
|
||||
def prev_issuable_for(issuable)
|
||||
base_issuable_scope(issuable).where('iid < ?', issuable.iid).first
|
||||
end
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
.merge-request{'data-url' => merge_request_path(@merge_request)}
|
||||
= render "projects/merge_requests/show/mr_title"
|
||||
|
||||
.merge-request-details.issuable-details
|
||||
.merge-request-details.issuable-details{data: {id: @merge_request.project.id}}
|
||||
= render "projects/merge_requests/show/mr_box"
|
||||
.append-bottom-default.mr-source-target.prepend-top-default
|
||||
- if @merge_request.open?
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
.filter-item.inline
|
||||
- if params[:author_id]
|
||||
= hidden_field_tag(:author_id, params[:author_id])
|
||||
= dropdown_tag(user_dropdown_label(params[:author_id], "Author"), options: { toggle_class: "js-user-search js-filter-submit js-author-search", title: "Filter by author", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-author",
|
||||
= dropdown_tag(user_dropdown_label(params[:author_id], "Author"), options: { toggle_class: "js-user-search js-filter-submit js-author-search", title: "Filter by author", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit",
|
||||
placeholder: "Search authors", data: { any_user: "Any Author", first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author_id], field_name: "author_id", default_label: "Author" } })
|
||||
|
||||
.filter-item.inline
|
||||
- if params[:assignee_id]
|
||||
= hidden_field_tag(:assignee_id, params[:assignee_id])
|
||||
= dropdown_tag(user_dropdown_label(params[:assignee_id], "Assignee"), options: { toggle_class: "js-user-search js-filter-submit js-assignee-search", title: "Filter by assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee",
|
||||
= dropdown_tag(user_dropdown_label(params[:assignee_id], "Assignee"), options: { toggle_class: "js-user-search js-filter-submit js-assignee-search", title: "Filter by assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee js-filter-submit",
|
||||
placeholder: "Search assignee", data: { any_user: "Any Assignee", first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: (@project.id if @project), selected: params[:assignee_id], field_name: "assignee_id", default_label: "Assignee" } })
|
||||
|
||||
.filter-item.inline.milestone-filter
|
||||
|
@ -23,7 +23,6 @@
|
|||
|
||||
.filter-item.inline.labels-filter
|
||||
= render "shared/issuable/label_dropdown"
|
||||
|
||||
.pull-right
|
||||
= render 'shared/sort_dropdown'
|
||||
|
||||
|
@ -38,11 +37,10 @@
|
|||
%li
|
||||
%a{href: "#", data: {id: "close"}} Closed
|
||||
.filter-item.inline
|
||||
= dropdown_tag("Assignee", options: { toggle_class: "js-user-search js-update-assignee", title: "Assign to", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable",
|
||||
= dropdown_tag("Assignee", options: { toggle_class: "js-user-search js-update-assignee js-filter-submit js-filter-bulk-update", title: "Assign to", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable",
|
||||
placeholder: "Search authors", data: { first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: @project.id, field_name: "update[assignee_id]" } })
|
||||
.filter-item.inline
|
||||
= dropdown_tag("Milestone", options: { title: "Assign milestone", toggle_class: 'js-milestone-select', filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone",
|
||||
placeholder: "Search milestones", data: { show_no: true, field_name: "update[milestone_id]", project_id: @project.id, milestones: namespace_project_milestones_path(@project.namespace, @project, :json), use_id: true } })
|
||||
= dropdown_tag("Milestone", options: { title: "Assign milestone", toggle_class: 'js-milestone-select js-extra-options js-filter-submit js-filter-bulk-update', filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone", placeholder: "Search milestones", data: { show_no: true, field_name: "update[milestone_id]", project_id: @project.id, milestones: namespace_project_milestones_path(@project.namespace, @project, :json), use_id: true } })
|
||||
= hidden_field_tag 'update[issues_ids]', []
|
||||
= hidden_field_tag :state_event, params[:state_event]
|
||||
.filter-item.inline
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
- if params[:milestone_title]
|
||||
= hidden_field_tag(:milestone_title, params[:milestone_title])
|
||||
= dropdown_tag(h(params[:milestone_title].presence || "Milestone"), options: { title: "Filter by milestone", toggle_class: 'js-milestone-select js-filter-submit', filter: true, dropdown_class: "dropdown-menu-selectable",
|
||||
= dropdown_tag(h(params[:milestone_title].presence || "Milestone"), options: { title: "Filter by milestone", toggle_class: 'js-milestone-select js-filter-submit js-extra-options', filter: true, dropdown_class: "dropdown-menu-selectable",
|
||||
placeholder: "Search milestones", footer_content: @project.present?, data: { show_no: true, show_any: true, field_name: "milestone_title", selected: params[:milestone_title], project_id: @project.try(:id), milestones: milestones_filter_dropdown_path, default_label: "Milestone" } }) do
|
||||
- if @project
|
||||
%ul.dropdown-footer-list
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
= icon('user')
|
||||
.title.hide-collapsed
|
||||
Assignee
|
||||
= icon('spinner spin', class: 'block-loading')
|
||||
- if can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
|
||||
= link_to 'Edit', '#', class: 'edit-link pull-right'
|
||||
.value.bold.hide-collapsed
|
||||
|
@ -39,10 +40,14 @@
|
|||
%span.username
|
||||
= issuable.assignee.to_reference
|
||||
- else
|
||||
.light None
|
||||
%span.assign-yourself
|
||||
No assignee -
|
||||
%a.js-assign-yourself{ href: '#' }
|
||||
assign yourself
|
||||
|
||||
.selectbox.hide-collapsed
|
||||
= users_select_tag("#{issuable.class.table_name.singularize}[assignee_id]", placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: issuable.assignee_id, project: @target_project, null_user: true, current_user: true, first_user: true)
|
||||
= f.hidden_field 'assignee_id', value: issuable.assignee_id, id: 'issue_assignee_id'
|
||||
= dropdown_tag('Select assignee', options: { toggle_class: 'js-user-search js-author-search', title: 'Assign to', filter: true, dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author', placeholder: 'Search users', data: { first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), field_name: "#{issuable.to_ability_name}[assignee_id]", issue_update: issuable_json_path(issuable), ability_name: issuable.to_ability_name, null_user: true } })
|
||||
|
||||
.block.milestone
|
||||
.sidebar-collapsed-icon
|
||||
|
@ -54,6 +59,7 @@
|
|||
No
|
||||
.title.hide-collapsed
|
||||
Milestone
|
||||
= icon('spinner spin', class: 'block-loading')
|
||||
- if can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
|
||||
= link_to 'Edit', '#', class: 'edit-link pull-right'
|
||||
.value.bold.hide-collapsed
|
||||
|
@ -62,10 +68,10 @@
|
|||
= issuable.milestone.title
|
||||
- else
|
||||
.light None
|
||||
|
||||
.selectbox.hide-collapsed
|
||||
= f.select(:milestone_id, milestone_options(issuable), { include_blank: true }, { class: 'select2 select2-compact js-select2 js-milestone', data: { placeholder: 'Select milestone' }})
|
||||
= hidden_field_tag :issuable_context
|
||||
= f.submit class: 'btn hide'
|
||||
= f.hidden_field 'milestone_id', value: issuable.milestone_id, id: nil
|
||||
= dropdown_tag('Milestone', options: { title: 'Assign milestone', toggle_class: 'js-milestone-select js-extra-options', filter: true, dropdown_class: 'dropdown-menu-selectable', placeholder: 'Search milestones', data: { show_no: true, field_name: "#{issuable.to_ability_name}[milestone_id]", project_id: @project.id, issuable_id: issuable.id, milestones: namespace_project_milestones_path(@project.namespace, @project, :json), ability_name: issuable.to_ability_name, issue_update: issuable_json_path(issuable), use_id: true }})
|
||||
|
||||
- if issuable.project.labels.any?
|
||||
.block.labels
|
||||
|
@ -75,6 +81,7 @@
|
|||
= issuable.labels.count
|
||||
.title.hide-collapsed
|
||||
Labels
|
||||
= icon('spinner spin', class: 'block-loading')
|
||||
- if can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
|
||||
= link_to 'Edit', '#', class: 'edit-link pull-right'
|
||||
.value.bold.issuable-show-labels.hide-collapsed{ class: ("has-labels" if issuable.labels.any?) }
|
||||
|
@ -84,8 +91,31 @@
|
|||
- else
|
||||
.light None
|
||||
.selectbox.hide-collapsed
|
||||
= f.collection_select :label_ids, issuable.project.labels.all, :id, :name,
|
||||
{ selected: issuable.label_ids }, multiple: true, class: 'select2 js-select2', data: { placeholder: "Select labels" }
|
||||
- issuable.labels.each do |label|
|
||||
= hidden_field_tag "#{issuable.to_ability_name}[label_names][]", label.id, id: nil
|
||||
.dropdown
|
||||
%button.dropdown-menu-toggle.js-label-select.js-multiselect{type: "button", data: {toggle: "dropdown", field_name: "#{issuable.to_ability_name}[label_names][]", ability_name: issuable.to_ability_name, show_no: "true", show_any: "true", project_id: (@project.id if @project), issue_update: issuable_json_path(issuable), labels: (namespace_project_labels_path(@project.namespace, @project, :json) if @project)}}
|
||||
%span.dropdown-toggle-text
|
||||
Label
|
||||
= icon('chevron-down')
|
||||
.dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable
|
||||
.dropdown-page-one
|
||||
= dropdown_title("Assign labels")
|
||||
= dropdown_filter("Search labels")
|
||||
= dropdown_content
|
||||
- if @project
|
||||
= dropdown_footer do
|
||||
%ul.dropdown-footer-list
|
||||
- if can? current_user, :admin_label, @project
|
||||
%li
|
||||
%a.dropdown-toggle-page{href: "#"}
|
||||
Create new
|
||||
%li
|
||||
= link_to namespace_project_labels_path(@project.namespace, @project) do
|
||||
- if can? current_user, :admin_label, @project
|
||||
Manage labels
|
||||
- else
|
||||
View labels
|
||||
|
||||
= render "shared/issuable/participants", participants: issuable.participants(current_user)
|
||||
- if current_user
|
||||
|
@ -116,5 +146,7 @@
|
|||
= clipboard_button(clipboard_text: project_ref)
|
||||
|
||||
:javascript
|
||||
new Subscription('.subscription');
|
||||
new IssuableContext();
|
||||
new MilestoneSelect('{"namespace":"#{@project.namespace.path}","path":"#{@project.path}"}');
|
||||
new LabelsSelect();
|
||||
new IssuableContext('#{current_user.to_json(only: [:username, :id, :name])}');
|
||||
new Subscription('.subscription')
|
||||
|
|
|
@ -31,7 +31,7 @@ feature 'Issue filtering by Milestone', feature: true do
|
|||
def filter_by_milestone(title)
|
||||
find(".js-milestone-select").click
|
||||
sleep 0.5
|
||||
find(".milestone-filter a", text: title).click
|
||||
find(".milestone-filter .dropdown-content a", text: title).click
|
||||
sleep 1
|
||||
end
|
||||
end
|
||||
|
|
|
@ -34,20 +34,7 @@ describe 'Issues', feature: true do
|
|||
fill_in 'issue_title', with: 'bug 345'
|
||||
fill_in 'issue_description', with: 'bug description'
|
||||
end
|
||||
|
||||
it 'does not change issue count' do
|
||||
expect { click_button 'Save changes' }.to_not change { Issue.count }
|
||||
end
|
||||
|
||||
it 'should update issue fields' do
|
||||
click_button 'Save changes'
|
||||
|
||||
expect(page).to have_content @user.name
|
||||
expect(page).to have_content 'bug 345'
|
||||
expect(page).to have_content project.name
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe 'Editing issue assignee' do
|
||||
|
@ -70,7 +57,7 @@ describe 'Issues', feature: true do
|
|||
click_button 'Save changes'
|
||||
|
||||
page.within('.assignee') do
|
||||
expect(page).to have_content 'None'
|
||||
expect(page).to have_content 'No assignee - assign yourself'
|
||||
end
|
||||
|
||||
expect(issue.reload.assignee).to be_nil
|
||||
|
@ -198,20 +185,26 @@ describe 'Issues', feature: true do
|
|||
end
|
||||
|
||||
describe 'update assignee from issue#show' do
|
||||
let(:issue) { create(:issue, project: project, author: @user) }
|
||||
let(:issue) { create(:issue, project: project, author: @user, assignee: @user) }
|
||||
|
||||
context 'by autorized user' do
|
||||
|
||||
it 'with dropdown menu' do
|
||||
it 'allows user to select unassigned', js: true do
|
||||
visit namespace_project_issue_path(project.namespace, project, issue)
|
||||
|
||||
find('.issuable-sidebar #issue_assignee_id').
|
||||
set project.team.members.first.id
|
||||
click_button 'Update Issue'
|
||||
page.within('.assignee') do
|
||||
expect(page).to have_content "#{@user.name}"
|
||||
end
|
||||
|
||||
expect(page).to have_content 'Assignee'
|
||||
has_select?('issue_assignee_id',
|
||||
selected: project.team.members.first.name)
|
||||
find('.block.assignee .edit-link').click
|
||||
sleep 2 # wait for ajax stuff to complete
|
||||
first('.dropdown-menu-user-link').click
|
||||
sleep 2
|
||||
page.within('.assignee') do
|
||||
expect(page).to have_content 'No assignee'
|
||||
end
|
||||
|
||||
expect(issue.reload.assignee).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -221,8 +214,6 @@ describe 'Issues', feature: true do
|
|||
|
||||
before :each do
|
||||
project.team << [[guest], :guest]
|
||||
issue.assignee = @user
|
||||
issue.save
|
||||
end
|
||||
|
||||
it 'shows assignee text', js: true do
|
||||
|
@ -241,20 +232,23 @@ describe 'Issues', feature: true do
|
|||
|
||||
context 'by authorized user' do
|
||||
|
||||
it 'with dropdown menu' do
|
||||
|
||||
it 'allows user to select unassigned', js: true do
|
||||
visit namespace_project_issue_path(project.namespace, project, issue)
|
||||
|
||||
find('.issuable-sidebar').
|
||||
select(milestone.title, from: 'issue_milestone_id')
|
||||
click_button 'Update Issue'
|
||||
|
||||
expect(page).to have_content "Milestone changed to #{milestone.title}"
|
||||
|
||||
page.within('.milestone') do
|
||||
expect(page).to have_content milestone.title
|
||||
expect(page).to have_content "None"
|
||||
end
|
||||
|
||||
has_select?('issue_assignee_id', selected: milestone.title)
|
||||
find('.block.milestone .edit-link').click
|
||||
sleep 2 # wait for ajax stuff to complete
|
||||
first('.dropdown-content li').click
|
||||
sleep 2
|
||||
page.within('.milestone') do
|
||||
expect(page).to have_content 'None'
|
||||
end
|
||||
|
||||
expect(issue.reload.milestone).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -283,25 +277,6 @@ describe 'Issues', feature: true do
|
|||
issue.assignee = user2
|
||||
issue.save
|
||||
end
|
||||
|
||||
it 'allows user to remove assignee', js: true do
|
||||
visit namespace_project_issue_path(project.namespace, project, issue)
|
||||
|
||||
page.within('.assignee') do
|
||||
expect(page).to have_content user2.name
|
||||
end
|
||||
|
||||
find('.assignee .edit-link').click
|
||||
sleep 2 # wait for ajax stuff to complete
|
||||
first('.user-result').click
|
||||
|
||||
page.within('.assignee') do
|
||||
expect(page).to have_content 'None'
|
||||
end
|
||||
|
||||
sleep 2 # wait for ajax stuff to complete
|
||||
expect(issue.reload.assignee).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
11
vendor/assets/stylesheets/animate.css
vendored
Normal file
11
vendor/assets/stylesheets/animate.css
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue