Commit 7deefa7d authored by Alex Buijs's avatar Alex Buijs

Add invite member component

When creating a group allow to invite new
teammates.
parent 0cd4feb5
<script>
import { __, sprintf } from '~/locale';
import { GlFormGroup, GlFormInput, GlButton } from '@gitlab/ui';
export default {
components: {
GlFormGroup,
GlFormInput,
GlButton,
},
props: {
emails: {
type: Array,
required: true,
},
},
data() {
return {
numberOfInputs: Math.max(this.emails.length, 2),
};
},
methods: {
addInput() {
this.numberOfInputs += 1;
this.$nextTick(() => {
this.$refs[this.emailID(this.numberOfInputs)][0].$el.focus();
});
},
emailLabel(number) {
return sprintf(this.$options.i18n.emailLabel, { number });
},
emailPlaceholder(number) {
return sprintf(this.$options.i18n.emailPlaceholder, { number });
},
emailID(number) {
return `email-${number}`;
},
},
i18n: {
inviteTeammatesLabel: __('Invite teammates (optional)'),
inviteTeammatesDescription: __(
'Invited users will be added with developer level permissions. You can always change this later.',
),
emailLabel: __('Email %{number}'),
emailPlaceholder: __('teammate%{number}@company.com'),
inviteAnother: __('Invite another teammate'),
},
};
</script>
<template>
<div class="gl-mb-6">
<gl-form-group
:label="$options.i18n.inviteTeammatesLabel"
:description="$options.i18n.inviteTeammatesDescription"
/>
<gl-form-group
v-for="(number, index) in numberOfInputs"
:key="number"
:label="emailLabel(number)"
:label-for="emailID(number)"
>
<gl-form-input
:id="emailID(number)"
:ref="emailID(number)"
name="group[emails][]"
:placeholder="emailPlaceholder(number)"
:value="emails[index]"
/>
</gl-form-group>
<gl-button icon="plus" @click="addInput">{{ $options.i18n.inviteAnother }}</gl-button>
</div>
</template>
......@@ -2,6 +2,7 @@ import Vue from 'vue';
import { STEPS, ONBOARDING_ISSUES_EXPERIMENT_FLOW_STEPS } from '../../constants';
import ProgressBar from '../../components/progress_bar.vue';
import VisibilityLevelDropdown from '../../components/visibility_level_dropdown.vue';
import InviteTeammates from '../../components/invite_teammates.vue';
function mountProgressBar() {
const el = document.getElementById('progress-bar');
......@@ -36,7 +37,25 @@ function mountVisibilityLevelDropdown() {
});
}
function mountInviteTeammates() {
const el = document.querySelector('.js-invite-teammates');
if (!el) return null;
return new Vue({
el,
render(createElement) {
return createElement(InviteTeammates, {
props: {
emails: JSON.parse(el.dataset.emails),
},
});
},
});
}
export default () => {
mountProgressBar();
mountVisibilityLevelDropdown();
mountInviteTeammates();
};
......@@ -169,6 +169,7 @@ $subscriptions-full-width-lg: 541px;
}
.field_with_errors {
@include gl-flex-grow-1;
display: inline;
}
......
- page_title _('Your GitLab group')
.row.flex-grow-1.bg-gray-light
.d-flex.flex-column.align-items-center.w-100.p-3
.row.flex-grow-1
.d-flex.flex-column.align-items-center.w-100.p-3.gl-bg-gray-10
.edit-group.d-flex.flex-column.align-items-center.pt-5
#progress-bar
%h2.center= _('Create your group')
......@@ -42,6 +42,7 @@
= f.label :visibility_level, class: 'label-bold' do
= _('Visibility level')
.js-visibility-level-dropdown{ data: { visibility_level_options: visibility_level_options.to_json, default_level: f.object.visibility_level } }
.js-invite-teammates{ data: { emails: params.dig(:group, :emails) || [] } }
.row
.form-group.col-sm-12.mb-0
= button_tag class: %w[btn btn-success w-100] do
......
import { shallowMount, mount } from '@vue/test-utils';
import { GlFormInput, GlButton } from '@gitlab/ui';
import Component from 'ee/registrations/components/invite_teammates.vue';
describe('User invites', () => {
let wrapper;
const createComponent = propsData => {
wrapper = shallowMount(Component, {
propsData,
});
};
beforeEach(() => {
createComponent({ emails: [] });
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
const inputs = () => wrapper.findAll(GlFormInput);
const clickButton = () => wrapper.find(GlButton).vm.$emit('click');
describe('Default state', () => {
it('creates 2 input fields', () => {
expect(inputs().length).toBe(2);
});
it.each([0, 1])('does not set a value', index => {
expect(
inputs()
.at(index)
.attributes('value'),
).toBe(undefined);
});
});
describe('With already filled emails', () => {
const emails = ['a@a', 'b@b', 'c@c'];
beforeEach(() => {
createComponent({ emails });
});
it('creates 3 input fields', () => {
expect(inputs().length).toBe(3);
});
it.each([0, 1, 2])('restores the value of the passed emails', index => {
expect(
inputs()
.at(index)
.attributes('value'),
).toBe(emails[index]);
});
});
describe('Adding an input', () => {
beforeEach(() => {
wrapper = mount(Component, {
propsData: { emails: [] },
attachToDocument: true,
});
clickButton();
});
it('adds an input field', () => {
expect(inputs().length).toBe(3);
});
it.each([0, 1, 2])('does not set a value', index => {
expect(
inputs()
.at(index)
.attributes('value'),
).toBe(undefined);
});
it('sets the focus to the new input field', () => {
expect(inputs().at(2).element).toBe(document.activeElement);
});
});
});
......@@ -8758,6 +8758,9 @@ msgstr ""
msgid "Email"
msgstr ""
msgid "Email %{number}"
msgstr ""
msgid "Email Notification"
msgstr ""
......@@ -13057,12 +13060,21 @@ msgstr ""
msgid "Invite Members"
msgstr ""
msgid "Invite another teammate"
msgstr ""
msgid "Invite group"
msgstr ""
msgid "Invite member"
msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
msgid "Invocations"
msgstr ""
......@@ -29283,6 +29295,9 @@ msgstr ""
msgid "tag name"
msgstr ""
msgid "teammate%{number}@company.com"
msgstr ""
msgid "the following issue(s)"
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