From 19c9ee4752717fb25529ef8b4dba7bc29616a076 Mon Sep 17 00:00:00 2001 From: Phil Hughes <me@iamphill.com> Date: Tue, 30 Aug 2016 10:32:19 +0100 Subject: [PATCH] Added search for all lists on issue boards Closes #21139 --- .../javascripts/boards/boards_bundle.js.es6 | 7 ++ .../boards/components/board.js.es6 | 10 +-- .../javascripts/boards/models/list.js.es6 | 4 -- .../boards/stores/boards_store.js.es6 | 3 +- app/assets/stylesheets/pages/boards.scss | 45 +++---------- .../boards/components/_board.html.haml | 5 -- app/views/shared/issuable/_filter.html.haml | 21 +++--- spec/features/boards/boards_spec.rb | 65 +++++++++++-------- spec/javascripts/boards/list_spec.js.es6 | 9 --- 9 files changed, 71 insertions(+), 98 deletions(-) diff --git a/app/assets/javascripts/boards/boards_bundle.js.es6 b/app/assets/javascripts/boards/boards_bundle.js.es6 index a612cf0f1ae..91c12570e09 100644 --- a/app/assets/javascripts/boards/boards_bundle.js.es6 +++ b/app/assets/javascripts/boards/boards_bundle.js.es6 @@ -54,4 +54,11 @@ $(() => { }); } }); + + gl.IssueBoardsSearch = new Vue({ + el: '#js-boards-seach', + data: { + filters: Store.state.filters + } + }); }); diff --git a/app/assets/javascripts/boards/components/board.js.es6 b/app/assets/javascripts/boards/components/board.js.es6 index d7f4107cb02..2e3a8f6870b 100644 --- a/app/assets/javascripts/boards/components/board.js.es6 +++ b/app/assets/javascripts/boards/components/board.js.es6 @@ -21,15 +21,10 @@ }, data () { return { - query: '', filters: Store.state.filters }; }, watch: { - query () { - this.list.filters = this.getFilterData(); - this.list.getIssues(true); - }, filters: { handler () { this.list.page = 1; @@ -40,10 +35,7 @@ }, methods: { getFilterData () { - const filters = this.filters; - let queryData = { search: this.query }; - - Object.keys(filters).forEach((key) => { queryData[key] = filters[key]; }); + Object.keys(this.filters).forEach((key) => { queryData[key] = this.filters[key]; }); return queryData; } diff --git a/app/assets/javascripts/boards/models/list.js.es6 b/app/assets/javascripts/boards/models/list.js.es6 index be2b8c568a8..816fa49516c 100644 --- a/app/assets/javascripts/boards/models/list.js.es6 +++ b/app/assets/javascripts/boards/models/list.js.es6 @@ -58,10 +58,6 @@ class List { } } - canSearch () { - return this.type === 'backlog'; - } - getIssues (emptyIssues = true) { const filters = this.filters; let data = { page: this.page }; diff --git a/app/assets/javascripts/boards/stores/boards_store.js.es6 b/app/assets/javascripts/boards/stores/boards_store.js.es6 index 18f26a1f911..bd07ee0c161 100644 --- a/app/assets/javascripts/boards/stores/boards_store.js.es6 +++ b/app/assets/javascripts/boards/stores/boards_store.js.es6 @@ -15,7 +15,8 @@ author_id: gl.utils.getParameterValues('author_id')[0], assignee_id: gl.utils.getParameterValues('assignee_id')[0], milestone_title: gl.utils.getParameterValues('milestone_title')[0], - label_name: gl.utils.getParameterValues('label_name[]') + label_name: gl.utils.getParameterValues('label_name[]'), + search: '' }; }, addList (listObj) { diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss index 9ac4d801ac4..d91558bc672 100644 --- a/app/assets/stylesheets/pages/boards.scss +++ b/app/assets/stylesheets/pages/boards.scss @@ -10,7 +10,7 @@ .is-dragging { // Important because plugin sets inline CSS opacity: 1!important; - + * { // !important to make sure no style can override this when dragging cursor: -webkit-grabbing!important; @@ -160,40 +160,6 @@ border-bottom: 1px solid $border-color; } -.board-search-container { - position: relative; - background-color: #fff; - - .form-control { - padding-right: 30px; - } -} - -.board-search-icon, -.board-search-clear-btn { - position: absolute; - right: $gl-padding + 10px; - top: 50%; - margin-top: -7px; - font-size: 14px; -} - -.board-search-icon { - color: $gl-placeholder-color; -} - -.board-search-clear-btn { - padding: 0; - line-height: 1; - background: transparent; - border: 0; - outline: 0; - - &:hover { - color: $gl-link-color; - } -} - .board-delete { margin-right: 10px; padding: 0; @@ -304,3 +270,12 @@ margin-right: 8px; font-weight: 500; } + +.issue-boards-search { + width: 335px; + + .form-control { + display: inline-block; + width: 210px; + } +} diff --git a/app/views/projects/boards/components/_board.html.haml b/app/views/projects/boards/components/_board.html.haml index de53a298f84..6b4bfe0c354 100644 --- a/app/views/projects/boards/components/_board.html.haml +++ b/app/views/projects/boards/components/_board.html.haml @@ -21,11 +21,6 @@ %button.board-delete.has-tooltip.pull-right{ type: "button", title: "Delete list", "aria-label" => "Delete list", data: { placement: "bottom" }, "@click.stop" => "deleteBoard" } = icon("trash") = icon("spinner spin", class: "board-header-loading-spinner pull-right", "v-show" => "list.loadingMore") - .board-inner-container.board-search-container{ "v-if" => "list.canSearch()" } - %input.form-control{ type: "text", placeholder: "Search issues", "v-model" => "query", "debounce" => "250" } - = icon("search", class: "board-search-icon", "v-show" => "!query") - %button.board-search-clear-btn{ type: "button", role: "button", "aria-label" => "Clear search", "@click" => "query = ''", "v-show" => "query" } - = icon("times", class: "board-search-clear") %board-list{ "inline-template" => true, "v-if" => "list.type !== 'blank'", ":list" => "list", diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml index 4f8ea7e7cef..0f4f744a71f 100644 --- a/app/views/shared/issuable/_filter.html.haml +++ b/app/views/shared/issuable/_filter.html.haml @@ -27,15 +27,18 @@ = render "shared/issuable/label_dropdown" .pull-right - - if controller.controller_name == 'boards' && can?(current_user, :admin_list, @project) - .dropdown - %button.btn.btn-create.js-new-board-list{ type: "button", data: { toggle: "dropdown", labels: labels_filter_path, project_id: @project.try(:id) } } - Create new list - .dropdown-menu.dropdown-menu-paging.dropdown-menu-align-right.dropdown-menu-issues-board-new.dropdown-menu-selectable - = render partial: "shared/issuable/label_page_default", locals: { show_footer: true, show_create: true, show_boards_content: true, title: "Create a new list" } - - if can?(current_user, :admin_label, @project) - = render partial: "shared/issuable/label_page_create" - = dropdown_loading + - if controller.controller_name == 'boards' + #js-boards-seach.issue-boards-search + %input.pull-left.form-control{ type: "search", placeholder: "Filter by name...", "v-model" => "filters.search", "debounce" => "250" } + - if can?(current_user, :admin_list, @project) + .dropdown.pull-right + %button.btn.btn-create.js-new-board-list{ type: "button", data: { toggle: "dropdown", labels: labels_filter_path, project_id: @project.try(:id) } } + Create new list + .dropdown-menu.dropdown-menu-paging.dropdown-menu-align-right.dropdown-menu-issues-board-new.dropdown-menu-selectable + = render partial: "shared/issuable/label_page_default", locals: { show_footer: true, show_create: true, show_boards_content: true, title: "Create a new list" } + - if can?(current_user, :admin_label, @project) + = render partial: "shared/issuable/label_page_create" + = dropdown_loading - else = render 'shared/sort_dropdown' diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index 5d777895542..55e5dc15428 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -110,6 +110,45 @@ describe 'Issue Boards', feature: true, js: true do end end + it 'search backlog list' do + page.within('#js-boards-seach') do + find('.form-control').set(issue1.title) + end + + wait_for_vue_resource + + expect(find('.board:nth-child(1)')).to have_selector('.card', count: 1) + expect(find('.board:nth-child(2)')).to have_selector('.card', count: 0) + expect(find('.board:nth-child(3)')).to have_selector('.card', count: 0) + expect(find('.board:nth-child(4)')).to have_selector('.card', count: 0) + end + + it 'search done list' do + page.within('#js-boards-seach') do + find('.form-control').set(issue8.title) + end + + wait_for_vue_resource + + expect(find('.board:nth-child(1)')).to have_selector('.card', count: 0) + expect(find('.board:nth-child(2)')).to have_selector('.card', count: 0) + expect(find('.board:nth-child(3)')).to have_selector('.card', count: 0) + expect(find('.board:nth-child(4)')).to have_selector('.card', count: 1) + end + + it 'search list' do + page.within('#js-boards-seach') do + find('.form-control').set(issue5.title) + end + + wait_for_vue_resource + + expect(find('.board:nth-child(1)')).to have_selector('.card', count: 0) + expect(find('.board:nth-child(2)')).to have_selector('.card', count: 1) + expect(find('.board:nth-child(3)')).to have_selector('.card', count: 0) + expect(find('.board:nth-child(4)')).to have_selector('.card', count: 0) + end + it 'allows user to delete board' do page.within(find('.board:nth-child(2)')) do find('.board-delete').click @@ -162,32 +201,6 @@ describe 'Issue Boards', feature: true, js: true do end end - it 'is searchable' do - page.within(find('.board', match: :first)) do - find('.form-control').set issue1.title - - wait_for_vue_resource(spinner: false) - - expect(page).to have_selector('.card', count: 1) - end - end - - it 'clears search' do - page.within(find('.board', match: :first)) do - find('.form-control').set issue1.title - - expect(page).to have_selector('.card', count: 1) - - find('.board-search-clear-btn').click - end - - wait_for_vue_resource - - page.within(find('.board', match: :first)) do - expect(page).to have_selector('.card', count: 6) - end - end - it 'moves issue from backlog into list' do drag_to(list_to_index: 1) diff --git a/spec/javascripts/boards/list_spec.js.es6 b/spec/javascripts/boards/list_spec.js.es6 index c206b794442..1688b996162 100644 --- a/spec/javascripts/boards/list_spec.js.es6 +++ b/spec/javascripts/boards/list_spec.js.es6 @@ -60,15 +60,6 @@ describe('List model', () => { }, 0); }); - it('can\'t search when not backlog', () => { - expect(list.canSearch()).toBe(false); - }); - - it('can search when backlog', () => { - list.type = 'backlog'; - expect(list.canSearch()).toBe(true); - }); - it('gets issue from list', (done) => { setTimeout(() => { const issue = list.findIssue(1); -- GitLab