Commit d3e7bd2f authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch '336616-clarify-text-for-compliance-frameworks-options-in-projects' into 'master'

Update project compliance framework settings to be more clear

See merge request gitlab-org/gitlab!81889
parents 0768066c c1aec2f8
...@@ -5,6 +5,7 @@ import mountApprovals from 'ee/approvals/mount_project_settings'; ...@@ -5,6 +5,7 @@ import mountApprovals from 'ee/approvals/mount_project_settings';
import { initMergeOptionSettings } from 'ee/pages/projects/edit/merge_options'; import { initMergeOptionSettings } from 'ee/pages/projects/edit/merge_options';
import { initServicePingSettingsClickTracking } from 'ee/registration_features_discovery_message'; import { initServicePingSettingsClickTracking } from 'ee/registration_features_discovery_message';
import initProjectAdjournedDeleteButton from 'ee/projects/project_adjourned_delete_button'; import initProjectAdjournedDeleteButton from 'ee/projects/project_adjourned_delete_button';
import initProjectComplianceFrameworkEmptyState from 'ee/projects/project_compliance_framework_empty_state';
import mountStatusChecks from 'ee/status_checks/mount'; import mountStatusChecks from 'ee/status_checks/mount';
import groupsSelect from '~/groups_select'; import groupsSelect from '~/groups_select';
import UserCallout from '~/user_callout'; import UserCallout from '~/user_callout';
...@@ -19,5 +20,6 @@ mountApprovals(document.getElementById('js-mr-approvals-settings')); ...@@ -19,5 +20,6 @@ mountApprovals(document.getElementById('js-mr-approvals-settings'));
mountStatusChecks(document.getElementById('js-status-checks-settings')); mountStatusChecks(document.getElementById('js-status-checks-settings'));
initProjectAdjournedDeleteButton(); initProjectAdjournedDeleteButton();
initProjectComplianceFrameworkEmptyState();
initMergeOptionSettings(); initMergeOptionSettings();
initServicePingSettingsClickTracking(); initServicePingSettingsClickTracking();
<script>
import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui';
import { sprintf } from '~/locale';
import { PROJECT_COMPLIANCE_FRAMEWORK_I18N } from '../constants';
export default {
components: {
GlEmptyState,
GlSprintf,
GlLink,
},
props: {
groupName: {
type: String,
required: true,
},
groupPath: {
type: String,
required: true,
},
addFrameworkPath: {
type: String,
required: false,
default: '',
},
emptyStateSvgPath: {
type: String,
required: true,
},
},
computed: {
canEdit() {
return this.addFrameworkPath !== '';
},
description() {
return this.canEdit
? PROJECT_COMPLIANCE_FRAMEWORK_I18N.ownerDescription
: PROJECT_COMPLIANCE_FRAMEWORK_I18N.maintainerDescription;
},
buttonText() {
return this.canEdit
? sprintf(PROJECT_COMPLIANCE_FRAMEWORK_I18N.buttonText, { groupName: this.groupName })
: null;
},
buttonLink() {
return this.canEdit ? this.addFrameworkPath : null;
},
},
i18n: {
title: PROJECT_COMPLIANCE_FRAMEWORK_I18N.title,
},
};
</script>
<template>
<gl-empty-state
:description="$options.i18n.description"
:primary-button-text="buttonText"
:primary-button-link="buttonLink"
:svg-path="emptyStateSvgPath"
:svg-height="100"
compact
>
<template #title>
<h5 class="gl-mt-0">{{ $options.i18n.title }}</h5>
</template>
<template #description>
<gl-sprintf :message="description">
<template #link>
<gl-link :href="groupPath">{{ groupName }}</gl-link>
</template>
</gl-sprintf>
</template>
</gl-empty-state>
</template>
import { s__ } from '~/locale';
export const PROJECT_COMPLIANCE_FRAMEWORK_I18N = {
title: s__('ComplianceFramework|No compliance frameworks are set up yet'),
ownerDescription: s__(
'ComplianceFramework|Add a framework to %{linkStart}%{groupName}%{linkEnd} and it will appear here.',
),
maintainerDescription: s__(
'ComplianceFramework|After a framework is added to %{linkStart}%{groupName}%{linkEnd}, it will appear here.',
),
buttonText: s__('ComplianceFramework|Add framework in %{groupName}'),
};
import Vue from 'vue';
import ProjectComplianceFrameworkEmptyState from './components/project_compliance_framework_empty_state.vue';
export default (selector = '#js-project-compliance-framework-empty-state') => {
const el = document.querySelector(selector);
if (!el) return;
const { groupName, groupPath, addFrameworkPath, emptyStateSvgPath } = el.dataset;
// eslint-disable-next-line no-new
new Vue({
el,
render(createElement) {
return createElement(ProjectComplianceFrameworkEmptyState, {
props: {
groupName,
groupPath,
addFrameworkPath,
emptyStateSvgPath,
},
});
},
});
};
...@@ -258,6 +258,19 @@ module EE ...@@ -258,6 +258,19 @@ module EE
project.marked_for_deletion_at.present? project.marked_for_deletion_at.present?
end end
def project_compliance_framework_app_data(project, can_edit)
group = project.root_ancestor
{
group_name: group.name,
group_path: group_path(group),
empty_state_svg_path: image_path('illustrations/welcome/ee_trial.svg')
}.tap do |data|
if can_edit
data[:add_framework_path] = "#{edit_group_path(group)}#js-compliance-frameworks-settings"
end
end
end
private private
def remove_message_data(project) def remove_message_data(project)
......
...@@ -6,32 +6,25 @@ ...@@ -6,32 +6,25 @@
.settings-header .settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Compliance framework') %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Compliance framework')
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand') %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
%p= html_escape(_('Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}')) % { linkStart: compliance_framework_doc_link, linkEnd: '</a>'.html_safe } %p= html_escape(_('Select a compliance framework to apply to this project. %{linkStart}How are these added?%{linkEnd}')) % { linkStart: compliance_framework_doc_link, linkEnd: '</a>'.html_safe }
.settings-content .settings-content
= form_for @project, html: { multipart: true, class: "compliance-framework-form" }, authenticity_token: true do |f| - frameworks = @project.root_ancestor.compliance_management_frameworks
- frameworks = @project.namespace.root_ancestor.compliance_management_frameworks - if frameworks.any?
= form_for @project, html: { multipart: true, class: "compliance-framework-form" }, authenticity_token: true do |f|
.form-group .form-group
= f.fields_for :compliance_framework_setting, ComplianceManagement::ComplianceFramework::ProjectSettings.new do |cf| = f.fields_for :compliance_framework_setting, ComplianceManagement::ComplianceFramework::ProjectSettings.new do |cf|
= cf.label :framework, class: 'gl-font-weight-bold' do = cf.label :framework, class: 'gl-font-weight-bold' do
= _('Compliance framework') = _('Compliance framework')
- if user_has_edit_permissions - if user_has_edit_permissions
- if frameworks.any?
- selected_default_framework = @project.compliance_framework_setting&.compliance_management_framework&.id - selected_default_framework = @project.compliance_framework_setting&.compliance_management_framework&.id
= cf.select :framework, options_for_select(frameworks.map { |fw| [fw.name.truncate(88), fw.id] }, selected_default_framework), { selected: '', prompt: _('Choose your framework'), include_blank: _('None') }, { class: 'form-control', disabled: false } = cf.select :framework, options_for_select(frameworks.map { |fw| [fw.name.truncate(88), fw.id] }, selected_default_framework), { selected: '', prompt: _('Choose your framework'), include_blank: _('None') }, { class: 'form-control gl-w-full', disabled: false }
- else - else
%p.form-text.text-muted
= _("No compliance frameworks are in use. Create one from the %{link} section in Group Settings.").html_safe % { link: link_to('Compliance frameworks', edit_group_path(@project.namespace.root_ancestor)).html_safe }
- else
- if frameworks.any?
- selected_framework = @project.compliance_framework_setting&.compliance_management_framework&.name&.truncate(88) || _('None') - selected_framework = @project.compliance_framework_setting&.compliance_management_framework&.name&.truncate(88) || _('None')
= cf.text_field :framework, value: selected_framework, class: 'form-control read-only', disabled: true = cf.text_field :framework, value: selected_framework, class: 'form-control read-only', disabled: true
%p.form-text.text-muted %p.form-text.text-muted
= _("Customizable by owners.") = _("Owners can modify this selection.")
- else - if user_has_edit_permissions
%p.form-text.text-muted = f.submit _('Save changes'), class: "btn gl-button btn-confirm"
= _("No compliance frameworks are in use.") - else
#js-project-compliance-framework-empty-state{ data: project_compliance_framework_app_data(@project, user_has_edit_permissions) }
- if user_has_edit_permissions && frameworks.any?
= f.submit _('Save changes'), class: "btn gl-button btn-confirm"
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Project compliance framework empty state it matches the snapshot when "addFrameworkPath" is a string path 1`] = `
<gl-empty-state-stub
compact="true"
primarybuttonlink="/edit-group"
primarybuttontext="Add framework in group-name"
svgheight="100"
svgpath="/image.svg"
>
<h5
class="gl-mt-0"
>
No compliance frameworks are set up yet
</h5>
Add a framework to
<gl-link-stub
href="/group-path"
>
group-name
</gl-link-stub>
and it will appear here.
</gl-empty-state-stub>
`;
exports[`Project compliance framework empty state it matches the snapshot when "addFrameworkPath" is undefined 1`] = `
<gl-empty-state-stub
compact="true"
svgheight="100"
svgpath="/image.svg"
>
<h5
class="gl-mt-0"
>
No compliance frameworks are set up yet
</h5>
After a framework is added to
<gl-link-stub
href="/group-path"
>
group-name
</gl-link-stub>
, it will appear here.
</gl-empty-state-stub>
`;
import { shallowMount } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
import ProjectComplianceFrameworkEmptyState from 'ee/projects/components/project_compliance_framework_empty_state.vue';
describe('Project compliance framework empty state', () => {
let wrapper;
const defaultProps = {
groupName: 'group-name',
groupPath: '/group-path',
emptyStateSvgPath: '/image.svg',
};
const createComponent = (props = {}) => {
wrapper = shallowMount(ProjectComplianceFrameworkEmptyState, {
propsData: {
...defaultProps,
...props,
},
stubs: {
GlSprintf,
},
});
};
afterEach(() => {
wrapper.destroy();
});
it.each`
addFrameworkPath | description
${undefined} | ${'undefined'}
${'/edit-group'} | ${'a string path'}
`('it matches the snapshot when "addFrameworkPath" is $description', ({ addFrameworkPath }) => {
createComponent({ addFrameworkPath });
expect(wrapper.element).toMatchSnapshot();
});
});
...@@ -462,4 +462,42 @@ RSpec.describe ProjectsHelper do ...@@ -462,4 +462,42 @@ RSpec.describe ProjectsHelper do
}) })
end end
end end
describe '#project_compliance_framework_app_data' do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let(:can_edit) { false }
subject { helper.project_compliance_framework_app_data(project, can_edit) }
before do
allow(helper).to receive(:image_path).and_return('#empty_state_svg_path')
end
context 'when the user cannot edit' do
let(:can_edit) { false }
it 'returns the correct data' do
expect(subject).to eq({
group_name: group.name,
group_path: group_path(group),
empty_state_svg_path: '#empty_state_svg_path'
})
end
end
context 'when the user can edit' do
let(:can_edit) { true }
it 'includes the framework edit path' do
expect(subject).to eq({
group_name: group.name,
group_path: group_path(group),
empty_state_svg_path: '#empty_state_svg_path',
add_framework_path: "#{edit_group_path(group)}#js-compliance-frameworks-settings"
})
end
end
end
end end
...@@ -18,7 +18,7 @@ RSpec.describe 'compliance_management/compliance_framework/_project_settings.htm ...@@ -18,7 +18,7 @@ RSpec.describe 'compliance_management/compliance_framework/_project_settings.htm
it 'shows the section description' do it 'shows the section description' do
render render
expect(rendered).to have_text 'Select a compliance framework to apply to this project. Learn more.' expect(rendered).to have_text 'Select a compliance framework to apply to this project. How are these added?'
end end
context 'group has compliance frameworks' do context 'group has compliance frameworks' do
...@@ -47,7 +47,7 @@ RSpec.describe 'compliance_management/compliance_framework/_project_settings.htm ...@@ -47,7 +47,7 @@ RSpec.describe 'compliance_management/compliance_framework/_project_settings.htm
it 'shows the no permissions text' do it 'shows the no permissions text' do
render render
expect(rendered).to have_text('Customizable by owners.') expect(rendered).to have_text('Owners can modify this selection.')
end end
it 'disables the dropdown' do it 'disables the dropdown' do
...@@ -67,10 +67,16 @@ RSpec.describe 'compliance_management/compliance_framework/_project_settings.htm ...@@ -67,10 +67,16 @@ RSpec.describe 'compliance_management/compliance_framework/_project_settings.htm
group.compliance_management_frameworks.delete_all group.compliance_management_frameworks.delete_all
end end
it 'shows the empty text' do it 'renders the empty state' do
render render
expect(rendered).to match /No compliance frameworks are in use. Create one from the .* section in Group Settings./ expect(rendered).to have_css(
'#js-project-compliance-framework-empty-state'\
"[data-add-framework-path=\"#{edit_group_path(group)}#js-compliance-frameworks-settings\"]"\
"[data-empty-state-svg-path]"\
"[data-group-name=\"#{group.name}\"]"\
"[data-group-path=\"#{group_path(group)}\"]"
)
end end
it 'hides the submit button' do it 'hides the submit button' do
...@@ -85,10 +91,15 @@ RSpec.describe 'compliance_management/compliance_framework/_project_settings.htm ...@@ -85,10 +91,15 @@ RSpec.describe 'compliance_management/compliance_framework/_project_settings.htm
allow(view).to receive(:current_user).and_return(maintainer) allow(view).to receive(:current_user).and_return(maintainer)
end end
it 'shows the empty text' do it 'renders the empty state' do
render render
expect(rendered).to have_text('No compliance frameworks are in use.') expect(rendered).to have_css(
'#js-project-compliance-framework-empty-state'\
"[data-empty-state-svg-path]"\
"[data-group-name=\"#{group.name}\"]"\
"[data-group-path=\"#{group_path(group)}\"]"
)
end end
it 'hides the submit button' do it 'hides the submit button' do
......
...@@ -9098,12 +9098,24 @@ msgstr "" ...@@ -9098,12 +9098,24 @@ msgstr ""
msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone." msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr "" msgstr ""
msgid "ComplianceFramework|Add a framework to %{linkStart}%{groupName}%{linkEnd} and it will appear here."
msgstr ""
msgid "ComplianceFramework|Add framework in %{groupName}"
msgstr ""
msgid "ComplianceFramework|After a framework is added to %{linkStart}%{groupName}%{linkEnd}, it will appear here."
msgstr ""
msgid "ComplianceFramework|Edit compliance framework" msgid "ComplianceFramework|Edit compliance framework"
msgstr "" msgstr ""
msgid "ComplianceFramework|New compliance framework" msgid "ComplianceFramework|New compliance framework"
msgstr "" msgstr ""
msgid "ComplianceFramework|No compliance frameworks are set up yet"
msgstr ""
msgid "ComplianceReport|Approved by author" msgid "ComplianceReport|Approved by author"
msgstr "" msgstr ""
...@@ -10772,9 +10784,6 @@ msgstr "" ...@@ -10772,9 +10784,6 @@ msgstr ""
msgid "Customer relations" msgid "Customer relations"
msgstr "" msgstr ""
msgid "Customizable by owners."
msgstr ""
msgid "Customize CI/CD settings, including Auto DevOps, shared runners, and job artifacts." msgid "Customize CI/CD settings, including Auto DevOps, shared runners, and job artifacts."
msgstr "" msgstr ""
...@@ -24639,12 +24648,6 @@ msgstr "" ...@@ -24639,12 +24648,6 @@ msgstr ""
msgid "No committers" msgid "No committers"
msgstr "" msgstr ""
msgid "No compliance frameworks are in use."
msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}." msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr "" msgstr ""
...@@ -25851,6 +25854,9 @@ msgstr "" ...@@ -25851,6 +25854,9 @@ msgstr ""
msgid "Owner" msgid "Owner"
msgstr "" msgstr ""
msgid "Owners can modify this selection."
msgstr ""
msgid "PQL|An error occurred while sending hand raise lead." msgid "PQL|An error occurred while sending hand raise lead."
msgstr "" msgstr ""
...@@ -33139,7 +33145,7 @@ msgstr "" ...@@ -33139,7 +33145,7 @@ msgstr ""
msgid "Select a branch" msgid "Select a branch"
msgstr "" msgstr ""
msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}" msgid "Select a compliance framework to apply to this project. %{linkStart}How are these added?%{linkEnd}"
msgstr "" msgstr ""
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes." msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
......
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