diff options
6 files changed, 103 insertions, 27 deletions
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js index 3be889c684b..4f0bba81e26 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_manager.js +++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js @@ -77,6 +77,41 @@ class FilteredSearchManager { } } + bindStateEvents() { + this.stateFilters = document.querySelector('.container-fluid .issues-state-filters'); + + if (this.stateFilters) { + this.searchStateWrapper = this.searchState.bind(this); + + this.stateFilters.querySelector('.state-opened') + .addEventListener('click', this.searchStateWrapper); + this.stateFilters.querySelector('.state-closed') + .addEventListener('click', this.searchStateWrapper); + this.stateFilters.querySelector('.state-all') + .addEventListener('click', this.searchStateWrapper); + + this.mergedState = this.stateFilters.querySelector('.state-merged'); + if (this.mergedState) { + this.mergedState.addEventListener('click', this.searchStateWrapper); + } + } + } + + unbindStateEvents() { + if (this.stateFilters) { + this.stateFilters.querySelector('.state-opened') + .removeEventListener('click', this.searchStateWrapper); + this.stateFilters.querySelector('.state-closed') + .removeEventListener('click', this.searchStateWrapper); + this.stateFilters.querySelector('.state-all') + .removeEventListener('click', this.searchStateWrapper); + + if (this.mergedState) { + this.mergedState.removeEventListener('click', this.searchStateWrapper); + } + } + } + bindEvents() { this.handleFormSubmit = this.handleFormSubmit.bind(this); this.setDropdownWrapper = this.dropdownManager.setDropdown.bind(this.dropdownManager); @@ -114,6 +149,8 @@ class FilteredSearchManager { document.addEventListener('click', this.removeInputContainerFocusWrapper); document.addEventListener('keydown', this.removeSelectedTokenKeydownWrapper); eventHub.$on('recentSearchesItemSelected', this.onrecentSearchesItemSelectedWrapper); + + this.bindStateEvents(); } unbindEvents() { @@ -136,6 +173,8 @@ class FilteredSearchManager { document.removeEventListener('click', this.removeInputContainerFocusWrapper); document.removeEventListener('keydown', this.removeSelectedTokenKeydownWrapper); eventHub.$off('recentSearchesItemSelected', this.onrecentSearchesItemSelectedWrapper); + + this.unbindStateEvents(); } checkForBackspace(e) { @@ -459,7 +498,20 @@ class FilteredSearchManager { } } - search() { + searchState(e) { + const target = e.currentTarget; + + // remove focus outline after click + target.blur(); + + // return class name that has a prefix of `state-` + const stateClassName = [].find.call(target.classList, name => name.match(/(state-)(\w+)/g)); + const state = stateClassName.replace('state-', ''); + + this.search(state); + } + + search(state = null) { const paths = []; const searchQuery = gl.DropdownUtils.getSearchQuery(); @@ -467,7 +519,7 @@ class FilteredSearchManager { const { tokens, searchToken } = this.tokenizer.processTokens(searchQuery, this.filteredSearchTokenKeys.getKeys()); - const currentState = gl.utils.getParameterByName('state') || 'opened'; + const currentState = state || gl.utils.getParameterByName('state') || 'opened'; paths.push(`state=${currentState}`); tokens.forEach((token) => { diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 28b2a7cfacd..3787ef370b2 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -45,7 +45,8 @@ li { display: flex; - a { + a, + .btn-link { padding: $gl-btn-padding; padding-bottom: 11px; font-size: 14px; @@ -67,7 +68,29 @@ } } - &.active a { + .btn-link { + padding-top: 16px; + padding-left: 15px; + padding-right: 15px; + border-left: none; + border-right: none; + border-top: none; + border-radius: 0; + + &:hover, + &:active, + &:focus { + background-color: transparent; + } + + &:active { + outline: 0; + box-shadow: none; + } + } + + &.active a, + &.active .btn-link { border-bottom: 2px solid $link-underline-blue; color: $black; font-weight: 600; diff --git a/app/views/shared/issuable/_nav.html.haml b/app/views/shared/issuable/_nav.html.haml index ad995cbe962..a530c0e7f5a 100644 --- a/app/views/shared/issuable/_nav.html.haml +++ b/app/views/shared/issuable/_nav.html.haml @@ -1,25 +1,24 @@ - type = local_assigns.fetch(:type, :issues) - page_context_word = type.to_s.humanize(capitalize: false) - issuables = @issues || @merge_requests +- closed_title = 'Filter by issues that are currently closed.' %ul.nav-links.issues-state-filters %li{ class: active_when(params[:state] == 'opened') }> - = link_to page_filter_path(state: 'opened', label: true), id: 'state-opened', title: "Filter by #{page_context_word} that are currently opened." do + %button.btn.btn-link.state-opened{ id: 'state-opened', title: "Filter by #{page_context_word} that are currently opened.", type: 'button' } #{issuables_state_counter_text(type, :opened)} - if type == :merge_requests %li{ class: active_when(params[:state] == 'merged') }> - = link_to page_filter_path(state: 'merged', label: true), id: 'state-merged', title: 'Filter by merge requests that are currently merged.' do + %button.btn.btn-link.state-merged{ id: 'state-merged', title: 'Filter by merge requests that are currently merged.', type: 'button' } #{issuables_state_counter_text(type, :merged)} - %li{ class: active_when(params[:state] == 'closed') }> - = link_to page_filter_path(state: 'closed', label: true), id: 'state-closed', title: 'Filter by merge requests that are currently closed and unmerged.' do - #{issuables_state_counter_text(type, :closed)} - - else - %li{ class: active_when(params[:state] == 'closed') }> - = link_to page_filter_path(state: 'closed', label: true), id: 'state-all', title: 'Filter by issues that are currently closed.' do - #{issuables_state_counter_text(type, :closed)} + - closed_title = 'Filter by merge requests that are currently closed and unmerged.' + + %li{ class: active_when(params[:state] == 'closed') }> + %button.btn.btn-link.state-closed{ id: 'state-closed', title: closed_title, type: 'button' } + #{issuables_state_counter_text(type, :closed)} %li{ class: active_when(params[:state] == 'all') }> - = link_to page_filter_path(state: 'all', label: true), id: 'state-all', title: "Show all #{page_context_word}." do + %button.btn.btn-link.state-all{ id: 'state-all', title: "Show all #{page_context_word}.", type: 'button' } #{issuables_state_counter_text(type, :all)} diff --git a/changelogs/unreleased/auto-search-when-state-changed.yml b/changelogs/unreleased/auto-search-when-state-changed.yml new file mode 100644 index 00000000000..2723beb8600 --- /dev/null +++ b/changelogs/unreleased/auto-search-when-state-changed.yml @@ -0,0 +1,4 @@ +--- +title: Perform filtered search when state tab is changed +merge_request: +author: diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb index e5e4ba06b5a..36f8369c142 100644 --- a/spec/features/issues/filtered_search/filter_issues_spec.rb +++ b/spec/features/issues/filtered_search/filter_issues_spec.rb @@ -777,17 +777,17 @@ describe 'Filter issues', js: true, feature: true do end it 'open state' do - find('.issues-state-filters a', text: 'Closed').click + find('.issues-state-filters .state-closed').click wait_for_requests - find('.issues-state-filters a', text: 'Open').click + find('.issues-state-filters .state-opened').click wait_for_requests expect(page).to have_selector('.issues-list .issue', count: 4) end it 'closed state' do - find('.issues-state-filters a', text: 'Closed').click + find('.issues-state-filters .state-closed').click wait_for_requests expect(page).to have_selector('.issues-list .issue', count: 1) @@ -795,7 +795,7 @@ describe 'Filter issues', js: true, feature: true do end it 'all state' do - find('.issues-state-filters a', text: 'All').click + find('.issues-state-filters .state-all').click wait_for_requests expect(page).to have_selector('.issues-list .issue', count: 5) diff --git a/spec/features/merge_requests/filter_merge_requests_spec.rb b/spec/features/merge_requests/filter_merge_requests_spec.rb index 1e26b3d601e..5a13189c5bf 100644 --- a/spec/features/merge_requests/filter_merge_requests_spec.rb +++ b/spec/features/merge_requests/filter_merge_requests_spec.rb @@ -40,13 +40,13 @@ describe 'Filter merge requests', feature: true do end it 'does not change when closed link is clicked' do - find('.issues-state-filters a', text: "Closed").click + find('.issues-state-filters .state-closed').click expect_assignee_visual_tokens() end it 'does not change when all link is clicked' do - find('.issues-state-filters a', text: "All").click + find('.issues-state-filters .state-all').click expect_assignee_visual_tokens() end @@ -73,13 +73,13 @@ describe 'Filter merge requests', feature: true do end it 'does not change when closed link is clicked' do - find('.issues-state-filters a', text: "Closed").click + find('.issues-state-filters .state-closed').click expect_milestone_visual_tokens() end it 'does not change when all link is clicked' do - find('.issues-state-filters a', text: "All").click + find('.issues-state-filters .state-all').click expect_milestone_visual_tokens() end @@ -142,11 +142,9 @@ describe 'Filter merge requests', feature: true do expect_tokens([{ name: 'assignee', value: "@#{user.username}" }]) expect_filtered_search_input_empty - input_filtered_search_keys("label:~#{label.title} ") + input_filtered_search_keys("label:~#{label.title}") expect_mr_list_count(1) - - find("#state-opened[href=\"#{URI.parse(current_url).path}?assignee_username=#{user.username}&label_name%5B%5D=#{label.title}&scope=all&state=opened\"]") end context 'assignee and label', js: true do @@ -163,13 +161,13 @@ describe 'Filter merge requests', feature: true do end it 'does not change when closed link is clicked' do - find('.issues-state-filters a', text: "Closed").click + find('.issues-state-filters .state-closed').click expect_assignee_label_visual_tokens() end it 'does not change when all link is clicked' do - find('.issues-state-filters a', text: "All").click + find('.issues-state-filters .state-all').click expect_assignee_label_visual_tokens() end |