From 92fc135f56a2b5d413acc243049710d628481214 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 22 Mar 2023 19:57:29 +0530 Subject: [PATCH] Used Filtered search bar for context commits --- .../add_context_commits_modal_wrapper.vue | 132 ++++++++++++++---- .../components/token.vue | 28 ++++ .../store/actions.js | 28 +++- .../add_context_commits_modal/store/index.js | 2 + .../add_context_commits_modal/store/state.js | 1 + app/assets/stylesheets/pages/commits.scss | 15 ++ app/finders/context_commits_finder.rb | 8 +- app/models/repository.rb | 2 +- locale/gitlab.pot | 15 +- spec/finders/context_commits_finder_spec.rb | 21 +-- .../add_context_commits_modal_spec.js.snap | 11 +- .../add_context_commits_modal_spec.js | 33 +++-- spec/models/repository_spec.rb | 9 ++ 13 files changed, 248 insertions(+), 57 deletions(-) create mode 100644 app/assets/javascripts/add_context_commits_modal/components/token.vue diff --git a/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue b/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue index c66b595ffdc1c1..a5f8f369604dd2 100644 --- a/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue +++ b/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue @@ -1,10 +1,15 @@ + + diff --git a/app/assets/javascripts/add_context_commits_modal/store/actions.js b/app/assets/javascripts/add_context_commits_modal/store/actions.js index de9c7488ace7c0..f085b0d0e5eebd 100644 --- a/app/assets/javascripts/add_context_commits_modal/store/actions.js +++ b/app/assets/javascripts/add_context_commits_modal/store/actions.js @@ -1,8 +1,11 @@ import _ from 'lodash'; +import * as Sentry from '@sentry/browser'; import Api from '~/api'; import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { s__ } from '~/locale'; +import { joinPaths } from '~/lib/utils/url_utility'; +import { ACTIVE_AND_BLOCKED_USER_STATES } from '~/users_select/constants'; import * as types from './mutation_types'; export const setBaseConfig = ({ commit }, options) => { @@ -11,14 +14,14 @@ export const setBaseConfig = ({ commit }, options) => { export const setTabIndex = ({ commit }, tabIndex) => commit(types.SET_TABINDEX, tabIndex); -export const searchCommits = ({ dispatch, commit, state }, searchText) => { +export const searchCommits = ({ dispatch, commit, state }, search = {}) => { commit(types.FETCH_COMMITS); let params = {}; - if (searchText) { + if (search) { params = { params: { - search: searchText, + ...search, per_page: 40, }, }; @@ -37,7 +40,7 @@ export const searchCommits = ({ dispatch, commit, state }, searchText) => { } return c; }); - if (!searchText) { + if (!search) { dispatch('setCommits', { commits: [...commits, ...state.contextCommits] }); } else { dispatch('setCommits', { commits }); @@ -131,6 +134,23 @@ export const setSelectedCommits = ({ commit }, selected) => { commit(types.SET_SELECTED_COMMITS, selectedCommits); }; +export const fetchAuthors = ({ dispatch, state }, author = null) => { + const { projectId } = state; + return axios + .get(joinPaths(gon.relative_url_root || '', '/-/autocomplete/users.json'), { + params: { + project_id: projectId, + states: ACTIVE_AND_BLOCKED_USER_STATES, + search: author, + }, + }) + .then(({ data }) => data) + .catch((error) => { + Sentry.captureException(error); + dispatch('receiveAuthorsError'); + }); +}; + export const setSearchText = ({ commit }, searchText) => commit(types.SET_SEARCH_TEXT, searchText); export const setToRemoveCommits = ({ commit }, data) => commit(types.SET_TO_REMOVE_COMMITS, data); diff --git a/app/assets/javascripts/add_context_commits_modal/store/index.js b/app/assets/javascripts/add_context_commits_modal/store/index.js index 0bf3441379b4ed..560834a26aefe1 100644 --- a/app/assets/javascripts/add_context_commits_modal/store/index.js +++ b/app/assets/javascripts/add_context_commits_modal/store/index.js @@ -1,5 +1,6 @@ import Vue from 'vue'; import Vuex from 'vuex'; +import filters from '~/vue_shared/components/filtered_search_bar/store/modules/filters'; import * as actions from './actions'; import mutations from './mutations'; import state from './state'; @@ -12,4 +13,5 @@ export default () => state: state(), actions, mutations, + modules: { filters }, }); diff --git a/app/assets/javascripts/add_context_commits_modal/store/state.js b/app/assets/javascripts/add_context_commits_modal/store/state.js index 37239adccbbf58..fed3148bc9e4c4 100644 --- a/app/assets/javascripts/add_context_commits_modal/store/state.js +++ b/app/assets/javascripts/add_context_commits_modal/store/state.js @@ -1,4 +1,5 @@ export default () => ({ + projectId: '', contextCommitsPath: '', tabIndex: 0, isLoadingCommits: false, diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss index 225c32c19892ce..83f51588f434d9 100644 --- a/app/assets/stylesheets/pages/commits.scss +++ b/app/assets/stylesheets/pages/commits.scss @@ -332,3 +332,18 @@ height: 100%; } } + +.add-review-item-modal { + .modal-content { + position: absolute; + top: 5%; + } + + .title-hint-text { + color: $gl-text-color-secondary; + } + + .gl-filtered-search-suggestion-list.dropdown-menu { + width: $gl-max-dropdown-max-height; + } +} diff --git a/app/finders/context_commits_finder.rb b/app/finders/context_commits_finder.rb index 4a45817cc61096..a186ca92c7b26c 100644 --- a/app/finders/context_commits_finder.rb +++ b/app/finders/context_commits_finder.rb @@ -21,20 +21,24 @@ def execute attr_reader :project, :merge_request, :search, :author, :committed_before, :committed_after, :limit def init_collection - if search.present? + if search_params_present? search_commits else project.repository.commits(merge_request.target_branch, { limit: limit }) end end + def search_params_present? + [search, author, committed_before, committed_after].map(&:present?).any? + end + def filter_existing_commits(commits) commits.select! { |commit| already_included_ids.exclude?(commit.id) } commits end def search_commits - key = search.strip + key = search&.strip commits = [] if Commit.valid_hash?(key) mr_existing_commits_ids = merge_request.commits.map(&:id) diff --git a/app/models/repository.rb b/app/models/repository.rb index 587b71315c2825..b4a0eaf0324e1f 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -199,7 +199,7 @@ def find_commits_by_message(query, ref = nil, path = nil, limit = 1000, offset = def list_commits_by(query, ref, author: nil, before: nil, after: nil, limit: 1000) return [] unless exists? return [] unless has_visible_content? - return [] unless query.present? && ref.present? + return [] unless ref.present? commits = raw_repository.list_commits_by( query, ref, author: author, before: before, after: after, limit: limit).map do |c| diff --git a/locale/gitlab.pot b/locale/gitlab.pot index a794c64a788fa2..61cc4de0ef3f1d 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -10547,6 +10547,12 @@ msgstr "" msgid "Committed by" msgstr "" +msgid "Committed-after" +msgstr "" + +msgid "Committed-before" +msgstr "" + msgid "CommonJS module" msgstr "" @@ -38527,9 +38533,6 @@ msgstr "" msgid "Search by author" msgstr "" -msgid "Search by commit title or SHA" -msgstr "" - msgid "Search by message" msgstr "" @@ -38575,6 +38578,9 @@ msgstr "" msgid "Search or create tag" msgstr "" +msgid "Search or filter commits" +msgstr "" + msgid "Search or filter results..." msgstr "" @@ -52970,6 +52976,9 @@ msgstr "" msgid "your settings" msgstr "" +msgid "yyyy-mm-dd" +msgstr "" + msgid "{group}" msgstr "" diff --git a/spec/finders/context_commits_finder_spec.rb b/spec/finders/context_commits_finder_spec.rb index c22675bc67d564..3de1d29b695c4c 100644 --- a/spec/finders/context_commits_finder_spec.rb +++ b/spec/finders/context_commits_finder_spec.rb @@ -26,27 +26,30 @@ end it 'returns commits based in author filter' do - params = { search: 'test text', author: 'Job van der Voort' } + params = { author: 'Job van der Voort' } commits = described_class.new(project, merge_request, params).execute expect(commits.length).to eq(1) expect(commits[0].id).to eq('b83d6e391c22777fca1ed3012fce84f633d7fed0') end - it 'returns commits based in before filter' do - params = { search: 'test text', committed_before: 1474828200 } + it 'returns commits based in committed before and after filter' do + params = { committed_before: 1471631400, committed_after: 1471458600 } # August 18, 2016 - # August 20, 2016 commits = described_class.new(project, merge_request, params).execute - expect(commits.length).to eq(1) - expect(commits[0].id).to eq('498214de67004b1da3d820901307bed2a68a8ef6') + expect(commits.length).to eq(2) + expect(commits[0].id).to eq('1b12f15a11fc6e62177bef08f47bc7b5ce50b141') + expect(commits[1].id).to eq('38008cb17ce1466d8fec2dfa6f6ab8dcfe5cf49e') end - it 'returns commits based in after filter' do - params = { search: 'test text', committed_after: 1474828200 } - commits = described_class.new(project, merge_request, params).execute + it 'returns commits from target branch if no filter is applied' do + expect(project.repository).to receive(:commits).with(merge_request.target_branch, anything).and_call_original - expect(commits.length).to eq(1) + commits = described_class.new(project, merge_request).execute + + expect(commits.length).to eq(37) expect(commits[0].id).to eq('b83d6e391c22777fca1ed3012fce84f633d7fed0') + expect(commits[1].id).to eq('498214de67004b1da3d820901307bed2a68a8ef6') end end end diff --git a/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap b/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap index 2c2151bfb419f3..e379aba094c54a 100644 --- a/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap +++ b/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap @@ -6,8 +6,9 @@ exports[`AddContextCommitsModal renders modal with 2 tabs 1`] = ` body-class="add-review-item pt-0" cancel-variant="light" dismisslabel="Close" - modalclass="" + modalclass="add-review-item-modal" modalid="add-review-item" + nofocusonshow="true" ok-disabled="true" ok-title="Save changes" scrollable="true" @@ -27,9 +28,13 @@ exports[`AddContextCommitsModal renders modal with 2 tabs 1`] = `
- diff --git a/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js b/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js index 5e96da9af7efff..27fe010c35415b 100644 --- a/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js +++ b/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js @@ -1,4 +1,4 @@ -import { GlModal, GlSearchBoxByType } from '@gitlab/ui'; +import { GlModal, GlFilteredSearch } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; @@ -49,7 +49,7 @@ describe('AddContextCommitsModal', () => { }; const findModal = () => wrapper.findComponent(GlModal); - const findSearch = () => wrapper.findComponent(GlSearchBoxByType); + const findSearch = () => wrapper.findComponent(GlFilteredSearch); beforeEach(() => { wrapper = createWrapper(); @@ -68,12 +68,29 @@ describe('AddContextCommitsModal', () => { expect(findSearch().exists()).toBe(true); }); - it('when user starts entering text in search box, it calls action "searchCommits" after waiting for 500s', () => { - const searchText = 'abcd'; - findSearch().vm.$emit('input', searchText); - expect(searchCommits).not.toHaveBeenCalled(); - jest.advanceTimersByTime(500); - expect(searchCommits).toHaveBeenCalledWith(expect.anything(), searchText); + it('when user submits after entering filters in search box, then it calls action "searchCommits"', () => { + const search = [ + 'abcd', + { + type: 'author', + value: { operator: '=', data: 'abhi' }, + }, + { + type: 'committed-before-date', + value: { operator: '=', data: '2022-10-31' }, + }, + { + type: 'committed-after-date', + value: { operator: '=', data: '2022-10-28' }, + }, + ]; + findSearch().vm.$emit('submit', search); + expect(searchCommits).toHaveBeenCalledWith(expect.anything(), { + searchText: 'abcd', + author: 'abhi', + committed_before: '2022-10-31', + committed_after: '2022-10-28', + }); }); it('disabled ok button when no row is selected', () => { diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index f970e818db9e0d..72011693e20dc4 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -597,6 +597,15 @@ def expect_to_raise_storage_error end describe '#list_commits_by' do + it 'returns commits when no filter is applied' do + commit_ids = repository.list_commits_by(nil, 'master', limit: 2).map(&:id) + + expect(commit_ids).to include( + 'b83d6e391c22777fca1ed3012fce84f633d7fed0', + '498214de67004b1da3d820901307bed2a68a8ef6' + ) + end + it 'returns commits with messages containing a given string' do commit_ids = repository.list_commits_by('test text', 'master').map(&:id) -- GitLab