diff options
author | Rémy Coutable <remy@rymai.me> | 2016-03-30 06:49:04 +0000 |
---|---|---|
committer | Rémy Coutable <remy@rymai.me> | 2016-03-30 09:26:54 +0200 |
commit | 07a4aacafce518dcdcec9a12d76df3c310af3e93 (patch) | |
tree | ce6021563933397bdf6c9aa04dfa8e72b8ca7991 | |
parent | 966ade1d7509d7acaad3c59c5d6cd23c560d72bd (diff) | |
download | gitlab-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-- | CHANGELOG | 2 | ||||
-rw-r--r-- | app/assets/javascripts/gl_dropdown.js.coffee | 29 | ||||
-rw-r--r-- | app/assets/javascripts/issues.js.coffee | 10 | ||||
-rw-r--r-- | app/assets/javascripts/labels_select.js.coffee | 4 | ||||
-rw-r--r-- | app/assets/javascripts/milestone_select.js.coffee | 83 | ||||
-rw-r--r-- | app/assets/javascripts/users_select.js.coffee | 10 | ||||
-rw-r--r-- | app/controllers/projects/milestones_controller.rb | 2 | ||||
-rw-r--r-- | app/finders/issuable_finder.rb | 4 | ||||
-rw-r--r-- | app/helpers/issuables_helper.rb | 8 | ||||
-rw-r--r-- | app/models/global_milestone.rb | 1 | ||||
-rw-r--r-- | app/views/shared/issuable/_milestone_dropdown.html.haml | 4 | ||||
-rw-r--r-- | spec/features/issues/filter_by_milestone_spec.rb | 42 | ||||
-rw-r--r-- | spec/features/merge_requests/filter_by_milestone_spec.rb | 38 |
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) |