Commit 39e416cf authored by Nick Kipling's avatar Nick Kipling

Adds filter by name to packages list

Created new packages_filter component
Added logic to trigger filter from api
Updated Vuex store to support new parameter
Added tests
Updated pot
parent b67ee058
---
title: Adds filter by name to the packages list
merge_request: 27586
author:
type: added
<script>
import { GlSearchBoxByClick } from '@gitlab/ui';
import { mapActions } from 'vuex';
export default {
components: {
GlSearchBoxByClick,
},
methods: {
...mapActions(['setFilter']),
onInput(query) {
this.setFilter(query);
},
onSubmit() {
this.$emit('filter');
},
},
};
</script>
<template>
<gl-search-box-by-click
:placeholder="s__('PackageRegistry|Filter by name')"
@submit="onSubmit"
@input="onInput"
/>
</template>
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { mapActions, mapState } from 'vuex'; import { mapActions, mapState } from 'vuex';
import { GlEmptyState, GlTab, GlTabs } from '@gitlab/ui'; import { GlEmptyState, GlTab, GlTabs } from '@gitlab/ui';
import { s__, sprintf } from '~/locale'; import { s__, sprintf } from '~/locale';
import PackageFilter from './packages_filter.vue';
import PackageList from './packages_list.vue'; import PackageList from './packages_list.vue';
import PackageSort from './packages_sort.vue'; import PackageSort from './packages_sort.vue';
import { PACKAGE_REGISTRY_TABS } from '../constants'; import { PACKAGE_REGISTRY_TABS } from '../constants';
...@@ -11,6 +12,7 @@ export default { ...@@ -11,6 +12,7 @@ export default {
GlEmptyState, GlEmptyState,
GlTab, GlTab,
GlTabs, GlTabs,
PackageFilter,
PackageList, PackageList,
PackageSort, PackageSort,
}, },
...@@ -70,7 +72,8 @@ export default { ...@@ -70,7 +72,8 @@ export default {
<template> <template>
<gl-tabs @input="tabChanged"> <gl-tabs @input="tabChanged">
<template #tabs-end> <template #tabs-end>
<div class="align-self-center ml-auto"> <div class="d-flex align-self-center ml-auto">
<package-filter class="mr-1" @filter="requestPackagesList" />
<package-sort @sort:changed="requestPackagesList" /> <package-sort @sort:changed="requestPackagesList" />
</div> </div>
</template> </template>
......
...@@ -15,6 +15,7 @@ export const setInitialState = ({ commit }, data) => commit(types.SET_INITIAL_ST ...@@ -15,6 +15,7 @@ export const setInitialState = ({ commit }, data) => commit(types.SET_INITIAL_ST
export const setLoading = ({ commit }, data) => commit(types.SET_MAIN_LOADING, data); export const setLoading = ({ commit }, data) => commit(types.SET_MAIN_LOADING, data);
export const setSorting = ({ commit }, data) => commit(types.SET_SORTING, data); export const setSorting = ({ commit }, data) => commit(types.SET_SORTING, data);
export const setSelectedType = ({ commit }, data) => commit(types.SET_SELECTED_TYPE, data); export const setSelectedType = ({ commit }, data) => commit(types.SET_SELECTED_TYPE, data);
export const setFilter = ({ commit }, data) => commit(types.SET_FILTER, data);
export const receivePackagesListSuccess = ({ commit }, { data, headers }) => { export const receivePackagesListSuccess = ({ commit }, { data, headers }) => {
commit(types.SET_PACKAGE_LIST_SUCCESS, data); commit(types.SET_PACKAGE_LIST_SUCCESS, data);
...@@ -26,12 +27,17 @@ export const requestPackagesList = ({ dispatch, state }, params = {}) => { ...@@ -26,12 +27,17 @@ export const requestPackagesList = ({ dispatch, state }, params = {}) => {
const { page = DEFAULT_PAGE, per_page = DEFAULT_PAGE_SIZE } = params; const { page = DEFAULT_PAGE, per_page = DEFAULT_PAGE_SIZE } = params;
const { sort, orderBy } = state.sorting; const { sort, orderBy } = state.sorting;
const type = state.selectedType?.type?.toLowerCase(); const type = state.selectedType?.type?.toLowerCase();
const packageType = { package_type: type }; const packageType = { package_type: type };
const nameFilter = state.filterQuery?.toLowerCase();
const packageName = { package_name: nameFilter };
const apiMethod = state.config.isGroupPage ? 'groupPackages' : 'projectPackages'; const apiMethod = state.config.isGroupPage ? 'groupPackages' : 'projectPackages';
return Api[apiMethod](state.config.resourceId, { return Api[apiMethod](state.config.resourceId, {
params: { page, per_page, sort, order_by: orderBy, ...packageType }, params: { page, per_page, sort, order_by: orderBy, ...packageType, ...packageName },
}) })
.then(({ data, headers }) => { .then(({ data, headers }) => {
dispatch('receivePackagesListSuccess', { data, headers }); dispatch('receivePackagesListSuccess', { data, headers });
......
...@@ -5,3 +5,4 @@ export const SET_PAGINATION = 'SET_PAGINATION'; ...@@ -5,3 +5,4 @@ export const SET_PAGINATION = 'SET_PAGINATION';
export const SET_MAIN_LOADING = 'SET_MAIN_LOADING'; export const SET_MAIN_LOADING = 'SET_MAIN_LOADING';
export const SET_SORTING = 'SET_SORTING'; export const SET_SORTING = 'SET_SORTING';
export const SET_SELECTED_TYPE = 'SET_SELECTED_TYPE'; export const SET_SELECTED_TYPE = 'SET_SELECTED_TYPE';
export const SET_FILTER = 'SET_FILTER';
...@@ -30,4 +30,8 @@ export default { ...@@ -30,4 +30,8 @@ export default {
[types.SET_SELECTED_TYPE](state, type) { [types.SET_SELECTED_TYPE](state, type) {
state.selectedType = type; state.selectedType = type;
}, },
[types.SET_FILTER](state, query) {
state.filterQuery = query;
},
}; };
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`packages_filter renders 1`] = `
<gl-search-box-by-click-stub
clearbuttontitle="Clear"
clearrecentsearchestext="Clear recent searches"
closebuttontitle="Close"
norecentsearchestext="You don't have any recent searches"
placeholder="Filter by name"
recentsearchesheader="Recent searches"
value=""
/>
`;
...@@ -350,8 +350,12 @@ exports[`packages_list_app renders 1`] = ` ...@@ -350,8 +350,12 @@ exports[`packages_list_app renders 1`] = `
</template> </template>
<template> <template>
<div <div
class="align-self-center ml-auto" class="d-flex align-self-center ml-auto"
> >
<package-filter-stub
class="mr-1"
/>
<package-sort-stub /> <package-sort-stub />
</div> </div>
</template> </template>
......
import Vuex from 'vuex';
import { GlSearchBoxByClick } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import PackagesFilter from 'ee/packages/list/components/packages_filter.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('packages_filter', () => {
let wrapper;
let store;
const findGlSearchBox = () => wrapper.find(GlSearchBoxByClick);
const mountComponent = () => {
store = new Vuex.Store();
store.dispatch = jest.fn();
wrapper = shallowMount(PackagesFilter, {
localVue,
store,
});
};
beforeEach(mountComponent);
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('renders', () => {
expect(wrapper.element).toMatchSnapshot();
});
describe('emits events', () => {
it('sets the filter value in the store on input', () => {
const searchString = 'foo';
findGlSearchBox().vm.$emit('input', searchString);
expect(store.dispatch).toHaveBeenCalledWith('setFilter', searchString);
});
it('emits the filter event when search box is submitted', () => {
findGlSearchBox().vm.$emit('submit');
expect(wrapper.emitted('filter')).toBeTruthy();
});
});
});
...@@ -228,4 +228,17 @@ describe('Actions Package list store', () => { ...@@ -228,4 +228,17 @@ describe('Actions Package list store', () => {
); );
}); });
}); });
describe('setFilter', () => {
it('should commit SET_FILTER', done => {
testAction(
actions.setFilter,
'foo',
null,
[{ type: types.SET_FILTER, payload: 'foo' }],
[],
done,
);
});
});
}); });
...@@ -84,4 +84,11 @@ describe('Mutations Registry Store', () => { ...@@ -84,4 +84,11 @@ describe('Mutations Registry Store', () => {
expect(mockState.selectedType).toEqual({ type: 'maven' }); expect(mockState.selectedType).toEqual({ type: 'maven' });
}); });
}); });
describe('SET_FILTER', () => {
it('should set the filter query', () => {
mutations[types.SET_FILTER](mockState, 'foo');
expect(mockState.filterQuery).toEqual('foo');
});
});
}); });
...@@ -13966,6 +13966,9 @@ msgstr "" ...@@ -13966,6 +13966,9 @@ msgstr ""
msgid "PackageRegistry|Delete package" msgid "PackageRegistry|Delete package"
msgstr "" msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}." msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr "" msgstr ""
......
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