Commit 7c820e4e authored by Tim Zallmann's avatar Tim Zallmann

Merge branch '6240-multiple-select-filters' into 'master'

Allows the GSD to select multiple filters

See merge request gitlab-org/gitlab-ee!9031
parents f6a9a307 429259bc
......@@ -22,13 +22,12 @@ export default {
},
},
computed: {
...mapGetters('filters', ['getFilter', 'getSelectedOptions']),
...mapGetters('filters', ['getFilter', 'getSelectedOptions', 'getSelectedOptionNames']),
filter() {
return this.getFilter(this.filterId);
},
selectedOptionText() {
const [selectedOption] = this.getSelectedOptions(this.filterId);
return (selectedOption && selectedOption.name) || '-';
return this.getSelectedOptionNames(this.filterId) || '-';
},
},
methods: {
......
import { sprintf, __ } from '~/locale';
export const getFilter = state => filterId => state.filters.find(filter => filter.id === filterId);
export const getSelectedOptions = (state, getters) => filterId =>
......@@ -6,6 +8,19 @@ export const getSelectedOptions = (state, getters) => filterId =>
export const getSelectedOptionIds = (state, getters) => filterId =>
getters.getSelectedOptions(filterId).map(option => option.id);
export const getSelectedOptionNames = (state, getters) => filterId => {
const selectedOptions = getters.getSelectedOptions(filterId);
const [firstOption] = selectedOptions.map(option => option.name);
const extraOptionCount = selectedOptions.length - 1;
return extraOptionCount
? sprintf(__('%{firstOption} +%{extraOptionCount} more'), {
firstOption,
extraOptionCount,
})
: firstOption;
};
export const getFilterIds = state => state.filters.map(filter => filter.id);
/**
......
......@@ -4,13 +4,41 @@ export default {
[types.SET_FILTER](state, payload) {
const { filterId, optionId } = payload;
const activeFilter = state.filters.find(filter => filter.id === filterId);
if (activeFilter) {
activeFilter.options = [
...activeFilter.options.map(option => ({
let activeOptions;
if (optionId === 'all') {
activeOptions = activeFilter.options.map(option => ({
...option,
selected: option.id === optionId,
})),
];
}));
} else {
activeOptions = activeFilter.options.map(option => {
if (option.id === 'all') {
return {
...option,
selected: false,
};
}
if (option.id === optionId) {
return {
...option,
selected: !option.selected,
};
}
return option;
});
}
// This prevents us from selecting nothing at all
if (!activeOptions.find(option => option.selected)) {
activeOptions[0].selected = true;
}
activeFilter.options = activeOptions;
}
},
};
---
title: Allows the Group Security Dashboard to select multiple filters
merge_request: 9031
author:
type: added
......@@ -28,14 +28,32 @@ describe('filters module getters', () => {
});
describe('getSelectedOptions', () => {
it('should return "All" as the selcted option', () => {
const state = createState();
const selectedOptions = getters.getSelectedOptions(state, mockedGetters(state))(
'report_type',
);
describe('with one selected option', () => {
it('should return "All" as the selected option', () => {
const state = createState();
const selectedOptions = getters.getSelectedOptions(state, mockedGetters(state))(
'report_type',
);
expect(selectedOptions).toHaveLength(1);
expect(selectedOptions[0].name).toEqual('All');
});
});
expect(selectedOptions).toHaveLength(1);
expect(selectedOptions[0].name).toEqual('All');
describe('with multiple selected options', () => {
it('should return both "High" and "Critical" ', () => {
const state = {
filters: [
{
id: 'severity',
options: [{ id: 'critical', selected: true }, { id: 'high', selected: true }],
},
],
};
const selectedOptions = getters.getSelectedOptions(state, mockedGetters(state))('severity');
expect(selectedOptions).toHaveLength(2);
});
});
});
......@@ -56,6 +74,33 @@ describe('filters module getters', () => {
});
});
describe('getSelectedOptionNames', () => {
it('should return "All" as the selected option', () => {
const state = createState();
const selectedOptionNames = getters.getSelectedOptionNames(state, mockedGetters(state))(
'severity',
);
expect(selectedOptionNames).toEqual('All');
});
it('should return the correct message when multiple filters are selected', () => {
const state = {
filters: [
{
id: 'severity',
options: [{ name: 'Critical', selected: true }, { name: 'High', selected: true }],
},
],
};
const selectedOptionNames = getters.getSelectedOptionNames(state, mockedGetters(state))(
'severity',
);
expect(selectedOptionNames).toEqual('Critical +1 more');
});
});
describe('activeFilters', () => {
it('should return no severity filters', () => {
const state = createState();
......
......@@ -5,26 +5,39 @@ import mutations from 'ee/security_dashboard/store/modules/filters/mutations';
describe('filters module mutations', () => {
describe('SET_FILTER', () => {
let state;
let typeFilter;
let sastOption;
let severityFilter;
let criticalOption;
let highOption;
beforeEach(() => {
state = createState();
[typeFilter] = state.filters;
[, sastOption] = typeFilter.options;
[severityFilter] = state.filters;
[, criticalOption, highOption] = severityFilter.options;
mutations[types.SET_FILTER](state, {
filterId: typeFilter.id,
optionId: sastOption.id,
filterId: severityFilter.id,
optionId: criticalOption.id,
});
});
it('should make SAST the selected option', () => {
it('should make critical the selected option', () => {
expect(state.filters[0].options[1].selected).toEqual(true);
});
it('should remove ALL as the selected option', () => {
expect(state.filters[0].options[0].selected).toEqual(false);
});
describe('on subsequent changes', () => {
it('should add "high" to the selected options', () => {
mutations[types.SET_FILTER](state, {
filterId: severityFilter.id,
optionId: highOption.id,
});
expect(state.filters[0].options[1].selected).toEqual(true);
expect(state.filters[0].options[2].selected).toEqual(true);
});
});
});
});
......@@ -150,6 +150,9 @@ msgstr ""
msgid "%{firstLabel} +%{labelCount} more"
msgstr ""
msgid "%{firstOption} +%{extraOptionCount} more"
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
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