FE fetch counts async on search page load
Creates `refresh_counts` module to dynamically fetch and load data based on attributes of HAML elements.
This commit is contained in:
parent
49c83155cc
commit
68aab284a1
5 changed files with 71 additions and 4 deletions
24
app/assets/javascripts/pages/search/show/refresh_counts.js
Normal file
24
app/assets/javascripts/pages/search/show/refresh_counts.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
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));
|
||||
}
|
|
@ -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() {
|
||||
|
@ -14,6 +15,7 @@ export default class Search {
|
|||
|
||||
this.groupId = $groupDropdown.data('groupId');
|
||||
this.eventListeners();
|
||||
refreshCounts();
|
||||
|
||||
$groupDropdown.glDropdown({
|
||||
selectable: true,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
// 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&project_id=3&scope=issues\\">4</div>
|
||||
<div class=\\"badge js-search-count\\" data-url=\\"http://test.host/search/count?search=lorem+ipsum&project_id=3&scope=merge_requests\\">5</div>"
|
||||
`;
|
35
spec/frontend/pages/search/show/refresh_counts_spec.js
Normal file
35
spec/frontend/pages/search/show/refresh_counts_spec.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
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();
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue