Commit 37cd1364 authored by Clement Ho's avatar Clement Ho

Merge branch '12846-update-security-dashboard-layout-for-improved-usability' into 'master'

Update Security Dashboard layout for improved usability

Closes #12846

See merge request gitlab-org/gitlab-ee!15050
parents b01101a3 be636d8b
......@@ -121,18 +121,25 @@ export default {
</script>
<template>
<div>
<filters />
<vulnerability-count-list :class="{ 'mb-0': isLockedToProject }" />
<section>
<header>
<filters />
</header>
<vulnerability-chart v-if="!isLockedToProject" />
<vulnerability-count-list v-if="isLockedToProject" class="mb-0" />
<h4 v-if="!isLockedToProject" class="my-4">{{ __('Vulnerability List') }}</h4>
<div class="row mt-4">
<main role="main" class="col" :class="{ 'col-xl-7': !isLockedToProject }">
<security-dashboard-table
:dashboard-documentation="dashboardDocumentation"
:empty-state-svg-path="emptyStateSvgPath"
/>
</main>
<security-dashboard-table
:dashboard-documentation="dashboardDocumentation"
:empty-state-svg-path="emptyStateSvgPath"
/>
<aside v-if="!isLockedToProject" class="col-xl-5">
<vulnerability-chart />
</aside>
</div>
<issue-modal
:modal="modal"
......@@ -153,5 +160,5 @@ export default {
@revertDismissVulnerability="undoDismiss({ vulnerability })"
@downloadPatch="downloadPatch({ vulnerability })"
/>
</div>
</section>
</template>
......@@ -53,7 +53,7 @@ export default {
</script>
<template>
<div class="ci-table">
<div class="ci-table js-security-dashboard-table">
<div
class="gl-responsive-table-row table-row-header vulnerabilities-row-header px-2"
role="row"
......
......@@ -3,7 +3,7 @@ import _ from 'underscore';
import dateFormat from 'dateformat';
import { mapState, mapGetters, mapActions } from 'vuex';
import GlLineChart from '@gitlab/ui/dist/components/charts/line/line';
import { __ } from '~/locale';
import { __, s__, sprintf } from '~/locale';
import ChartTooltip from './vulnerability_chart_tooltip.vue';
import ChartButtons from './vulnerability_chart_buttons.vue';
import { DAY_IN_MS, DAYS } from '../store/modules/vulnerabilities/constants';
......@@ -70,9 +70,9 @@ export default {
options() {
return {
grid: {
bottom: 70,
left: 75,
right: 15,
bottom: 30,
left: 30,
right: 20,
top: 10,
},
tooltip: {
......@@ -87,14 +87,7 @@ export default {
margin: 8,
},
maxInterval: DAY_IN_MS * this.vulnerabilitiesHistoryMaxDayInterval,
min: Date.now() - DAY_IN_MS * this.vulnerabilitiesHistoryDayRange,
name: __('Date'),
nameGap: 35,
nameLocation: 'center',
nameTextStyle: {
color: '#2e2e2e',
fontWeight: 'bold',
},
min: this.startDate,
type: 'time',
},
yAxis: {
......@@ -102,19 +95,21 @@ export default {
color: '#707070',
},
boundaryGap: [0, '5%'],
name: __('Vulnerabilities'),
nameGap: 42,
nameLocation: 'center',
nameRotation: 90,
nameTextStyle: {
color: '#2e2e2e',
fontWeight: 'bold',
},
minInterval: 1,
type: 'value',
},
};
},
startDate() {
return Date.now() - DAY_IN_MS * this.vulnerabilitiesHistoryDayRange;
},
dateInfo() {
const formattedStartDate = dateFormat(this.startDate, 'mmmm dS');
return sprintf(s__('VulnerabilityChart|%{formattedStartDate} to today'), {
formattedStartDate,
});
},
days() {
const { $options } = this;
return [$options.DAYS.THIRTY, $options.DAYS.SIXTY, $options.DAYS.NINETY];
......@@ -133,17 +128,21 @@ export default {
</script>
<template>
<div>
<div class="d-flex justify-content-between">
<h4 class="my-4">{{ __('Vulnerability Chart') }}</h4>
<div class="align-self-center">
<chart-buttons
:days="days"
:active-day="vulnerabilitiesHistoryDayRange"
@click="setVulnerabilitiesHistoryDayRange"
/>
</div>
<section class="border rounded p-3">
<header>
<h4 class="mt-0 mb-1">
{{ __('Vulnerabilities over time') }}
</h4>
<p class="text-secondary mt-0 js-vulnerabilities-chart-time-info">
{{ dateInfo }}
</p>
</header>
<div class="align-self-center mb-3">
<chart-buttons
:days="days"
:active-day="vulnerabilitiesHistoryDayRange"
@click="setVulnerabilitiesHistoryDayRange"
/>
</div>
<div class="vulnerabilities-chart">
......@@ -151,11 +150,12 @@ export default {
<resizable-chart-container>
<gl-line-chart
slot-scope="{ width }"
class="js-vulnerabilities-chart-line-chart"
:width="width"
:option="options"
:data="series"
:format-tooltip-text="noop"
:include-legend-avg-max="false"
:include-legend-avg-max="true"
>
<span slot="tooltipTitle">{{ tooltipTitle }}</span>
<chart-tooltip slot="tooltipContent" :entries="tooltipEntries" />
......@@ -163,5 +163,5 @@ export default {
</resizable-chart-container>
</div>
</div>
</div>
</section>
</template>
......@@ -31,7 +31,7 @@ export default {
</script>
<template>
<div class="btn-group">
<div class="btn-group w-100">
<gl-button
v-for="day in days"
:key="day"
......
---
title: Update Security Dashboard for improved usability
merge_request: 15050
author:
type: changed
......@@ -40,9 +40,14 @@ describe 'Group overview', :js do
it 'displays the Security Dashboard view' do
visit group_path(group)
page.within(find('.content')) do
expect(page).to have_content 'Vulnerability Chart'
expect(page).to have_content 'Vulnerability List'
page.within(find('main')) do
expect(page).to have_selector('.js-security-dashboard-table')
end
page.within(find('aside')) do
expect(page).to have_content 'Vulnerabilities over time'
expect(page).to have_selector('.js-vulnerabilities-chart-time-info')
expect(page).to have_selector('.js-vulnerabilities-chart-line-chart')
end
end
end
......
......@@ -63,16 +63,31 @@ describe('Card security reports app', () => {
createComponent();
});
it('render sub components', () => {
it('renders the filters', () => {
expect(wrapper.find(Filters).exists()).toBe(true);
});
it('renders the security dashboard table ', () => {
expect(wrapper.find(SecurityDashboardTable).exists()).toBe(true);
});
it('renders the vulnerability chart', () => {
expect(wrapper.find(VulnerabilityChart).exists()).toBe(true);
expect(wrapper.find(VulnerabilityCountList).exists()).toBe(true);
});
it('fetches projects and does not lock projects filter', () => {
it('does not render the vulnerability count list', () => {
expect(wrapper.find(VulnerabilityCountList).exists()).toBe(false);
});
it('does not lock to a project', () => {
expect(wrapper.vm.isLockedToProject).toBe(false);
});
it('fetches projects', () => {
expect(fetchProjectsSpy).toHaveBeenCalled();
});
it('does not lock project filters', () => {
expect(lockFilterSpy).not.toHaveBeenCalled();
});
});
......@@ -89,9 +104,19 @@ describe('Card security reports app', () => {
});
});
it('locks to given project and does not fetch projects', () => {
it('renders the vulnerability count list', () => {
expect(wrapper.find(VulnerabilityCountList).exists()).toBe(true);
});
it('locks to a given project', () => {
expect(wrapper.vm.isLockedToProject).toBe(true);
});
it('does not fetch projects', () => {
expect(fetchProjectsSpy).not.toHaveBeenCalled();
});
it('locks the filters to a given project', () => {
expect(lockFilterSpy).toHaveBeenCalledWith({
filterId: 'project_id',
optionId: project.id,
......
......@@ -4566,9 +4566,6 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
msgid "Date"
msgstr ""
msgid "Date picker"
msgstr ""
......@@ -17063,13 +17060,13 @@ msgstr ""
msgid "Vulnerabilities"
msgstr ""
msgid "Vulnerability Chart"
msgid "Vulnerabilities over time"
msgstr ""
msgid "Vulnerability List"
msgid "Vulnerability-Check requires one or more merge request approvals only if high or critical security vulnerabilities are detected."
msgstr ""
msgid "Vulnerability-Check requires one or more merge request approvals only if high or critical security vulnerabilities are detected."
msgid "VulnerabilityChart|%{formattedStartDate} to today"
msgstr ""
msgid "Vulnerability|Class"
......
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