Skip to content
代码片段 群组 项目
未验证 提交 89a336ce 编辑于 作者: Alexander Turinske's avatar Alexander Turinske 提交者: GitLab
浏览文件

Notify user of policy name change

- show previous name below new name
- show alert on policy list
- use local storage for alert
- update tests

Changelog: changed

EE: true
上级 4e90a861
No related branches found
No related tags found
无相关合并请求
<script> <script>
import { GlAlert, GlButton, GlIcon, GlSprintf } from '@gitlab/ui'; import { GlAlert, GlButton, GlIcon, GlSprintf } from '@gitlab/ui';
import { joinPaths } from '~/lib/utils/url_utility'; import { joinPaths } from '~/lib/utils/url_utility';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { NEW_POLICY_BUTTON_TEXT } from '../constants'; import { NEW_POLICY_BUTTON_TEXT } from '../constants';
...@@ -8,12 +9,14 @@ import ExperimentFeaturesBanner from './experiment_features_banner.vue'; ...@@ -8,12 +9,14 @@ import ExperimentFeaturesBanner from './experiment_features_banner.vue';
import ProjectModal from './project_modal.vue'; import ProjectModal from './project_modal.vue';
export default { export default {
BANNER_STORAGE_KEY: 'security_policies_scan_result_name_change',
components: { components: {
ExperimentFeaturesBanner, ExperimentFeaturesBanner,
GlAlert, GlAlert,
GlButton, GlButton,
GlIcon, GlIcon,
GlSprintf, GlSprintf,
LocalStorageSync,
ProjectModal, ProjectModal,
}, },
mixins: [glFeatureFlagMixin()], mixins: [glFeatureFlagMixin()],
...@@ -32,11 +35,16 @@ export default { ...@@ -32,11 +35,16 @@ export default {
newPolicyButtonText: NEW_POLICY_BUTTON_TEXT, newPolicyButtonText: NEW_POLICY_BUTTON_TEXT,
editPolicyProjectButtonText: s__('SecurityOrchestration|Edit policy project'), editPolicyProjectButtonText: s__('SecurityOrchestration|Edit policy project'),
viewPolicyProjectButtonText: s__('SecurityOrchestration|View policy project'), viewPolicyProjectButtonText: s__('SecurityOrchestration|View policy project'),
migrationTitle: s__('SecurityOrchestration|Updated policy name'),
migrationDescription: s__(
'SecurityOrchestration|The %{oldNameStart}Scan result policy%{oldNameEnd} is now called the %{newNameStart}Merge request approval policy%{newNameEnd} to better align with its purpose. For more details, see the release notes.',
),
}, },
data() { data() {
return { return {
projectIsBeingLinked: false, projectIsBeingLinked: false,
showAlert: false, showAlert: false,
migrationAlertDismissed: false,
alertVariant: '', alertVariant: '',
alertText: '', alertText: '',
modalVisible: false, modalVisible: false,
...@@ -75,6 +83,9 @@ export default { ...@@ -75,6 +83,9 @@ export default {
dismissAlert() { dismissAlert() {
this.showAlert = false; this.showAlert = false;
}, },
dismissMigrationAlert() {
this.migrationAlertDismissed = true;
},
showNewPolicyModal() { showNewPolicyModal() {
this.modalVisible = true; this.modalVisible = true;
}, },
...@@ -88,6 +99,7 @@ export default { ...@@ -88,6 +99,7 @@ export default {
class="gl-mt-3" class="gl-mt-3"
:dismissible="true" :dismissible="true"
:variant="alertVariant" :variant="alertVariant"
data-testid="error-alert"
@dismiss="dismissAlert" @dismiss="dismissAlert"
> >
{{ alertText }} {{ alertText }}
...@@ -151,5 +163,27 @@ export default { ...@@ -151,5 +163,27 @@ export default {
@updating-project="isUpdatingProject" @updating-project="isUpdatingProject"
/> />
</header> </header>
<local-storage-sync
v-model="migrationAlertDismissed"
:storage-key="$options.BANNER_STORAGE_KEY"
>
<gl-alert
v-if="!migrationAlertDismissed"
class="gl-mt-3 gl-mb-6"
:dismissible="true"
:title="$options.i18n.migrationTitle"
data-testid="migration-alert"
@dismiss="dismissMigrationAlert()"
>
<gl-sprintf :message="$options.i18n.migrationDescription">
<template #oldName="{ content }">
<b>{{ content }}</b>
</template>
<template #newName="{ content }">
<b>{{ content }}</b>
</template>
</gl-sprintf>
</gl-alert>
</local-storage-sync>
</div> </div>
</template> </template>
<script> <script>
import shieldCheckIllustrationUrl from '@gitlab/svgs/dist/illustrations/secure-sm.svg?url'; import shieldCheckIllustrationUrl from '@gitlab/svgs/dist/illustrations/secure-sm.svg?url';
import magnifyingGlassIllustrationUrl from '@gitlab/svgs/dist/illustrations/search-sm.svg?url'; import magnifyingGlassIllustrationUrl from '@gitlab/svgs/dist/illustrations/search-sm.svg?url';
import { GlButton, GlCard, GlIcon, GlSprintf } from '@gitlab/ui'; import { GlButton, GlCard, GlIcon, GlPopover, GlSprintf } from '@gitlab/ui';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import SafeHtml from '~/vue_shared/directives/safe_html'; import SafeHtml from '~/vue_shared/directives/safe_html';
import { s__, __ } from '~/locale'; import { s__, __ } from '~/locale';
...@@ -12,6 +12,11 @@ const i18n = { ...@@ -12,6 +12,11 @@ const i18n = {
examples: __('Examples'), examples: __('Examples'),
selectPolicy: s__('SecurityOrchestration|Select policy'), selectPolicy: s__('SecurityOrchestration|Select policy'),
scanResultPolicyTitle: s__('SecurityOrchestration|Merge request approval policy'), scanResultPolicyTitle: s__('SecurityOrchestration|Merge request approval policy'),
scanResultPolicyTitlePopoverTitle: s__('SecurityOrchestration|Updated policy name'),
scanResultPolicyTitlePopoverDesc: s__(
'SecurityOrchestration|The Scan result policy is now called the Merge request approval policy to better align with its purpose. For more details, see the release notes.',
),
scanResultPolicySubTitle: s__('SecurityOrchestraation|(Formerly Scan result policy)'),
scanResultPolicyDesc: s__( scanResultPolicyDesc: s__(
'SecurityOrchestration|Use a merge request approval policy to create rules that check for security vulnerabilities and license compliance before merging a merge request.', 'SecurityOrchestration|Use a merge request approval policy to create rules that check for security vulnerabilities and license compliance before merging a merge request.',
), ),
...@@ -35,6 +40,7 @@ export default { ...@@ -35,6 +40,7 @@ export default {
GlButton, GlButton,
GlCard, GlCard,
GlIcon, GlIcon,
GlPopover,
GlSprintf, GlSprintf,
}, },
directives: { directives: {
...@@ -55,11 +61,14 @@ export default { ...@@ -55,11 +61,14 @@ export default {
text: POLICY_TYPE_COMPONENT_OPTIONS.scanResult.text.toLowerCase(), text: POLICY_TYPE_COMPONENT_OPTIONS.scanResult.text.toLowerCase(),
urlParameter: POLICY_TYPE_COMPONENT_OPTIONS.approval.urlParameter, urlParameter: POLICY_TYPE_COMPONENT_OPTIONS.approval.urlParameter,
title: i18n.scanResultPolicyTitle, title: i18n.scanResultPolicyTitle,
titlePopover: i18n.scanResultPolicyTitlePopoverTitle,
titlePopoverDesc: i18n.scanResultPolicyTitlePopoverDesc,
description: i18n.scanResultPolicyDesc, description: i18n.scanResultPolicyDesc,
example: i18n.scanResultPolicyExample, example: i18n.scanResultPolicyExample,
imageSrc: shieldCheckIllustrationUrl, imageSrc: shieldCheckIllustrationUrl,
hasMax: this.maxActiveScanResultPoliciesReached, hasMax: this.maxActiveScanResultPoliciesReached,
maxPoliciesAllowed: this.maxScanResultPoliciesAllowed, maxPoliciesAllowed: this.maxScanResultPoliciesAllowed,
subtitle: i18n.scanResultPolicySubTitle,
}, },
{ {
text: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.text.toLowerCase(), text: POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.text.toLowerCase(),
...@@ -93,7 +102,27 @@ export default { ...@@ -93,7 +102,27 @@ export default {
<img :alt="option.title" aria-hidden="true" :src="option.imageSrc" /> <img :alt="option.title" aria-hidden="true" :src="option.imageSrc" />
</div> </div>
<div class="gl-display-flex gl-flex-direction-column"> <div class="gl-display-flex gl-flex-direction-column">
<h4 class="gl-mt-0">{{ option.title }}</h4> <div>
<h4 class="gl-display-inline-block gl-my-0">{{ option.title }}</h4>
<gl-icon
v-if="option.titlePopover"
id="change-icon"
name="status-active"
:size="12"
class="gl-display-inline-block gl-text-blue-500"
/>
<gl-popover
v-if="option.titlePopover"
triggers="hover focus"
:title="option.titlePopover"
:show-close-button="false"
placement="top"
target="change-icon"
:content="option.titlePopoverDesc"
:show="false"
/>
</div>
<p v-if="option.subtitle" class="gl-text-gray-400">{{ option.subtitle }}</p>
<p>{{ option.description }}</p> <p>{{ option.description }}</p>
<h5>{{ $options.i18n.examples }}</h5> <h5>{{ $options.i18n.examples }}</h5>
<p class="gl-flex-grow-1">{{ option.example }}</p> <p class="gl-flex-grow-1">{{ option.example }}</p>
......
import { GlAlert, GlButton, GlSprintf } from '@gitlab/ui'; import { GlButton, GlSprintf } from '@gitlab/ui';
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import ExperimentFeaturesBanner from 'ee/security_orchestration/components/policies/experiment_features_banner.vue'; import ExperimentFeaturesBanner from 'ee/security_orchestration/components/policies/experiment_features_banner.vue';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import ListHeader from 'ee/security_orchestration/components/policies/list_header.vue'; import ListHeader from 'ee/security_orchestration/components/policies/list_header.vue';
import ProjectModal from 'ee/security_orchestration/components/policies/project_modal.vue'; import ProjectModal from 'ee/security_orchestration/components/policies/project_modal.vue';
import { NEW_POLICY_BUTTON_TEXT } from 'ee/security_orchestration/components/constants'; import { NEW_POLICY_BUTTON_TEXT } from 'ee/security_orchestration/components/constants';
...@@ -13,7 +14,8 @@ describe('List Header Component', () => { ...@@ -13,7 +14,8 @@ describe('List Header Component', () => {
const newPolicyPath = '/path/to/new/policy/page'; const newPolicyPath = '/path/to/new/policy/page';
const projectLinkSuccessText = 'Project was linked successfully.'; const projectLinkSuccessText = 'Project was linked successfully.';
const findAlert = () => wrapper.findComponent(GlAlert); const findErrorAlert = () => wrapper.findByTestId('error-alert');
const findMigrationAlert = () => wrapper.findByTestId('migration-alert');
const findScanNewPolicyModal = () => wrapper.findComponent(ProjectModal); const findScanNewPolicyModal = () => wrapper.findComponent(ProjectModal);
const findHeader = () => wrapper.findByRole('heading'); const findHeader = () => wrapper.findByRole('heading');
const findMoreInformationLink = () => wrapper.findComponent(GlButton); const findMoreInformationLink = () => wrapper.findComponent(GlButton);
...@@ -22,6 +24,7 @@ describe('List Header Component', () => { ...@@ -22,6 +24,7 @@ describe('List Header Component', () => {
const findNewPolicyButton = () => wrapper.findByTestId('new-policy-button'); const findNewPolicyButton = () => wrapper.findByTestId('new-policy-button');
const findSubheader = () => wrapper.findByTestId('policies-subheader'); const findSubheader = () => wrapper.findByTestId('policies-subheader');
const findExperimentFeaturesBanner = () => wrapper.findComponent(ExperimentFeaturesBanner); const findExperimentFeaturesBanner = () => wrapper.findComponent(ExperimentFeaturesBanner);
const findLocalStorageSync = () => wrapper.findComponent(LocalStorageSync);
const linkSecurityPoliciesProject = async () => { const linkSecurityPoliciesProject = async () => {
findScanNewPolicyModal().vm.$emit('project-updated', { findScanNewPolicyModal().vm.$emit('project-updated', {
...@@ -42,8 +45,8 @@ describe('List Header Component', () => { ...@@ -42,8 +45,8 @@ describe('List Header Component', () => {
...provide, ...provide,
}, },
stubs: { stubs: {
GlSprintf,
GlButton, GlButton,
GlSprintf,
}, },
}); });
}; };
...@@ -64,7 +67,7 @@ describe('List Header Component', () => { ...@@ -64,7 +67,7 @@ describe('List Header Component', () => {
status | component | findFn | exists status | component | findFn | exists
${'does'} | ${'edit policy project button'} | ${findEditPolicyProjectButton} | ${true} ${'does'} | ${'edit policy project button'} | ${findEditPolicyProjectButton} | ${true}
${'does not'} | ${'view policy project button'} | ${findViewPolicyProjectButton} | ${false} ${'does not'} | ${'view policy project button'} | ${findViewPolicyProjectButton} | ${false}
${'does not'} | ${'alert component'} | ${findAlert} | ${false} ${'does not'} | ${'alert component'} | ${findErrorAlert} | ${false}
${'does'} | ${'header'} | ${findHeader} | ${true} ${'does'} | ${'header'} | ${findHeader} | ${true}
`('$status display the $component', ({ findFn, exists }) => { `('$status display the $component', ({ findFn, exists }) => {
expect(findFn().exists()).toBe(exists); expect(findFn().exists()).toBe(exists);
...@@ -93,7 +96,7 @@ describe('List Header Component', () => { ...@@ -93,7 +96,7 @@ describe('List Header Component', () => {
}); });
it('displays the alert component when scan new modal policy emits event', () => { it('displays the alert component when scan new modal policy emits event', () => {
expect(findAlert().text()).toBe(projectLinkSuccessText); expect(findErrorAlert().text()).toBe(projectLinkSuccessText);
expect(wrapper.emitted('update-policy-list')).toStrictEqual([ expect(wrapper.emitted('update-policy-list')).toStrictEqual([
[ [
{ {
...@@ -107,7 +110,20 @@ describe('List Header Component', () => { ...@@ -107,7 +110,20 @@ describe('List Header Component', () => {
it('hides the previous alert when scan new modal policy is processing a new link', async () => { it('hides the previous alert when scan new modal policy is processing a new link', async () => {
findScanNewPolicyModal().vm.$emit('updating-project'); findScanNewPolicyModal().vm.$emit('updating-project');
await nextTick(); await nextTick();
expect(findAlert().exists()).toBe(false); expect(findErrorAlert().exists()).toBe(false);
});
});
describe('migration alert', () => {
it('displays the migration alert', () => {
expect(findLocalStorageSync().exists()).toBe(true);
expect(findMigrationAlert().exists()).toBe(true);
});
it('dismisses the alert when the dismiss button is clicked', async () => {
await findMigrationAlert().vm.$emit('dismiss');
expect(findMigrationAlert().exists()).toBe(false);
expect(findLocalStorageSync().props().value).toBe(true);
}); });
}); });
}); });
......
...@@ -61,7 +61,7 @@ describe('SettingPopover', () => { ...@@ -61,7 +61,7 @@ describe('SettingPopover', () => {
}); });
it('permanently dismisses the popover when the popover button is clicked', async () => { it('permanently dismisses the popover when the popover button is clicked', async () => {
createComponent({ propsData: { propsData: { showPopover: true } } }); createComponent({ propsData: { showPopover: true } });
await findButton().vm.$emit('click'); await findButton().vm.$emit('click');
expect(userCalloutDismissSpy).toHaveBeenCalled(); expect(userCalloutDismissSpy).toHaveBeenCalled();
}); });
......
...@@ -44373,6 +44373,9 @@ msgstr "" ...@@ -44373,6 +44373,9 @@ msgstr ""
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request" msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr "" msgstr ""
   
msgid "SecurityOrchestraation|(Formerly Scan result policy)"
msgstr ""
msgid "SecurityOrchestration| and " msgid "SecurityOrchestration| and "
msgstr "" msgstr ""
   
...@@ -44894,6 +44897,12 @@ msgstr "" ...@@ -44894,6 +44897,12 @@ msgstr ""
msgid "SecurityOrchestration|Summary" msgid "SecurityOrchestration|Summary"
msgstr "" msgstr ""
   
msgid "SecurityOrchestration|The %{oldNameStart}Scan result policy%{oldNameEnd} is now called the %{newNameStart}Merge request approval policy%{newNameEnd} to better align with its purpose. For more details, see the release notes."
msgstr ""
msgid "SecurityOrchestration|The Scan result policy is now called the Merge request approval policy to better align with its purpose. For more details, see the release notes."
msgstr ""
msgid "SecurityOrchestration|The following branches do not exist on this development project: %{branches}. Please review all protected branches to ensure the values are accurate before updating this policy." msgid "SecurityOrchestration|The following branches do not exist on this development project: %{branches}. Please review all protected branches to ensure the values are accurate before updating this policy."
msgstr "" msgstr ""
   
...@@ -44954,6 +44963,9 @@ msgstr "" ...@@ -44954,6 +44963,9 @@ msgstr ""
msgid "SecurityOrchestration|Update scan policies" msgid "SecurityOrchestration|Update scan policies"
msgstr "" msgstr ""
   
msgid "SecurityOrchestration|Updated policy name"
msgstr ""
msgid "SecurityOrchestration|Use a merge request approval policy to create rules that check for security vulnerabilities and license compliance before merging a merge request." msgid "SecurityOrchestration|Use a merge request approval policy to create rules that check for security vulnerabilities and license compliance before merging a merge request."
msgstr "" msgstr ""
   
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册