summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRémy Coutable <remy@rymai.me>2016-03-30 06:49:04 +0000
committerRémy Coutable <remy@rymai.me>2016-03-30 09:26:54 +0200
commit07a4aacafce518dcdcec9a12d76df3c310af3e93 (patch)
treece6021563933397bdf6c9aa04dfa8e72b8ca7991
parent966ade1d7509d7acaad3c59c5d6cd23c560d72bd (diff)
downloadgitlab-ce-07a4aacafce518dcdcec9a12d76df3c310af3e93.tar.gz
Merge branch 'added-milestone-upcoming' into 'master'
Dropdown bug fixes - Added back upcoming to milestone filter ![Screen_Shot_2016-03-23_at_16.45.22](/uploads/8c31eff7e0984aad17881f6397ff17cd/Screen_Shot_2016-03-23_at_16.45.22.png) - Fixed bug that would cause the currently selected value to disappear on filters - Fixed bug that throw an error when filtering by upcoming when there is only a milestone in the past Closes #14536 See merge request !3368 Signed-off-by: Rémy Coutable <remy@rymai.me>
-rw-r--r--CHANGELOG2
-rw-r--r--app/assets/javascripts/gl_dropdown.js.coffee29
-rw-r--r--app/assets/javascripts/issues.js.coffee10
-rw-r--r--app/assets/javascripts/labels_select.js.coffee4
-rw-r--r--app/assets/javascripts/milestone_select.js.coffee83
-rw-r--r--app/assets/javascripts/users_select.js.coffee10
-rw-r--r--app/controllers/projects/milestones_controller.rb2
-rw-r--r--app/finders/issuable_finder.rb4
-rw-r--r--app/helpers/issuables_helper.rb8
-rw-r--r--app/models/global_milestone.rb1
-rw-r--r--app/views/shared/issuable/_milestone_dropdown.html.haml4
-rw-r--r--spec/features/issues/filter_by_milestone_spec.rb42
-rw-r--r--spec/features/merge_requests/filter_by_milestone_spec.rb38
13 files changed, 178 insertions, 59 deletions
diff --git a/CHANGELOG b/CHANGELOG
index deae7218fc9..84babb67f61 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -9,7 +9,7 @@ v 8.6.2
- Fix order of steps to prevent PostgreSQL errors when running migration. !3355
- Fix bold text in issuable sidebar. !3358
- Fix error with anonymous token in applications settings. !3362
- - Fix the milestone 'upcoming' filter. !3364
+ - Fix the milestone 'upcoming' filter. !3364 + !3368
- Fix comments on confidential issues showing up in activity feed to non-members. !3375
- Fix `NoMethodError` when visiting CI root path at `/ci`. !3377
- Add a tooltip to new branch button in issue page. !3380
diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee
index 4b78bcde774..2221ff05357 100644
--- a/app/assets/javascripts/gl_dropdown.js.coffee
+++ b/app/assets/javascripts/gl_dropdown.js.coffee
@@ -143,10 +143,10 @@ class GitLabDropdown
selector = ".dropdown-page-one .dropdown-content a"
@dropdown.on "click", selector, (e) ->
- self.rowClicked $(@)
+ selected = self.rowClicked $(@)
if self.options.clicked
- self.options.clicked()
+ self.options.clicked(selected)
toggleLoading: ->
$('.dropdown-menu', @dropdown).toggleClass LOADING_CLASS
@@ -258,17 +258,19 @@ 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)
field.remove()
- else
- fieldName = @options.fieldName
- selectedIndex = el.parent().index()
- if @renderedData
- selectedObject = @renderedData[selectedIndex]
- value = if @options.id then @options.id(selectedObject, el) else selectedObject.id
+ # Toggle the dropdown label
+ if @options.toggleLabel
+ $(@el).find(".dropdown-toggle-text").text @options.toggleLabel
+ else
if !value?
field.remove()
@@ -280,7 +282,7 @@ class GitLabDropdown
@dropdown.find(".#{ACTIVE_CLASS}").removeClass ACTIVE_CLASS
# Toggle active class for the tick mark
- el.toggleClass "is-active"
+ el.addClass ACTIVE_CLASS
# Toggle the dropdown label
if @options.toggleLabel
@@ -289,10 +291,13 @@ class GitLabDropdown
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
+ return selectedObject
selectFirstRow: ->
selector = '.dropdown-content li:first-child a'
diff --git a/app/assets/javascripts/issues.js.coffee b/app/assets/javascripts/issues.js.coffee
index 1127b289264..b1479bfb449 100644
--- a/app/assets/javascripts/issues.js.coffee
+++ b/app/assets/javascripts/issues.js.coffee
@@ -1,7 +1,6 @@
@Issues =
init: ->
Issues.initSearch()
- Issues.initSelects()
Issues.initChecks()
$("body").on "ajax:success", ".close_issue, .reopen_issue", ->
@@ -17,18 +16,9 @@
$(this).html totalIssues - 1
reload: ->
- Issues.initSelects()
Issues.initChecks()
$('#filter_issue_search').val($('#issue_search').val())
- initSelects: ->
- $("select#update_state_event").select2(width: 'resolve', dropdownAutoWidth: true)
- $("select#update_assignee_id").select2(width: 'resolve', dropdownAutoWidth: true)
- $("select#update_milestone_id").select2(width: 'resolve', dropdownAutoWidth: true)
- $("select#label_name").select2(width: 'resolve', dropdownAutoWidth: true)
- $("#milestone_id, #assignee_id, #label_name").on "change", ->
- $(this).closest("form").submit()
-
initChecks: ->
$(".check_all_issues").click ->
$(".selected_issue").prop("checked", @checked)
diff --git a/app/assets/javascripts/labels_select.js.coffee b/app/assets/javascripts/labels_select.js.coffee
index e08648d583b..9d0654083dc 100644
--- a/app/assets/javascripts/labels_select.js.coffee
+++ b/app/assets/javascripts/labels_select.js.coffee
@@ -144,12 +144,14 @@ class @LabelsSelect
''
else
label.title
- clicked: ->
+ clicked: (label) ->
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)
+ selectedLabel = label.title
+
Issues.filterResults $dropdown.closest('form')
else if $dropdown.hasClass 'js-filter-submit'
$dropdown.closest('form').submit()
diff --git a/app/assets/javascripts/milestone_select.js.coffee b/app/assets/javascripts/milestone_select.js.coffee
index e17a1adb648..1432f261cdd 100644
--- a/app/assets/javascripts/milestone_select.js.coffee
+++ b/app/assets/javascripts/milestone_select.js.coffee
@@ -7,6 +7,7 @@ class @MilestoneSelect
selectedMilestone = $dropdown.data('selected')
showNo = $dropdown.data('show-no')
showAny = $dropdown.data('show-any')
+ showUpcoming = $dropdown.data('show-upcoming')
useId = $dropdown.data('use-id')
defaultLabel = $dropdown.data('default-label')
@@ -15,22 +16,32 @@ class @MilestoneSelect
$.ajax(
url: milestonesUrl
).done (data) ->
+ extraOptions = []
+ if showAny
+ extraOptions.push(
+ id: 0
+ name: ''
+ title: 'Any Milestone'
+ )
+
if showNo
- data.unshift(
- id: '0'
+ extraOptions.push(
+ id: -1
+ name: 'No Milestone'
title: 'No Milestone'
)
- if showAny
- data.unshift(
- isAny: true
- title: 'Any Milestone'
+ if showUpcoming
+ extraOptions.push(
+ id: -2
+ name: '#upcoming'
+ title: 'Upcoming'
)
- if data.length > 2
- data.splice 2, 0, 'divider'
+ if extraOptions.length > 2
+ extraOptions.push 'divider'
- callback(data)
+ callback(extraOptions.concat(data))
filterable: true
search:
fields: ['title']
@@ -45,21 +56,49 @@ class @MilestoneSelect
milestone.title
id: (milestone) ->
if !useId
- if !milestone.isAny?
- milestone.title
- else
- ''
+ milestone.name
else
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'
+ milestone.name is selectedMilestone
+ hidden: ->
+ $selectbox.hide()
+ $value.show()
+ clicked: (selected) ->
+ 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()
+ if $dropdown.hasClass('js-filter-submit')
+ if selected.name?
+ selectedMilestone = selected.name
+ else if selected.title?
+ selectedMilestone = selected.title
+ else
+ selectedMilestone = ''
+ $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)
)
diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee
index 84193400890..dcf7d14e41e 100644
--- a/app/assets/javascripts/users_select.js.coffee
+++ b/app/assets/javascripts/users_select.js.coffee
@@ -62,12 +62,20 @@ class @UsersSelect
selected.name
else
defaultLabel
- clicked: ->
+
+ inputId: 'issue_assignee_id'
+
+ hidden: (e) ->
+ $selectbox.hide()
+ $value.show()
+
+ clicked: (user) ->
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)
+ selectedId = user.id
Issues.filterResults $dropdown.closest('form')
else if $dropdown.hasClass 'js-filter-submit'
$dropdown.closest('form').submit()
diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index 0998b191c07..f6b431b7703 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -25,7 +25,7 @@ class Projects::MilestonesController < Projects::ApplicationController
@milestones = @milestones.page(params[:page]).per(PER_PAGE)
end
format.json do
- render json: @milestones
+ render json: @milestones.to_json(methods: :name)
end
end
end
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 046286dd9e1..f1df6832bf6 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -243,7 +243,7 @@ class IssuableFinder
end
def filter_by_upcoming_milestone?
- params[:milestone_title] == '#upcoming'
+ params[:milestone_title] == Milestone::Upcoming.name
end
def by_milestone(items)
@@ -252,7 +252,7 @@ class IssuableFinder
items = items.where(milestone_id: [-1, nil])
elsif filter_by_upcoming_milestone?
upcoming = Milestone.where(project_id: projects).upcoming
- items = items.joins(:milestone).where(milestones: { title: upcoming.title })
+ items = items.joins(:milestone).where(milestones: { title: upcoming.try(:title) })
else
items = items.joins(:milestone).where(milestones: { title: params[:milestone_title] })
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 81df2094392..2d366c80575 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -37,6 +37,14 @@ module IssuablesHelper
end
end
+ def milestone_dropdown_label(milestone_title, default_label = "Milestone")
+ if milestone_title == Milestone::Upcoming.name
+ milestone_title = Milestone::Upcoming.title
+ end
+
+ h(milestone_title.presence || default_label)
+ end
+
private
def sidebar_gutter_collapsed?
diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb
index 97bd79af083..da7c265a371 100644
--- a/app/models/global_milestone.rb
+++ b/app/models/global_milestone.rb
@@ -14,6 +14,7 @@ class GlobalMilestone
def initialize(title, milestones)
@title = title
+ @name = title
@milestones = milestones
end
diff --git a/app/views/shared/issuable/_milestone_dropdown.html.haml b/app/views/shared/issuable/_milestone_dropdown.html.haml
index 0434506c8d7..e52d2e39e6b 100644
--- a/app/views/shared/issuable/_milestone_dropdown.html.haml
+++ b/app/views/shared/issuable/_milestone_dropdown.html.haml
@@ -1,7 +1,7 @@
- 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",
- 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
+= dropdown_tag(milestone_dropdown_label(params[:milestone_title]), options: { title: "Filter by milestone", toggle_class: 'js-milestone-select js-filter-submit', filter: true, dropdown_class: "dropdown-menu-selectable",
+ placeholder: "Search milestones", footer_content: @project.present?, data: { show_no: true, show_any: true, show_upcoming: 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
- if can? current_user, :admin_milestone, @project
diff --git a/spec/features/issues/filter_by_milestone_spec.rb b/spec/features/issues/filter_by_milestone_spec.rb
index f6e33f651c4..99445185893 100644
--- a/spec/features/issues/filter_by_milestone_spec.rb
+++ b/spec/features/issues/filter_by_milestone_spec.rb
@@ -11,7 +11,41 @@ feature 'Issue filtering by Milestone', feature: true do
visit_issues(project)
filter_by_milestone(Milestone::None.title)
- expect(page).to have_css('.issue .title', count: 1)
+ expect(page).to have_css('.issue', count: 1)
+ end
+
+ context 'filters by upcoming milestone', js: true do
+ it 'should not show issues with no expiry' do
+ create(:issue, project: project)
+ create(:issue, project: project, milestone: milestone)
+
+ visit_issues(project)
+ filter_by_milestone(Milestone::Upcoming.title)
+
+ expect(page).to have_css('.issue', count: 0)
+ end
+
+ it 'should show issues in future' do
+ milestone = create(:milestone, project: project, due_date: Date.tomorrow)
+ create(:issue, project: project)
+ create(:issue, project: project, milestone: milestone)
+
+ visit_issues(project)
+ filter_by_milestone(Milestone::Upcoming.title)
+
+ expect(page).to have_css('.issue', count: 1)
+ end
+
+ it 'should not show issues in past' do
+ milestone = create(:milestone, project: project, due_date: Date.yesterday)
+ create(:issue, project: project)
+ create(:issue, project: project, milestone: milestone)
+
+ visit_issues(project)
+ filter_by_milestone(Milestone::Upcoming.title)
+
+ expect(page).to have_css('.issue', count: 0)
+ end
end
scenario 'filters by a specific Milestone', js: true do
@@ -21,7 +55,7 @@ feature 'Issue filtering by Milestone', feature: true do
visit_issues(project)
filter_by_milestone(milestone.title)
- expect(page).to have_css('.issue .title', count: 1)
+ expect(page).to have_css('.issue', count: 1)
end
def visit_issues(project)
@@ -30,8 +64,6 @@ 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
- sleep 1
+ find(".milestone-filter .dropdown-content a", text: title).click
end
end
diff --git a/spec/features/merge_requests/filter_by_milestone_spec.rb b/spec/features/merge_requests/filter_by_milestone_spec.rb
index b76e4c74c79..c57ab5f3b03 100644
--- a/spec/features/merge_requests/filter_by_milestone_spec.rb
+++ b/spec/features/merge_requests/filter_by_milestone_spec.rb
@@ -11,7 +11,41 @@ feature 'Merge Request filtering by Milestone', feature: true do
visit_merge_requests(project)
filter_by_milestone(Milestone::None.title)
- expect(page).to have_css('.merge-request-title', count: 1)
+ expect(page).to have_css('.merge-request', count: 1)
+ end
+
+ context 'filters by upcoming milestone', js: true do
+ it 'should not show issues with no expiry' do
+ create(:merge_request, :with_diffs, source_project: project)
+ create(:merge_request, :simple, source_project: project, milestone: milestone)
+
+ visit_merge_requests(project)
+ filter_by_milestone(Milestone::Upcoming.title)
+
+ expect(page).to have_css('.merge-request', count: 0)
+ end
+
+ it 'should show issues in future' do
+ milestone = create(:milestone, project: project, due_date: Date.tomorrow)
+ create(:merge_request, :with_diffs, source_project: project)
+ create(:merge_request, :simple, source_project: project, milestone: milestone)
+
+ visit_merge_requests(project)
+ filter_by_milestone(Milestone::Upcoming.title)
+
+ expect(page).to have_css('.merge-request', count: 1)
+ end
+
+ it 'should not show issues in past' do
+ milestone = create(:milestone, project: project, due_date: Date.yesterday)
+ create(:merge_request, :with_diffs, source_project: project)
+ create(:merge_request, :simple, source_project: project, milestone: milestone)
+
+ visit_merge_requests(project)
+ filter_by_milestone(Milestone::Upcoming.title)
+
+ expect(page).to have_css('.merge-request', count: 0)
+ end
end
scenario 'filters by a specific Milestone', js: true do
@@ -21,7 +55,7 @@ feature 'Merge Request filtering by Milestone', feature: true do
visit_merge_requests(project)
filter_by_milestone(milestone.title)
- expect(page).to have_css('.merge-request-title', count: 1)
+ expect(page).to have_css('.merge-request', count: 1)
end
def visit_merge_requests(project)