Commit 6b1dca5c authored by Austin Regnery's avatar Austin Regnery Committed by Savas Vedova

Add a description to approval settings

parent b27e5dfc
<script>
import { GlAlert, GlButton, GlForm, GlFormGroup, GlLoadingIcon } from '@gitlab/ui';
import { GlAlert, GlButton, GlForm, GlFormGroup, GlLoadingIcon, GlLink } from '@gitlab/ui';
import { isEmpty } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
import { helpPagePath } from '~/helpers/help_page_helper';
import { mapComputed } from '~/vuex_shared/bindings';
import { APPROVAL_SETTINGS_I18N } from '../constants';
import ApprovalSettingsCheckbox from './approval_settings_checkbox.vue';
......@@ -14,6 +15,7 @@ export default {
GlForm,
GlFormGroup,
GlLoadingIcon,
GlLink,
},
props: {
approvalSettingsPath: {
......@@ -80,15 +82,10 @@ export default {
await this.updateSettings(this.approvalSettingsPath);
},
},
i18n: APPROVAL_SETTINGS_I18N,
links: {
preventAuthorApprovalDocsAnchor: 'prevent-approval-by-author',
preventCommittersApprovalDocsAnchor: 'prevent-approvals-by-users-who-add-commits',
preventMrApprovalRuleEditDocsAnchor: 'prevent-editing-approval-rules-in-merge-requests',
requireUserPasswordDocsAnchor: 'require-user-password-to-approve',
removeApprovalsOnPushDocsAnchor:
'remove-all-approvals-when-commits-are-added-to-the-source-branch',
approvalSettingsDocsPath: helpPagePath('user/project/merge_requests/approvals/settings'),
},
i18n: APPROVAL_SETTINGS_I18N,
};
</script>
......@@ -118,11 +115,17 @@ export default {
{{ $options.i18n.savingSuccessMessage }}
</gl-alert>
<gl-form v-if="hasSettings" @submit.prevent="onSubmit">
<label class="label-bold"> {{ $options.i18n.approvalSettingsHeader }} </label>
<p>
{{ $options.i18n.approvalSettingsDescription }}
<gl-link :href="$options.links.approvalSettingsDocsPath" target="_blank">
{{ $options.i18n.learnMore }}
</gl-link>
</p>
<gl-form-group>
<approval-settings-checkbox
v-model="preventAuthorApproval"
:label="settingsLabels.authorApprovalLabel"
:anchor="$options.links.preventAuthorApprovalDocsAnchor"
:locked="!canPreventAuthorApproval"
:locked-text="$options.i18n.lockedByAdmin"
data-testid="prevent-author-approval"
......@@ -130,7 +133,6 @@ export default {
<approval-settings-checkbox
v-model="preventCommittersApproval"
:label="settingsLabels.preventCommittersApprovalLabel"
:anchor="$options.links.preventCommittersApprovalDocsAnchor"
:locked="!canPreventCommittersApproval"
:locked-text="$options.i18n.lockedByAdmin"
data-testid="prevent-committers-approval"
......@@ -138,7 +140,6 @@ export default {
<approval-settings-checkbox
v-model="preventMrApprovalRuleEdit"
:label="settingsLabels.preventMrApprovalRuleEditLabel"
:anchor="$options.links.preventMrApprovalRuleEditDocsAnchor"
:locked="!canPreventMrApprovalRuleEdit"
:locked-text="$options.i18n.lockedByAdmin"
data-testid="prevent-mr-approval-rule-edit"
......@@ -146,13 +147,11 @@ export default {
<approval-settings-checkbox
v-model="requireUserPassword"
:label="settingsLabels.requireUserPasswordLabel"
:anchor="$options.links.requireUserPasswordDocsAnchor"
data-testid="require-user-password"
/>
<approval-settings-checkbox
v-model="removeApprovalsOnPush"
:label="settingsLabels.removeApprovalsOnPushLabel"
:anchor="$options.links.removeApprovalsOnPushDocsAnchor"
data-testid="remove-approvals-on-push"
/>
</gl-form-group>
......
<script>
import { GlFormCheckbox, GlIcon, GlLink, GlPopover } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
import { GlFormCheckbox, GlIcon, GlPopover } from '@gitlab/ui';
import { slugify } from '~/lib/utils/text_utility';
import { __ } from '~/locale';
import { APPROVALS_HELP_PATH } from '../constants';
export default {
components: {
GlFormCheckbox,
GlIcon,
GlLink,
GlPopover,
},
props: {
......@@ -17,10 +14,6 @@ export default {
type: String,
required: true,
},
anchor: {
type: String,
required: true,
},
value: {
type: Boolean,
required: false,
......@@ -38,9 +31,6 @@ export default {
},
},
computed: {
href() {
return helpPagePath(APPROVALS_HELP_PATH, { anchor: this.anchor });
},
lockIconId() {
return `approval-settings-checkbox-lock-icon-${slugify(this.label)}`;
},
......@@ -51,7 +41,6 @@ export default {
},
},
i18n: {
helpLinkText: __('Learn more.'),
lockIconTitle: __('Setting enforced'),
},
};
......@@ -71,8 +60,5 @@ export default {
:content="lockedText"
/>
</template>
<gl-link :href="href" target="_blank">
{{ $options.i18n.helpLinkText }}
</gl-link>
</gl-form-checkbox>
</template>
<script>
import { mapState } from 'vuex';
import { __ } from '~/locale';
import { PROJECT_APPROVAL_SETTINGS_LABELS_I18N } from '../../constants';
import ApprovalSettings from '../approval_settings.vue';
......@@ -16,18 +15,12 @@ export default {
canModifyCommiterSettings: (state) => state.settings.canModifyCommiterSettings,
}),
},
i18n: {
projectSettingsHeader: __('Approval settings'),
},
labels: PROJECT_APPROVAL_SETTINGS_LABELS_I18N,
};
</script>
<template>
<div data-testid="merge-request-approval-settings">
<label class="label-bold">
{{ $options.i18n.projectSettingsHeader }}
</label>
<approval-settings
:approval-settings-path="approvalsPath"
:can-prevent-author-approval="canModifyAuthorSettings"
......
......@@ -50,6 +50,11 @@ export const APPROVAL_RULE_CONFIGS = {
export const APPROVALS_HELP_PATH = 'user/project/merge_requests/approvals/settings';
export const APPROVAL_SETTINGS_I18N = {
learnMore: __('Learn more.'),
approvalSettingsHeader: __('Approval settings'),
approvalSettingsDescription: __(
'Define how approval rules are applied as a merge request moves toward completion.',
),
saveChanges: __('Save changes'),
loadingErrorMessage: s__(
'ApprovalSettings|There was an error loading merge request approval settings.',
......
......@@ -8,9 +8,6 @@
%p
= _('Regulate approvals by authors/committers. Affects all projects.')
.settings-content
%hr.clearfix.mt-0
= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'merge-request-approval-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
......
%fieldset
%legend.h5.gl-border-none
= _('Approval settings')
%p
= _("Define how approval rules are applied as a merge request moves toward completion.")
= link_to _("Learn more."), help_page_path("user/project/merge_requests/approvals/settings.md"), target: '_blank'
.gl-form-checkbox-group
.gl-form-checkbox.custom-control.custom-checkbox
= f.check_box :prevent_merge_requests_author_approval, class: 'custom-control-input'
......
......@@ -2,14 +2,12 @@ import { GlFormCheckbox, GlIcon, GlLink, GlPopover } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import ApprovalSettingsCheckbox from 'ee/approvals/components/approval_settings_checkbox.vue';
import { APPROVALS_HELP_PATH } from 'ee/approvals/constants';
import { stubComponent } from 'helpers/stub_component';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { slugify } from '~/lib/utils/text_utility';
describe('ApprovalSettingsCheckbox', () => {
const label = 'Foo';
const anchor = 'bar-baz';
const lockIconId = `approval-settings-checkbox-lock-icon-${slugify(label)}`;
let wrapper;
......@@ -17,7 +15,7 @@ describe('ApprovalSettingsCheckbox', () => {
const createWrapper = (props = {}) => {
wrapper = extendedWrapper(
shallowMount(ApprovalSettingsCheckbox, {
propsData: { label, anchor, ...props },
propsData: { label, ...props },
stubs: {
GlFormCheckbox: stubComponent(GlFormCheckbox, {
props: ['checked'],
......@@ -30,7 +28,6 @@ describe('ApprovalSettingsCheckbox', () => {
};
const findCheckbox = () => wrapper.findComponent(GlFormCheckbox);
const findLink = () => wrapper.findComponent(GlLink);
const findPopover = () => wrapper.findComponent(GlPopover);
const findLockIcon = () => wrapper.findByTestId('lock-icon');
......@@ -46,14 +43,6 @@ describe('ApprovalSettingsCheckbox', () => {
it('shows the label', () => {
expect(findCheckbox().text()).toContain(label);
});
it('shows the help text', () => {
expect(findCheckbox().text()).toContain('Learn more.');
});
it('sets the correct help link', () => {
expect(findLink().attributes('href')).toBe(`/help/${APPROVALS_HELP_PATH}#${anchor}`);
});
});
describe('value', () => {
......
import { GlButton, GlForm, GlLoadingIcon } from '@gitlab/ui';
import { GlButton, GlForm, GlLoadingIcon, GlLink } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
......@@ -59,6 +59,7 @@ describe('ApprovalSettings', () => {
const findSuccessAlert = () => wrapper.findByTestId('success-alert');
const findForm = () => wrapper.findComponent(GlForm);
const findSaveButton = () => wrapper.findComponent(GlButton);
const findLink = () => wrapper.findComponent(GlLink);
afterEach(() => {
wrapper.destroy();
......@@ -153,14 +154,34 @@ describe('ApprovalSettings', () => {
expect(findSaveButton().attributes('disabled')).toBeUndefined();
});
it('renders the approval settings heading', async () => {
createWrapper();
await waitForPromises();
expect(findForm().text()).toContain('Approval settings');
expect(findForm().text()).toContain(
'Define how approval rules are applied as a merge request moves toward completion.',
);
});
it('renders the help link', async () => {
createWrapper();
await waitForPromises();
expect(findLink().text()).toBe('Learn more.');
expect(findLink().attributes('href')).toBe(
'/help/user/project/merge_requests/approvals/settings',
);
});
describe.each`
testid | action | setting | labelKey | anchor
${'prevent-author-approval'} | ${'setPreventAuthorApproval'} | ${'preventAuthorApproval'} | ${'authorApprovalLabel'} | ${'prevent-approval-by-author'}
${'prevent-committers-approval'} | ${'setPreventCommittersApproval'} | ${'preventCommittersApproval'} | ${'preventCommittersApprovalLabel'} | ${'prevent-approvals-by-users-who-add-commits'}
${'prevent-mr-approval-rule-edit'} | ${'setPreventMrApprovalRuleEdit'} | ${'preventMrApprovalRuleEdit'} | ${'preventMrApprovalRuleEditLabel'} | ${'prevent-editing-approval-rules-in-merge-requests'}
${'require-user-password'} | ${'setRequireUserPassword'} | ${'requireUserPassword'} | ${'requireUserPasswordLabel'} | ${'require-user-password-to-approve'}
${'remove-approvals-on-push'} | ${'setRemoveApprovalsOnPush'} | ${'removeApprovalsOnPush'} | ${'removeApprovalsOnPushLabel'} | ${'remove-all-approvals-when-commits-are-added-to-the-source-branch'}
`('with the $testid checkbox', ({ testid, action, setting, labelKey, anchor }) => {
testid | action | setting | labelKey
${'prevent-author-approval'} | ${'setPreventAuthorApproval'} | ${'preventAuthorApproval'} | ${'authorApprovalLabel'}
${'prevent-committers-approval'} | ${'setPreventCommittersApproval'} | ${'preventCommittersApproval'} | ${'preventCommittersApprovalLabel'}
${'prevent-mr-approval-rule-edit'} | ${'setPreventMrApprovalRuleEdit'} | ${'preventMrApprovalRuleEdit'} | ${'preventMrApprovalRuleEditLabel'}
${'require-user-password'} | ${'setRequireUserPassword'} | ${'requireUserPassword'} | ${'requireUserPasswordLabel'}
${'remove-approvals-on-push'} | ${'setRemoveApprovalsOnPush'} | ${'removeApprovalsOnPush'} | ${'removeApprovalsOnPushLabel'}
`('with the $testid checkbox', ({ testid, action, setting, labelKey }) => {
let checkbox = null;
beforeEach(async () => {
......@@ -178,11 +199,8 @@ describe('ApprovalSettings', () => {
expect(checkbox.exists()).toBe(true);
});
it('has the anchor and label props', () => {
expect(checkbox.props()).toMatchObject({
anchor,
label: PROJECT_APPROVAL_SETTINGS_LABELS_I18N[labelKey],
});
it('has the label prop', () => {
expect(checkbox.props('label')).toBe(PROJECT_APPROVAL_SETTINGS_LABELS_I18N[labelKey]);
});
it(`triggers the action ${action} when the value is changed`, async () => {
......
......@@ -10723,6 +10723,9 @@ msgstr ""
msgid "Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%{code_close} to track deployments here."
msgstr ""
msgid "Define how approval rules are applied as a merge request moves toward completion."
msgstr ""
msgid "Definition"
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