Commit 964a603a authored by Martin Wortschack's avatar Martin Wortschack

Merge branch...

Merge branch '220567-implement-token-selector-component-for-group-restrict-membership-by-email-field' into 'master'

Implement token selector component for group "Restrict membership by email" field

See merge request gitlab-org/gitlab!35543
parents 21061935 d285bb3d
......@@ -554,7 +554,7 @@ Some domains cannot be restricted. These are the most popular public email domai
To enable this feature:
1. Navigate to the group's **Settings > General** page.
1. Expand the **Permissions, LFS, 2FA** section, and enter the domain names into **Restrict membership by email** field. You can enter multiple domains by separating each domain with a comma (,).
1. Expand the **Permissions, LFS, 2FA** section, and enter the domain names into **Restrict membership by email** field.
1. Click **Save changes**.
This will enable the domain-checking for all new users added to the group from this moment on.
......
import Vue from 'vue';
import { __, sprintf } from '~/locale';
import CommaSeparatedListTokenSelector from '../components/comma_separated_list_token_selector.vue';
export default () => {
// eslint-disable-next-line no-new
new Vue({
el: '.js-allowed-email-domains',
components: {
CommaSeparatedListTokenSelector,
},
data() {
const { hiddenInputId, labelId } = document.querySelector(this.$options.el).dataset;
return { hiddenInputId, labelId };
},
render(createElement) {
return createElement('comma-separated-list-token-selector', {
props: {
hiddenInputId: this.hiddenInputId,
ariaLabelledby: this.labelId,
placeholder: __('Enter domain'),
},
scopedSlots: {
'user-defined-token-content': ({ inputText: value }) => {
return sprintf(__('Add "%{value}" to allowlist'), { value });
},
},
});
},
});
};
<script>
import { GlTokenSelector } from '@gitlab/ui';
export default {
name: 'CommaSeparatedListTokenSelector',
hiddenInput: null,
components: { GlTokenSelector },
props: {
hiddenInputId: {
type: String,
required: true,
},
ariaLabelledby: {
type: String,
required: true,
},
placeholder: {
type: String,
required: false,
default: null,
},
},
data() {
return {
selectedTokens: [],
};
},
watch: {
selectedTokens(newValue) {
this.$options.hiddenInput.value = newValue.map(token => token.name).join(',');
// Dispatch `input` event so form submit button becomes active
this.$options.hiddenInput.dispatchEvent(
new Event('input', {
bubbles: true,
cancelable: true,
}),
);
},
},
mounted() {
const hiddenInput = document.getElementById(this.hiddenInputId);
this.$options.hiddenInput = hiddenInput;
if (hiddenInput.value === '') {
return;
}
this.selectedTokens = hiddenInput.value.split(/,\s*/).map((token, index) => ({
id: index,
name: token,
}));
},
methods: {
handleEnter(event) {
// Prevent form from submitting when adding a token
if (event.target.value !== '') {
event.preventDefault();
}
},
},
};
</script>
<template>
<gl-token-selector
v-model="selectedTokens"
container-class="gl-h-auto!"
allow-user-defined-tokens
hide-dropdown-with-no-items
:aria-labelledby="ariaLabelledby"
:placeholder="placeholder"
@keydown.enter="handleEnter"
>
<template #user-defined-token-content="{ inputText }">
<slot name="user-defined-token-content" :input-text="inputText"></slot>
</template>
</gl-token-selector>
</template>
import '~/pages/groups/edit';
import initAllowedEmailDomains from 'ee/groups/settings/allowed_email_domains';
document.addEventListener('DOMContentLoaded', () => {
initAllowedEmailDomains();
});
- return if !group.feature_available?(:group_allowed_email_domains) || group.parent_id.present?
%h5= _('Restrict membership by email')
- hidden_input_id = 'group_allowed_email_domains_list'
- label_id = "#{hidden_input_id}_label"
.form-group
= f.text_field :allowed_email_domains_list, class: 'form-control', placeholder: _('Enter domain')
%label{ id: label_id }
= _('Restrict membership by email domain')
.js-allowed-email-domains{ data: { hidden_input_id: hidden_input_id, label_id: label_id } }
= f.hidden_field :allowed_email_domains_list, id: hidden_input_id
.form-text.text-muted
- read_more_link = link_to(_('Read more'), help_page_path('user/group/index', anchor: 'allowed-domain-restriction-premium'))
= _('Only verified users with an email address in any of these domains can be added to the group.')
%br
= _('Multiple domains are supported with comma delimiters.')
%br
= _('Example: <code>acme.com,acme.co.in,acme.uk</code>.').html_safe
= _('Multiple domains are supported.')
%br
= _('Some common domains are not allowed. %{read_more_link}.').html_safe % { read_more_link: read_more_link }
---
title: Change "Restrict membership by email" field from a comma separated list to
the GitLab UI Token Selector component
merge_request: 35543
author:
type: changed
import { nextTick } from 'vue';
import { mount } from '@vue/test-utils';
import { GlToken, GlTokenSelector } from '@gitlab/ui';
import CommaSeparatedListTokenSelector from 'ee/groups/settings/components/comma_separated_list_token_selector.vue';
describe('CommaSeparatedListTokenSelector', () => {
let wrapper;
let div;
let input;
const defaultProps = {
hiddenInputId: 'comma-separated-list',
ariaLabelledby: 'comma-separated-list-label',
};
const createComponent = options => {
wrapper = mount(CommaSeparatedListTokenSelector, {
attachTo: div,
...options,
propsData: {
...defaultProps,
...(options?.propsData || {}),
},
});
};
beforeEach(() => {
div = document.createElement('div');
input = document.createElement('input');
input.setAttribute('type', 'text');
input.id = 'comma-separated-list';
document.body.appendChild(div);
div.appendChild(input);
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
div.remove();
});
describe('when component is mounted', () => {
it.each`
inputValue | expectedTokens
${'gitlab.com,gitlab.org,gitlab.ninja'} | ${['gitlab.com', 'gitlab.org', 'gitlab.ninja']}
${'gitlab.com, gitlab.org, gitlab.ninja'} | ${['gitlab.com', 'gitlab.org', 'gitlab.ninja']}
${'foo bar, baz'} | ${['foo bar', 'baz']}
${'192.168.0.0/24,192.168.1.0/24'} | ${['192.168.0.0/24', '192.168.1.0/24']}
`(
'parses comma separated list ($inputValue) into tokens',
async ({ inputValue, expectedTokens }) => {
input.value = inputValue;
createComponent();
await nextTick();
wrapper.findAll(GlToken).wrappers.forEach((tokenWrapper, index) => {
expect(tokenWrapper.text()).toBe(expectedTokens[index]);
});
},
);
});
describe('when selected tokens changes', () => {
const setup = async () => {
const tokens = [
{
id: 1,
name: 'gitlab.com',
},
{
id: 2,
name: 'gitlab.org',
},
{
id: 3,
name: 'gitlab.ninja',
},
];
createComponent();
await wrapper.setData({
selectedTokens: tokens,
});
};
it('sets input value ', async () => {
await setup();
expect(input.value).toBe('gitlab.com,gitlab.org,gitlab.ninja');
});
it('fires `input` event', async () => {
const dispatchEvent = jest.spyOn(input, 'dispatchEvent');
await setup();
expect(dispatchEvent).toHaveBeenCalledWith(
new Event('input', {
bubbles: true,
cancelable: true,
}),
);
});
});
describe('when enter key is pressed', () => {
it('does not submit the form if token selector text input has a value', async () => {
createComponent();
const tokenSelectorInput = wrapper.find(GlTokenSelector).find('input[type="text"]');
tokenSelectorInput.element.value = 'foo bar';
const event = { preventDefault: jest.fn() };
await tokenSelectorInput.trigger('keydown.enter', event);
expect(event.preventDefault).toHaveBeenCalled();
});
});
});
......@@ -83,7 +83,8 @@ RSpec.describe 'groups/edit.html.haml' do
expect(rendered).to render_template('groups/settings/_allowed_email_domain')
expect(rendered).to(have_field('group_allowed_email_domains_list',
{ disabled: false,
with: domains.join(",") }))
with: domains.join(","),
type: :hidden }))
end
end
......
......@@ -1301,6 +1301,9 @@ msgstr ""
msgid "Add"
msgstr ""
msgid "Add \"%{value}\" to allowlist"
msgstr ""
msgid "Add %d issue"
msgid_plural "Add %d issues"
msgstr[0] ""
......@@ -9373,9 +9376,6 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
msgid "Example: <code>acme.com,acme.co.in,acme.uk</code>."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
......@@ -14918,7 +14918,7 @@ msgstr ""
msgid "MrDeploymentActions|Stop environment"
msgstr ""
msgid "Multiple domains are supported with comma delimiters."
msgid "Multiple domains are supported."
msgstr ""
msgid "Multiple issue boards"
......@@ -19639,7 +19639,7 @@ msgstr ""
msgid "Restrict access by IP address"
msgstr ""
msgid "Restrict membership by email"
msgid "Restrict membership by email domain"
msgstr ""
msgid "Restricts sign-ups for email addresses that match the given regex. See the %{supported_syntax_link_start}supported syntax%{supported_syntax_link_end} for more information."
......
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