Commit 09238aba authored by Mike Greiling's avatar Mike Greiling

Merge branch 'dz-update-milestones-labels-routes' into 'master'

Use scoped routes for labels and milestones

See merge request gitlab-org/gitlab-ce!29358
parents d8b361af 14b0a462
...@@ -8,9 +8,19 @@ import DropdownUtils from './dropdown_utils'; ...@@ -8,9 +8,19 @@ import DropdownUtils from './dropdown_utils';
import { mergeUrlParams } from '../lib/utils/url_utility'; import { mergeUrlParams } from '../lib/utils/url_utility';
export default class AvailableDropdownMappings { export default class AvailableDropdownMappings {
constructor(container, baseEndpoint, groupsOnly, includeAncestorGroups, includeDescendantGroups) { constructor(
container,
baseEndpoint,
labelsEndpoint,
milestonesEndpoint,
groupsOnly,
includeAncestorGroups,
includeDescendantGroups,
) {
this.container = container; this.container = container;
this.baseEndpoint = baseEndpoint; this.baseEndpoint = baseEndpoint;
this.labelsEndpoint = labelsEndpoint;
this.milestonesEndpoint = milestonesEndpoint;
this.groupsOnly = groupsOnly; this.groupsOnly = groupsOnly;
this.includeAncestorGroups = includeAncestorGroups; this.includeAncestorGroups = includeAncestorGroups;
this.includeDescendantGroups = includeDescendantGroups; this.includeDescendantGroups = includeDescendantGroups;
...@@ -117,11 +127,11 @@ export default class AvailableDropdownMappings { ...@@ -117,11 +127,11 @@ export default class AvailableDropdownMappings {
} }
getMilestoneEndpoint() { getMilestoneEndpoint() {
return `${this.baseEndpoint}/milestones.json`; return `${this.milestonesEndpoint}.json`;
} }
getLabelsEndpoint() { getLabelsEndpoint() {
let endpoint = `${this.baseEndpoint}/labels.json?`; let endpoint = `${this.labelsEndpoint}.json?`;
if (this.groupsOnly) { if (this.groupsOnly) {
endpoint = `${endpoint}only_group_labels=true&`; endpoint = `${endpoint}only_group_labels=true&`;
......
...@@ -9,6 +9,8 @@ import FilteredSearchVisualTokens from './filtered_search_visual_tokens'; ...@@ -9,6 +9,8 @@ import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
export default class FilteredSearchDropdownManager { export default class FilteredSearchDropdownManager {
constructor({ constructor({
baseEndpoint = '', baseEndpoint = '',
labelsEndpoint = '',
milestonesEndpoint = '',
tokenizer, tokenizer,
page, page,
isGroup, isGroup,
...@@ -18,6 +20,8 @@ export default class FilteredSearchDropdownManager { ...@@ -18,6 +20,8 @@ export default class FilteredSearchDropdownManager {
}) { }) {
this.container = FilteredSearchContainer.container; this.container = FilteredSearchContainer.container;
this.baseEndpoint = baseEndpoint.replace(/\/$/, ''); this.baseEndpoint = baseEndpoint.replace(/\/$/, '');
this.labelsEndpoint = labelsEndpoint.replace(/\/$/, '');
this.milestonesEndpoint = milestonesEndpoint.replace(/\/$/, '');
this.tokenizer = tokenizer; this.tokenizer = tokenizer;
this.filteredSearchTokenKeys = filteredSearchTokenKeys || FilteredSearchTokenKeys; this.filteredSearchTokenKeys = filteredSearchTokenKeys || FilteredSearchTokenKeys;
this.filteredSearchInput = this.container.querySelector('.filtered-search'); this.filteredSearchInput = this.container.querySelector('.filtered-search');
...@@ -48,6 +52,8 @@ export default class FilteredSearchDropdownManager { ...@@ -48,6 +52,8 @@ export default class FilteredSearchDropdownManager {
const availableMappings = new AvailableDropdownMappings( const availableMappings = new AvailableDropdownMappings(
this.container, this.container,
this.baseEndpoint, this.baseEndpoint,
this.labelsEndpoint,
this.milestonesEndpoint,
this.groupsOnly, this.groupsOnly,
this.includeAncestorGroups, this.includeAncestorGroups,
this.includeDescendantGroups, this.includeDescendantGroups,
......
...@@ -86,6 +86,8 @@ export default class FilteredSearchManager { ...@@ -86,6 +86,8 @@ export default class FilteredSearchManager {
this.tokenizer = FilteredSearchTokenizer; this.tokenizer = FilteredSearchTokenizer;
this.dropdownManager = new FilteredSearchDropdownManager({ this.dropdownManager = new FilteredSearchDropdownManager({
baseEndpoint: this.filteredSearchInput.getAttribute('data-base-endpoint') || '', baseEndpoint: this.filteredSearchInput.getAttribute('data-base-endpoint') || '',
labelsEndpoint: this.filteredSearchInput.getAttribute('data-labels-endpoint') || '',
milestonesEndpoint: this.filteredSearchInput.getAttribute('data-milestones-endpoint') || '',
tokenizer: this.tokenizer, tokenizer: this.tokenizer,
page: this.page, page: this.page,
isGroup: this.isGroup, isGroup: this.isGroup,
......
...@@ -56,13 +56,13 @@ export default class VisualTokenValue { ...@@ -56,13 +56,13 @@ export default class VisualTokenValue {
updateLabelTokenColor(tokenValueContainer) { updateLabelTokenColor(tokenValueContainer) {
const { tokenValue } = this; const { tokenValue } = this;
const filteredSearchInput = FilteredSearchContainer.container.querySelector('.filtered-search'); const filteredSearchInput = FilteredSearchContainer.container.querySelector('.filtered-search');
const { baseEndpoint } = filteredSearchInput.dataset; const { labelsEndpoint } = filteredSearchInput.dataset;
const labelsEndpoint = FilteredSearchVisualTokens.getEndpointWithQueryParams( const labelsEndpointWithParams = FilteredSearchVisualTokens.getEndpointWithQueryParams(
`${baseEndpoint}/labels.json`, `${labelsEndpoint}.json`,
filteredSearchInput.dataset.endpointQueryParams, filteredSearchInput.dataset.endpointQueryParams,
); );
return AjaxCache.retrieve(labelsEndpoint) return AjaxCache.retrieve(labelsEndpointWithParams)
.then(labels => { .then(labels => {
const matchingLabel = (labels || []).find( const matchingLabel = (labels || []).find(
label => `~${DropdownUtils.getEscapedText(label.title)}` === tokenValue, label => `~${DropdownUtils.getEscapedText(label.title)}` === tokenValue,
......
...@@ -172,11 +172,17 @@ module SearchHelper ...@@ -172,11 +172,17 @@ module SearchHelper
if @project.present? if @project.present?
opts[:data]['project-id'] = @project.id opts[:data]['project-id'] = @project.id
opts[:data]['base-endpoint'] = project_path(@project) opts[:data]['base-endpoint'] = project_path(@project)
opts[:data]['labels-endpoint'] = project_labels_path(@project)
opts[:data]['milestones-endpoint'] = project_milestones_path(@project)
elsif @group.present? elsif @group.present?
opts[:data]['group-id'] = @group.id opts[:data]['group-id'] = @group.id
opts[:data]['base-endpoint'] = group_canonical_path(@group) opts[:data]['base-endpoint'] = group_canonical_path(@group)
opts[:data]['labels-endpoint'] = group_labels_path(@group)
opts[:data]['milestones-endpoint'] = group_milestones_path(@group)
else else
opts[:data]['base-endpoint'] = root_dashboard_path opts[:data]['base-endpoint'] = root_dashboard_path
opts[:data]['labels-endpoint'] = dashboard_labels_path
opts[:data]['milestones-endpoint'] = dashboard_milestones_path
end end
opts opts
......
...@@ -113,8 +113,10 @@ describe SearchHelper do ...@@ -113,8 +113,10 @@ describe SearchHelper do
expect(search_filter_input_options('')[:data]['project-id']).to eq(@project.id) expect(search_filter_input_options('')[:data]['project-id']).to eq(@project.id)
end end
it 'includes project base-endpoint' do it 'includes project endpoints' do
expect(search_filter_input_options('')[:data]['base-endpoint']).to eq(project_path(@project)) expect(search_filter_input_options('')[:data]['base-endpoint']).to eq(project_path(@project))
expect(search_filter_input_options('')[:data]['labels-endpoint']).to eq(project_labels_path(@project))
expect(search_filter_input_options('')[:data]['milestones-endpoint']).to eq(project_milestones_path(@project))
end end
it 'includes autocomplete=off flag' do it 'includes autocomplete=off flag' do
...@@ -131,8 +133,10 @@ describe SearchHelper do ...@@ -131,8 +133,10 @@ describe SearchHelper do
expect(search_filter_input_options('')[:data]['project-id']).to eq(nil) expect(search_filter_input_options('')[:data]['project-id']).to eq(nil)
end end
it 'includes group base-endpoint' do it 'includes group endpoints' do
expect(search_filter_input_options('')[:data]['base-endpoint']).to eq("/groups#{group_path(@group)}") expect(search_filter_input_options('')[:data]['base-endpoint']).to eq("/groups#{group_path(@group)}")
expect(search_filter_input_options('')[:data]['labels-endpoint']).to eq(group_labels_path(@group))
expect(search_filter_input_options('')[:data]['milestones-endpoint']).to eq(group_milestones_path(@group))
end end
end end
...@@ -142,8 +146,10 @@ describe SearchHelper do ...@@ -142,8 +146,10 @@ describe SearchHelper do
expect(search_filter_input_options('')[:data]['group-id']).to eq(nil) expect(search_filter_input_options('')[:data]['group-id']).to eq(nil)
end end
it 'includes dashboard base-endpoint' do it 'includes dashboard endpoints' do
expect(search_filter_input_options('')[:data]['base-endpoint']).to eq("/dashboard") expect(search_filter_input_options('')[:data]['base-endpoint']).to eq("/dashboard")
expect(search_filter_input_options('')[:data]['labels-endpoint']).to eq(dashboard_labels_path)
expect(search_filter_input_options('')[:data]['milestones-endpoint']).to eq(dashboard_milestones_path)
end end
end end
end end
......
...@@ -118,7 +118,7 @@ describe('Filtered Search Visual Tokens', () => { ...@@ -118,7 +118,7 @@ describe('Filtered Search Visual Tokens', () => {
describe('getEndpointWithQueryParams', () => { describe('getEndpointWithQueryParams', () => {
it('returns `endpoint` string as is when second param `endpointQueryParams` is undefined, null or empty string', () => { it('returns `endpoint` string as is when second param `endpointQueryParams` is undefined, null or empty string', () => {
const endpoint = 'foo/bar/labels.json'; const endpoint = 'foo/bar/-/labels.json';
expect(subject.getEndpointWithQueryParams(endpoint)).toBe(endpoint); expect(subject.getEndpointWithQueryParams(endpoint)).toBe(endpoint);
expect(subject.getEndpointWithQueryParams(endpoint, null)).toBe(endpoint); expect(subject.getEndpointWithQueryParams(endpoint, null)).toBe(endpoint);
...@@ -126,7 +126,7 @@ describe('Filtered Search Visual Tokens', () => { ...@@ -126,7 +126,7 @@ describe('Filtered Search Visual Tokens', () => {
}); });
it('returns `endpoint` string with values of `endpointQueryParams`', () => { it('returns `endpoint` string with values of `endpointQueryParams`', () => {
const endpoint = 'foo/bar/labels.json'; const endpoint = 'foo/bar/-/labels.json';
const singleQueryParams = '{"foo":"true"}'; const singleQueryParams = '{"foo":"true"}';
const multipleQueryParams = '{"foo":"true","bar":"true"}'; const multipleQueryParams = '{"foo":"true","bar":"true"}';
......
...@@ -156,9 +156,11 @@ describe('Filtered Search Visual Tokens', () => { ...@@ -156,9 +156,11 @@ describe('Filtered Search Visual Tokens', () => {
const filteredSearchInput = document.querySelector('.filtered-search'); const filteredSearchInput = document.querySelector('.filtered-search');
filteredSearchInput.dataset.baseEndpoint = dummyEndpoint; filteredSearchInput.dataset.baseEndpoint = dummyEndpoint;
filteredSearchInput.dataset.labelsEndpoint = `${dummyEndpoint}/-/labels`;
filteredSearchInput.dataset.milestonesEndpoint = `${dummyEndpoint}/-/milestones`;
AjaxCache.internalStorage = {}; AjaxCache.internalStorage = {};
AjaxCache.internalStorage[`${dummyEndpoint}/labels.json`] = labelData; AjaxCache.internalStorage[`${filteredSearchInput.dataset.labelsEndpoint}.json`] = labelData;
}); });
const parseColor = color => { const parseColor = color => {
......
...@@ -48,8 +48,8 @@ export const mockConfig = { ...@@ -48,8 +48,8 @@ export const mockConfig = {
}, },
namespace: 'gitlab-org', namespace: 'gitlab-org',
updatePath: '/gitlab-org/my-project/issue/1', updatePath: '/gitlab-org/my-project/issue/1',
labelsPath: '/gitlab-org/my-project/labels.json', labelsPath: '/gitlab-org/my-project/-/labels.json',
labelsWebUrl: '/gitlab-org/my-project/labels', labelsWebUrl: '/gitlab-org/my-project/-/labels',
labelFilterBasePath: '/gitlab-org/my-project/issues', labelFilterBasePath: '/gitlab-org/my-project/issues',
canEdit: true, canEdit: true,
suggestedColors: mockSuggestedColors, suggestedColors: mockSuggestedColors,
......
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