Commit 47195d3c authored by Andrew Smith (EspadaV8)'s avatar Andrew Smith (EspadaV8) Committed by Doug Stull

Insert full epic reference in auto-complete selections

parent 21607dbf
...@@ -21,6 +21,7 @@ export const tributeConfig = { ...@@ -21,6 +21,7 @@ export const tributeConfig = {
menuItemLimit, menuItemLimit,
menuItemTemplate: ({ original }) => menuItemTemplate: ({ original }) =>
`<small>${original.iid}</small> ${escape(original.title)}`, `<small>${original.iid}</small> ${escape(original.title)}`,
selectTemplate: ({ original }) => original.reference || `&${original.iid}`,
}, },
}, },
}; };
...@@ -13,7 +13,10 @@ module EE ...@@ -13,7 +13,10 @@ module EE
def epics def epics
return render_404 unless project.group.licensed_feature_available?(:epics) return render_404 unless project.group.licensed_feature_available?(:epics)
render json: autocomplete_service.epics render json: issuable_serializer.represent(
autocomplete_service.epics,
parent_group: project.group&.id
)
end end
def vulnerabilities def vulnerabilities
...@@ -21,6 +24,12 @@ module EE ...@@ -21,6 +24,12 @@ module EE
render json: autocomplete_service.vulnerabilities render json: autocomplete_service.vulnerabilities
end end
private
def issuable_serializer
GroupIssuableAutocompleteSerializer.new
end
end end
end end
end end
...@@ -156,6 +156,8 @@ module EE ...@@ -156,6 +156,8 @@ module EE
public_only.or(where(confidential: true, group_id: groups)) public_only.or(where(confidential: true, group_id: groups))
end end
scope :with_group_route, -> { preload([group: :route]) }
MAX_HIERARCHY_DEPTH = 7 MAX_HIERARCHY_DEPTH = 7
def etag_caching_enabled? def etag_caching_enabled?
......
...@@ -5,7 +5,9 @@ module EE ...@@ -5,7 +5,9 @@ module EE
def epics def epics
EpicsFinder EpicsFinder
.new(current_user, group_id: project.group&.id, state: 'opened') .new(current_user, group_id: project.group&.id, state: 'opened')
.execute.select([:iid, :title]) .execute
.with_group_route
.select(:iid, :title, :group_id)
end end
def vulnerabilities def vulnerabilities
......
...@@ -29,15 +29,19 @@ RSpec.describe Projects::AutocompleteSourcesController do ...@@ -29,15 +29,19 @@ RSpec.describe Projects::AutocompleteSourcesController do
end end
describe '#epics' do describe '#epics' do
it 'returns the correct response' do it 'returns the correct response', :aggregate_failures do
epic_json_response = {
'iid' => epic.iid,
'title' => epic.title,
'reference' => epic.to_reference(epic)
}
get :epics, params: { namespace_id: project.namespace, project_id: project } get :epics, params: { namespace_id: project.namespace, project_id: project }
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an(Array) expect(json_response).to be_an(Array)
expect(json_response.count).to eq(1) expect(json_response.count).to eq(1)
expect(json_response.first).to include( expect(json_response.first).to include(epic_json_response)
'iid' => epic.iid, 'title' => epic.title
)
end end
end end
end end
......
...@@ -12,6 +12,12 @@ describe('ee gfm_autocomplete/utils', () => { ...@@ -12,6 +12,12 @@ describe('ee gfm_autocomplete/utils', () => {
title: "Epic title <script>alert('hi')</script>", title: "Epic title <script>alert('hi')</script>",
}; };
const subgroupEpic = {
iid: 987654,
reference: 'gitlab&987654',
title: "Subgroup context epic title <script>alert('hi')</script>",
};
it('uses & as the trigger', () => { it('uses & as the trigger', () => {
expect(epicsConfig.trigger).toBe('&'); expect(epicsConfig.trigger).toBe('&');
}); });
...@@ -31,5 +37,13 @@ describe('ee gfm_autocomplete/utils', () => { ...@@ -31,5 +37,13 @@ describe('ee gfm_autocomplete/utils', () => {
it('shows the iid and title in the menu item', () => { it('shows the iid and title in the menu item', () => {
expect(epicsConfig.menuItemTemplate({ original: epic })).toMatchSnapshot(); expect(epicsConfig.menuItemTemplate({ original: epic })).toMatchSnapshot();
}); });
it('inserts the iid on autocomplete selection within a top level group context', () => {
expect(epicsConfig.selectTemplate({ original: epic })).toBe(`&${epic.iid}`);
});
it('inserts the reference on autocomplete selection within a group context', () => {
expect(epicsConfig.selectTemplate({ original: subgroupEpic })).toBe(subgroupEpic.reference);
});
}); });
}); });
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Projects::AutocompleteService do
let_it_be(:group, refind: true) { create(:group, :nested, :private, avatar: fixture_file_upload('spec/fixtures/dk.png')) }
let_it_be(:project) { create(:project, group: group) }
let(:user) { create(:user) }
let!(:epic) { create(:epic, group: group, author: user) }
subject { described_class.new(project, user) }
before do
group.add_developer(user)
end
describe '#epics' do
let(:expected_attributes) { [:iid, :title, :group_id, :group] }
before do
stub_licensed_features(epics: true)
end
it 'returns nothing if not allowed' do
guest = create(:user)
epics = described_class.new(project, guest).epics
expect(epics).to be_empty
end
it 'returns epics from group' do
result = subject.epics.map { |epic| epic.slice(expected_attributes) }
expect(result).to contain_exactly(epic.slice(expected_attributes))
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment