Skip to content
Snippets Groups Projects
Verified Commit 68aab284 authored by Paul Slaughter's avatar Paul Slaughter Committed by Markus Koller
Browse files

FE fetch counts async on search page load

Creates `refresh_counts` module to dynamically fetch
and load data based on attributes of HAML elements.
parent 49c83155
No related branches found
No related tags found
No related merge requests found
import axios from '~/lib/utils/axios_utils';
function showCount(el, count) {
el.textContent = count;
el.classList.remove('hidden');
}
function refreshCount(el) {
const { url } = el.dataset;
return axios
.get(url)
.then(({ data }) => showCount(el, data.count))
.catch(e => {
// eslint-disable-next-line no-console
console.error(`Failed to fetch search count from '${url}'.`, e);
});
}
export default function refreshCounts() {
const elements = Array.from(document.querySelectorAll('.js-search-count'));
return Promise.all(elements.map(refreshCount));
}
Loading
Loading
@@ -3,6 +3,7 @@ import Flash from '~/flash';
import Api from '~/api';
import { __ } from '~/locale';
import Project from '~/pages/projects/project';
import refreshCounts from './refresh_counts';
 
export default class Search {
constructor() {
Loading
Loading
@@ -14,6 +15,7 @@ export default class Search {
 
this.groupId = $groupDropdown.data('groupId');
this.eventListeners();
refreshCounts();
 
$groupDropdown.glDropdown({
selectable: true,
Loading
Loading
Loading
Loading
@@ -155,16 +155,15 @@ module SearchHelper
li_class = 'active'
count = @search_results.formatted_count(scope)
else
count = 0
badge_class = 'js-search-count'
badge_data = { scope: scope, url: search_count_path(search_params) }
badge_class = 'js-search-count hidden'
badge_data = { url: search_count_path(search_params) }
end
 
content_tag :li, class: li_class, data: data do
link_to search_path(search_params) do
concat label
concat ' '
concat content_tag(:span, count, class: 'badge badge-pill', data: { scope: scope })
concat content_tag(:span, count, class: ['badge badge-pill', badge_class], data: badge_data)
end
end
end
Loading
Loading
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`pages/search/show/refresh_counts fetches and displays search counts 1`] = `
"<div class=\\"badge\\">22</div>
<div class=\\"badge js-search-count\\" data-url=\\"http://test.host/search/count?search=lorem+ipsum&amp;project_id=3&amp;scope=issues\\">4</div>
<div class=\\"badge js-search-count\\" data-url=\\"http://test.host/search/count?search=lorem+ipsum&amp;project_id=3&amp;scope=merge_requests\\">5</div>"
`;
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
import refreshCounts from '~/pages/search/show/refresh_counts';
const URL = `${TEST_HOST}/search/count?search=lorem+ipsum&project_id=3`;
const urlWithScope = scope => `${URL}&scope=${scope}`;
const counts = [{ scope: 'issues', count: 4 }, { scope: 'merge_requests', count: 5 }];
const fixture = `<div class="badge">22</div>
<div class="badge js-search-count hidden" data-url="${urlWithScope('issues')}"></div>
<div class="badge js-search-count hidden" data-url="${urlWithScope('merge_requests')}"></div>`;
describe('pages/search/show/refresh_counts', () => {
let mock;
beforeEach(() => {
mock = new MockAdapter(axios);
setFixtures(fixture);
});
afterEach(() => {
mock.restore();
});
it('fetches and displays search counts', () => {
counts.forEach(({ scope, count }) => {
mock.onGet(urlWithScope(scope)).reply(200, { count });
});
// assert before act behavior
return refreshCounts().then(() => {
expect(document.body.innerHTML).toMatchSnapshot();
});
});
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment