Commit fed187a7 authored by Savas Vedova's avatar Savas Vedova

Merge branch 'ar-approval-settings-help-description' into 'master'

Add a description to approval settings

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