Commit 11464845 authored by Markus Koller's avatar Markus Koller

Merge branch '223924-remove-banner' into 'master'

Remove the introduction banner once and for all

See merge request gitlab-org/gitlab!38967
parents e676795f e02f19e2
<script>
import { GlBanner } from '@gitlab/ui';
import Cookies from 'js-cookie';
import { parseBoolean } from '~/lib/utils/common_utils';
import axios from '~/lib/utils/axios_utils';
import ProjectVulnerabilitiesApp from './project_vulnerabilities.vue';
import ReportsNotConfigured from './empty_states/reports_not_configured.vue';
import SecurityDashboardLayout from './security_dashboard_layout.vue';
......@@ -20,7 +16,6 @@ export default {
VulnerabilitiesCountList,
CsvExportButton,
Filters,
GlBanner,
},
props: {
securityDashboardHelpPath: {
......@@ -42,25 +37,10 @@ export default {
required: false,
default: '',
},
showIntroductionBanner: {
type: Boolean,
required: true,
},
userCalloutId: {
type: String,
required: false,
default: '',
},
userCalloutsPath: {
type: String,
required: false,
default: '',
},
},
data() {
return {
filters: {},
isBannerVisible: this.showIntroductionBanner && !parseBoolean(Cookies.get(BANNER_COOKIE_KEY)), // The and statement is for backward compatibility. See https://gitlab.com/gitlab-org/gitlab/-/issues/213671 for more information.
};
},
inject: ['dashboardDocumentation'],
......@@ -68,13 +48,6 @@ export default {
handleFilterChange(filters) {
this.filters = filters;
},
handleBannerClose() {
this.isBannerVisible = false;
axios.post(this.userCalloutsPath, {
feature_name: this.userCalloutId,
});
},
},
};
</script>
......@@ -84,23 +57,6 @@ export default {
<template v-if="hasVulnerabilities">
<security-dashboard-layout>
<template #header>
<gl-banner
v-if="isBannerVisible"
class="mt-4"
variant="introduction"
:title="s__('SecurityReports|Introducing standalone vulnerabilities')"
:button-text="s__('SecurityReports|Learn more')"
:button-link="dashboardDocumentation"
@close="handleBannerClose"
>
<div class="mb-2">
{{
s__(
'SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans.',
)
}}
</div>
</gl-banner>
<div class="mt-4 d-flex">
<h4 class="flex-grow mt-0 mb-0">{{ __('Vulnerabilities') }}</h4>
<csv-export-button :vulnerabilities-export-endpoint="vulnerabilitiesExportEndpoint" />
......
import Vue from 'vue';
import { DASHBOARD_TYPES } from 'ee/security_dashboard/store/constants';
import { parseBoolean } from '~/lib/utils/common_utils';
import FirstClassProjectSecurityDashboard from './components/first_class_project_security_dashboard.vue';
import FirstClassGroupSecurityDashboard from './components/first_class_group_security_dashboard.vue';
import FirstClassInstanceSecurityDashboard from './components/first_class_instance_security_dashboard.vue';
......@@ -42,9 +41,6 @@ export default (el, dashboardType) => {
if (dashboardType === DASHBOARD_TYPES.PROJECT) {
component = FirstClassProjectSecurityDashboard;
props.projectFullPath = el.dataset.projectFullPath;
props.userCalloutId = el.dataset.userCalloutId;
props.userCalloutsPath = el.dataset.userCalloutsPath;
props.showIntroductionBanner = parseBoolean(el.dataset.showIntroductionBanner);
} else if (dashboardType === DASHBOARD_TYPES.GROUP) {
component = FirstClassGroupSecurityDashboard;
props.groupFullPath = el.dataset.groupFullPath;
......
......@@ -198,10 +198,7 @@ module EE
dashboard_documentation: help_page_path('user/application_security/security_dashboard/index'),
not_enabled_scanners_help_path: help_page_path('user/application_security/index', anchor: 'quick-start'),
no_pipeline_run_scanners_help_path: new_project_pipeline_path(project),
security_dashboard_help_path: help_page_path('user/application_security/security_dashboard/index'),
user_callouts_path: user_callouts_path,
user_callout_id: UserCalloutsHelper::STANDALONE_VULNERABILITIES_INTRODUCTION_BANNER,
show_introduction_banner: show_standalone_vulnerabilities_introduction_banner?.to_s
security_dashboard_help_path: help_page_path('user/application_security/security_dashboard/index')
}
end
end
......
......@@ -12,7 +12,6 @@ module EE
THREAT_MONITORING_INFO = 'threat_monitoring_info'
ACCOUNT_RECOVERY_REGULAR_CHECK = 'account_recovery_regular_check'
USERS_OVER_LICENSE_BANNER = 'users_over_license_banner'
STANDALONE_VULNERABILITIES_INTRODUCTION_BANNER = 'standalone_vulnerabilities_introduction_banner'
ACTIVE_USER_COUNT_THRESHOLD = 'active_user_count_threshold'
PERSONAL_ACCESS_TOKEN_EXPIRY = 'personal_access_token_expiry'
......@@ -84,10 +83,6 @@ module EE
!user_dismissed?(THREAT_MONITORING_INFO)
end
def show_standalone_vulnerabilities_introduction_banner?
!user_dismissed?(STANDALONE_VULNERABILITIES_INTRODUCTION_BANNER)
end
def show_token_expiry_notification?
return false unless current_user
......
......@@ -20,7 +20,6 @@ module EE
threat_monitoring_info: 11,
account_recovery_regular_check: 12,
users_over_license_banner: 16,
standalone_vulnerabilities_introduction_banner: 17,
active_user_count_threshold: 18,
buy_pipeline_minutes_notification_dot: 19
)
......
import { shallowMount } from '@vue/test-utils';
import { GlBanner } from '@gitlab/ui';
import Cookies from 'js-cookie';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import waitForPromises from 'helpers/wait_for_promises';
import { TEST_HOST } from 'helpers/test_constants';
import FirstClassProjectSecurityDashboard, {
BANNER_COOKIE_KEY,
} from 'ee/security_dashboard/components/first_class_project_security_dashboard.vue';
import FirstClassProjectSecurityDashboard from 'ee/security_dashboard/components/first_class_project_security_dashboard.vue';
import Filters from 'ee/security_dashboard/components/first_class_vulnerability_filters.vue';
import SecurityDashboardLayout from 'ee/security_dashboard/components/security_dashboard_layout.vue';
import ProjectVulnerabilitiesApp from 'ee/security_dashboard/components/project_vulnerabilities.vue';
......@@ -20,9 +13,6 @@ const props = {
projectFullPath: '/group/project',
securityDashboardHelpPath: '/security/dashboard/help-path',
vulnerabilitiesExportEndpoint: '/vulnerabilities/exports',
userCalloutId: 'standalone_vulnerabilities_introduction_banner',
userCalloutsPath: `${TEST_HOST}/user_callouts`,
showIntroductionBanner: false,
};
const provide = {
......@@ -39,7 +29,6 @@ describe('First class Project Security Dashboard component', () => {
const findVulnerabilities = () => wrapper.find(ProjectVulnerabilitiesApp);
const findUnconfiguredState = () => wrapper.find(ReportsNotConfigured);
const findCsvExportButton = () => wrapper.find(CsvExportButton);
const findIntroductionBanner = () => wrapper.find(GlBanner);
const createComponent = options => {
wrapper = shallowMount(FirstClassProjectSecurityDashboard, {
......@@ -86,60 +75,6 @@ describe('First class Project Security Dashboard component', () => {
});
});
describe('when user visits for the first time', () => {
let mockAxios;
beforeEach(() => {
mockAxios = new MockAdapter(axios);
mockAxios.onPost(props.userCalloutsPath, { feature_name: props.userCalloutId }).reply(200);
createComponent({ props: { hasVulnerabilities: true, showIntroductionBanner: true } });
});
afterEach(() => {
mockAxios.restore();
});
it('displays a banner which the title highlights the new functionality', () => {
expect(findIntroductionBanner().text()).toContain('Introducing standalone vulnerabilities');
});
it('displays a banner which the content describes the new functionality', () => {
expect(findIntroductionBanner().text()).toContain(
'Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans.',
);
});
it('links the banner to the proper documentation page', () => {
expect(findIntroductionBanner().props('buttonLink')).toBe(provide.dashboardDocumentation);
});
it('hides the banner when the user clicks on the dismiss button', () => {
findIntroductionBanner()
.find('button.close')
.trigger('click');
return waitForPromises().then(() => {
expect(findIntroductionBanner().exists()).toBe(false);
expect(mockAxios.history.post).toHaveLength(1);
});
});
});
describe('when user already dismissed the banner in the past', () => {
beforeEach(() => {
Cookies.set(BANNER_COOKIE_KEY, 'true');
createComponent({ props: { hasVulnerabilities: true, showIntroductionBanner: true } });
});
afterEach(() => {
Cookies.remove(BANNER_COOKIE_KEY);
});
it('does not display the banner despite showIntroductionBanner is true', () => {
expect(findIntroductionBanner().exists()).toBe(false);
});
});
describe('with filter data', () => {
beforeEach(() => {
createComponent({
......
......@@ -384,26 +384,4 @@ RSpec.describe EE::UserCalloutsHelper do
end
end
end
describe '.show_standalone_vulnerabilities_introduction_banner?' do
subject { helper.show_standalone_vulnerabilities_introduction_banner? }
let(:user) { create(:user) }
before do
allow(helper).to receive(:current_user).and_return(user)
end
context 'when the introduction banner has not been dismissed' do
it { is_expected.to be_truthy }
end
context 'when the introduction banner was dismissed' do
before do
create(:user_callout, user: user, feature_name: described_class::STANDALONE_VULNERABILITIES_INTRODUCTION_BANNER)
end
it { is_expected.to be_falsy }
end
end
end
......@@ -157,9 +157,6 @@ RSpec.describe ProjectsHelper do
empty_state_svg_path: start_with('/assets/illustrations/security-dashboard-empty-state'),
dashboard_documentation: '/help/user/application_security/security_dashboard/index',
security_dashboard_help_path: '/help/user/application_security/security_dashboard/index',
user_callouts_path: '/-/user_callouts',
user_callout_id: 'standalone_vulnerabilities_introduction_banner',
show_introduction_banner: 'true',
not_enabled_scanners_help_path: help_page_path('user/application_security/index', anchor: 'quick-start'),
no_pipeline_run_scanners_help_path: new_project_pipeline_path(project)
}
......
......@@ -21498,9 +21498,6 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
msgstr ""
msgid "SecurityReports|Edit dashboard"
msgstr ""
......@@ -21522,15 +21519,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
msgid "SecurityReports|Introducing standalone vulnerabilities"
msgstr ""
msgid "SecurityReports|Issue Created"
msgstr ""
msgid "SecurityReports|Learn more"
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
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