summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js56
-rw-r--r--app/assets/stylesheets/framework/nav.scss27
-rw-r--r--app/views/shared/issuable/_nav.html.haml19
-rw-r--r--changelogs/unreleased/auto-search-when-state-changed.yml4
-rw-r--r--spec/features/issues/filtered_search/filter_issues_spec.rb8
-rw-r--r--spec/features/merge_requests/filter_merge_requests_spec.rb16
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