Commit 5c61a788 authored by Daniel Tian's avatar Daniel Tian Committed by Natalia Tepluhina

Improve pipeline security tab filter logic

parent 801d158b
...@@ -15,12 +15,17 @@ export default { ...@@ -15,12 +15,17 @@ export default {
}), }),
computed: { computed: {
...mapState('filters', ['filters']), ...mapState('filters', ['filters']),
hideDismissed() { hideDismissed: {
return this.filters.scope === DISMISSAL_STATES.DISMISSED; set(isHidden) {
this.setHideDismissed(isHidden);
},
get() {
return this.filters.scope === DISMISSAL_STATES.DISMISSED;
},
}, },
}, },
methods: { methods: {
...mapActions('filters', ['setFilter', 'toggleHideDismissed']), ...mapActions('filters', ['setFilter', 'setHideDismissed']),
}, },
}; };
</script> </script>
...@@ -39,11 +44,7 @@ export default { ...@@ -39,11 +44,7 @@ export default {
<slot name="buttons"></slot> <slot name="buttons"></slot>
<div class="pl-md-6"> <div class="pl-md-6">
<strong>{{ s__('SecurityReports|Hide dismissed') }}</strong> <strong>{{ s__('SecurityReports|Hide dismissed') }}</strong>
<gl-toggle <gl-toggle v-model="hideDismissed" class="gl-mt-2 js-toggle" />
class="d-block mt-1 js-toggle"
:value="hideDismissed"
@change="toggleHideDismissed"
/>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -83,9 +83,13 @@ export default { ...@@ -83,9 +83,13 @@ export default {
this.updateRouteQuery(); this.updateRouteQuery();
}, },
updateRouteQuery() { updateRouteQuery() {
if (!this.$router) {
return;
}
const query = { query: { ...this.$route?.query, ...this.queryObject } }; const query = { query: { ...this.$route?.query, ...this.queryObject } };
// To avoid a console error, don't update the querystring if it's the same as the current one. // To avoid a console error, don't update the querystring if it's the same as the current one.
if (this.$router && !isEqual(this.routeQueryIds, this.queryObject[this.filter.id])) { if (!isEqual(this.routeQueryIds, this.queryObject[this.filter.id])) {
this.$router.push(query); this.$router.push(query);
} }
}, },
......
...@@ -31,7 +31,7 @@ export const severityFilter = { ...@@ -31,7 +31,7 @@ export const severityFilter = {
}; };
export const scannerFilter = { export const scannerFilter = {
name: s__('Reports|Scanner'), name: s__('SecurityReports|Scanner'),
id: 'reportType', id: 'reportType',
options: parseOptions(REPORT_TYPES), options: parseOptions(REPORT_TYPES),
allOption: BASE_FILTERS.report_type, allOption: BASE_FILTERS.report_type,
......
import * as types from './mutation_types'; import { mapValues } from 'lodash';
import Tracking from '~/tracking';
import { SET_FILTER, SET_HIDE_DISMISSED } from './mutation_types';
import { DISMISSAL_STATES } from './constants';
import { convertObjectPropsToSnakeCase } from '~/lib/utils/common_utils';
export const setFilter = ({ commit }, filter) => { export const setFilter = ({ commit }, filter) => {
commit(types.SET_FILTER, filter); // Convert the filter key to snake case and the selected option IDs to lower case. The API
// endpoint needs them to be in this format.
const convertedFilter = mapValues(convertObjectPropsToSnakeCase(filter), array =>
array.map(element => element.toLowerCase()),
);
commit(SET_FILTER, convertedFilter);
const [label, value] = Object.values(filter);
Tracking.event(document.body.dataset.page, 'set_filter', { label, value });
}; };
export const toggleHideDismissed = ({ commit }) => { export const setHideDismissed = ({ commit }, isHidden) => {
commit(types.TOGGLE_HIDE_DISMISSED); const value = isHidden ? DISMISSAL_STATES.DISMISSED : DISMISSAL_STATES.ALL;
commit(SET_HIDE_DISMISSED, value);
Tracking.event(document.body.dataset.page, 'set_toggle', { label: 'scope', value });
}; };
export const SET_FILTER = 'SET_FILTER'; export const SET_FILTER = 'SET_FILTER';
export const TOGGLE_HIDE_DISMISSED = 'TOGGLE_HIDE_DISMISSED'; export const SET_HIDE_DISMISSED = 'SET_HIDE_DISMISSED';
import { mapValues } from 'lodash'; import { SET_FILTER, SET_HIDE_DISMISSED } from './mutation_types';
import { convertObjectPropsToSnakeCase } from '~/lib/utils/common_utils';
import * as types from './mutation_types';
import { DISMISSAL_STATES } from './constants';
import Tracking from '~/tracking';
export default { export default {
[types.SET_FILTER](state, filter) { [SET_FILTER](state, filter) {
// Convert the filter key to snake case and the selected option IDs to lower case. The API state.filters = { ...state.filters, ...filter };
// endpoint needs them to be in this format.
const convertedFilter = mapValues(convertObjectPropsToSnakeCase(filter), array =>
array.map(element => element.toLowerCase()),
);
state.filters = { ...state.filters, ...convertedFilter };
const [label, value] = Object.values(filter);
Tracking.event(document.body.dataset.page, 'set_filter', { label, value });
}, },
[types.TOGGLE_HIDE_DISMISSED](state) { [SET_HIDE_DISMISSED](state, scope) {
const scope =
state.filters.scope === DISMISSAL_STATES.DISMISSED
? DISMISSAL_STATES.ALL
: DISMISSAL_STATES.DISMISSED;
state.filters = { ...state.filters, scope }; state.filters = { ...state.filters, scope };
Tracking.event(document.body.dataset.page, 'set_toggle', { label: 'scope', value: scope });
}, },
}; };
import { SET_FILTER, TOGGLE_HIDE_DISMISSED } from '../modules/filters/mutation_types'; import { SET_FILTER, SET_HIDE_DISMISSED } from '../modules/filters/mutation_types';
const refreshTypes = [`filters/${SET_FILTER}`, `filters/${TOGGLE_HIDE_DISMISSED}`]; const refreshTypes = [`filters/${SET_FILTER}`, `filters/${SET_HIDE_DISMISSED}`];
export default store => { export default store => {
const refreshVulnerabilities = payload => { const refreshVulnerabilities = payload => {
......
import * as actions from 'ee/security_dashboard/store/modules/filters/actions'; import * as actions from 'ee/security_dashboard/store/modules/filters/actions';
import * as types from 'ee/security_dashboard/store/modules/filters/mutation_types'; import * as types from 'ee/security_dashboard/store/modules/filters/mutation_types';
import createState from 'ee/security_dashboard/store/modules/filters/state'; import { DISMISSAL_STATES } from 'ee/security_dashboard/store/modules/filters/constants';
import testAction from 'helpers/vuex_action_helper'; import testAction from 'helpers/vuex_action_helper';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
...@@ -14,28 +14,41 @@ describe('filters actions', () => { ...@@ -14,28 +14,41 @@ describe('filters actions', () => {
}); });
describe('setFilter', () => { describe('setFilter', () => {
it('should commit the SET_FILTER mutuation', () => { it('should commit the SET_FILTER mutation with the right casing', () => {
const state = createState(); const payload = {
const payload = { reportType: ['sast'] }; oneWord: ['ABC', 'DEF'],
twoWords: ['123', '456'],
threeTotalWords: ['Abc123', 'dEF456'],
};
return testAction(actions.setFilter, payload, state, [ return testAction(actions.setFilter, payload, undefined, [
{ {
type: types.SET_FILTER, type: types.SET_FILTER,
payload, payload: {
one_word: ['abc', 'def'],
two_words: ['123', '456'],
three_total_words: ['abc123', 'def456'],
},
}, },
]); ]);
}); });
}); });
describe('toggleHideDismissed', () => { describe('setHideDismissed', () => {
it('should commit the TOGGLE_HIDE_DISMISSED mutation', () => { it.each`
const state = createState(); isHidden | expected
${true} | ${DISMISSAL_STATES.DISMISSED}
return testAction(actions.toggleHideDismissed, undefined, state, [ ${false} | ${DISMISSAL_STATES.ALL}
{ `(
type: types.TOGGLE_HIDE_DISMISSED, 'should commit the SET_HIDE_DISMISSED mutation with "$expected" when called with $isHidden',
}, ({ isHidden, expected }) => {
]); return testAction(actions.setHideDismissed, isHidden, undefined, [
}); {
type: types.SET_HIDE_DISMISSED,
payload: expected,
},
]);
},
);
}); });
}); });
import { severityFilter } from 'ee/security_dashboard/helpers'; import { severityFilter } from 'ee/security_dashboard/helpers';
import { import {
SET_FILTER, SET_FILTER,
TOGGLE_HIDE_DISMISSED, SET_HIDE_DISMISSED,
} from 'ee/security_dashboard/store/modules/filters/mutation_types'; } from 'ee/security_dashboard/store/modules/filters/mutation_types';
import mutations from 'ee/security_dashboard/store/modules/filters/mutations'; import mutations from 'ee/security_dashboard/store/modules/filters/mutations';
import createState from 'ee/security_dashboard/store/modules/filters/state'; import createState from 'ee/security_dashboard/store/modules/filters/state';
import { DISMISSAL_STATES } from 'ee/security_dashboard/store/modules/filters/constants';
const criticalOption = severityFilter.options.find(x => x.id === 'CRITICAL'); const criticalOption = severityFilter.options.find(x => x.id === 'CRITICAL');
const highOption = severityFilter.options.find(x => x.id === 'HIGH'); const highOption = severityFilter.options.find(x => x.id === 'HIGH');
const existingFilters = {
filter1: ['some', 'value'],
filter2: ['other', 'values'],
};
describe('filters module mutations', () => { describe('filters module mutations', () => {
let state; let state;
...@@ -18,43 +24,36 @@ describe('filters module mutations', () => { ...@@ -18,43 +24,36 @@ describe('filters module mutations', () => {
describe('SET_FILTER', () => { describe('SET_FILTER', () => {
it.each` it.each`
options | expected options
${[]} | ${[]} ${[]}
${[criticalOption.id]} | ${[criticalOption.id.toLowerCase()]} ${[criticalOption.id]}
${[criticalOption.id, highOption.id]} | ${[criticalOption.id.toLowerCase(), highOption.id.toLowerCase()]} ${[criticalOption.id, highOption.id]}
`('sets the filter to $options', ({ options, expected }) => { `('sets the filter to $options', ({ options }) => {
mutations[SET_FILTER](state, { [severityFilter.id]: options }); mutations[SET_FILTER](state, { [severityFilter.id]: options });
expect(state.filters[severityFilter.id]).toEqual(expected); expect(state.filters[severityFilter.id]).toEqual(options);
}); });
it('sets multiple filters correctly with the right casing', () => { it('adds new filter to existing filters', () => {
const filter1 = { oneWord: ['ABC', 'DEF'] }; const newFilter = { filter3: ['custom', 'filters'] };
const filter2 = { twoWords: ['123', '456'] }; state.filters = existingFilters;
const filter3 = { threeTotalWords: ['Abc123', 'dEF456'] }; mutations[SET_FILTER](state, newFilter);
mutations[SET_FILTER](state, filter1);
mutations[SET_FILTER](state, filter2);
mutations[SET_FILTER](state, filter3);
expect(state.filters).toMatchObject({ expect(state.filters).toEqual({ ...existingFilters, ...newFilter });
one_word: ['abc', 'def'],
two_words: ['123', '456'],
three_total_words: ['abc123', 'def456'],
});
}); });
}); });
describe('TOGGLE_HIDE_DISMISSED', () => { describe('SET_HIDE_DISMISSED', () => {
it('toggles scope filter', () => { it.each(Object.values(DISMISSAL_STATES))(`sets scope filter to "%s"`, value => {
const toggleAndCheck = expected => { mutations[SET_HIDE_DISMISSED](state, value);
mutations[TOGGLE_HIDE_DISMISSED](state); expect(state.filters.scope).toBe(value);
expect(state.filters.scope).toBe(expected); });
};
it('adds scope filter to existing filters', () => {
state.filters = existingFilters;
mutations[SET_HIDE_DISMISSED](state, 'dismissed');
toggleAndCheck('all'); expect(state.filters).toEqual({ ...existingFilters, scope: 'dismissed' });
toggleAndCheck('dismissed');
toggleAndCheck('all');
}); });
}); });
}); });
import createStore from 'ee/security_dashboard/store/index'; import createStore from 'ee/security_dashboard/store/index';
import { import {
SET_FILTER, SET_FILTER,
TOGGLE_HIDE_DISMISSED, SET_HIDE_DISMISSED,
} from 'ee/security_dashboard/store/modules/filters/mutation_types'; } from 'ee/security_dashboard/store/modules/filters/mutation_types';
function expectRefreshDispatches(store, payload) { function expectRefreshDispatches(store, payload) {
...@@ -38,7 +38,7 @@ describe('mediator', () => { ...@@ -38,7 +38,7 @@ describe('mediator', () => {
}); });
it('triggers fetching vulnerabilities after "Hide dismissed" toggle changes', () => { it('triggers fetching vulnerabilities after "Hide dismissed" toggle changes', () => {
store.commit(`filters/${TOGGLE_HIDE_DISMISSED}`); store.commit(`filters/${SET_HIDE_DISMISSED}`);
expectRefreshDispatches(store, store.state.filters.filters); expectRefreshDispatches(store, store.state.filters.filters);
}); });
......
...@@ -24246,6 +24246,9 @@ msgstr "" ...@@ -24246,6 +24246,9 @@ msgstr ""
msgid "SecurityReports|Scan details" msgid "SecurityReports|Scan details"
msgstr "" msgstr ""
msgid "SecurityReports|Scanner"
msgstr ""
msgid "SecurityReports|Security Dashboard" msgid "SecurityReports|Security Dashboard"
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