diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-10-21 07:08:36 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-10-21 07:08:36 +0000 |
commit | 48aff82709769b098321c738f3444b9bdaa694c6 (patch) | |
tree | e00c7c43e2d9b603a5a6af576b1685e400410dee /app/assets/javascripts/invite_members | |
parent | 879f5329ee916a948223f8f43d77fba4da6cd028 (diff) | |
download | gitlab-ce-48aff82709769b098321c738f3444b9bdaa694c6.tar.gz |
Add latest changes from gitlab-org/gitlab@13-5-stable-eev13.5.0-rc42
Diffstat (limited to 'app/assets/javascripts/invite_members')
5 files changed, 310 insertions, 0 deletions
diff --git a/app/assets/javascripts/invite_members/components/invite_members_modal.vue b/app/assets/javascripts/invite_members/components/invite_members_modal.vue new file mode 100644 index 00000000000..d2ea14a658b --- /dev/null +++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue @@ -0,0 +1,224 @@ +<script> +import { + GlModal, + GlDropdown, + GlDropdownItem, + GlDatepicker, + GlLink, + GlSprintf, + GlSearchBoxByType, + GlButton, + GlFormInput, +} from '@gitlab/ui'; +import eventHub from '../event_hub'; +import { s__, sprintf } from '~/locale'; +import Api from '~/api'; + +export default { + name: 'InviteMembersModal', + components: { + GlDatepicker, + GlLink, + GlModal, + GlDropdown, + GlDropdownItem, + GlSprintf, + GlSearchBoxByType, + GlButton, + GlFormInput, + }, + props: { + groupId: { + type: String, + required: true, + }, + groupName: { + type: String, + required: true, + }, + accessLevels: { + type: Object, + required: true, + }, + defaultAccessLevel: { + type: String, + required: true, + }, + helpLink: { + type: String, + required: true, + }, + }, + data() { + return { + visible: true, + modalId: 'invite-members-modal', + selectedAccessLevel: this.defaultAccessLevel, + newUsersToInvite: '', + selectedDate: undefined, + }; + }, + computed: { + introText() { + return sprintf(s__("InviteMembersModal|You're inviting members to the %{group_name} group"), { + group_name: this.groupName, + }); + }, + toastOptions() { + return { + onComplete: () => { + this.selectedAccessLevel = this.defaultAccessLevel; + this.newUsersToInvite = ''; + }, + }; + }, + postData() { + return { + user_id: this.newUsersToInvite, + access_level: this.selectedAccessLevel, + expires_at: this.selectedDate, + format: 'json', + }; + }, + selectedRoleName() { + return Object.keys(this.accessLevels).find( + key => this.accessLevels[key] === Number(this.selectedAccessLevel), + ); + }, + }, + mounted() { + eventHub.$on('openModal', this.openModal); + }, + methods: { + openModal() { + this.$root.$emit('bv::show::modal', this.modalId); + }, + closeModal() { + this.$root.$emit('bv::hide::modal', this.modalId); + }, + sendInvite() { + this.submitForm(this.postData); + this.closeModal(); + }, + cancelInvite() { + this.selectedAccessLevel = this.defaultAccessLevel; + this.selectedDate = undefined; + this.newUsersToInvite = ''; + this.closeModal(); + }, + changeSelectedItem(item) { + this.selectedAccessLevel = item; + }, + submitForm(formData) { + return Api.inviteGroupMember(this.groupId, formData) + .then(() => { + this.showToastMessageSuccess(); + }) + .catch(error => { + this.showToastMessageError(error); + }); + }, + showToastMessageSuccess() { + this.$toast.show(this.$options.labels.toastMessageSuccessful, this.toastOptions); + }, + showToastMessageError(error) { + const message = error.response.data.message || this.$options.labels.toastMessageUnsuccessful; + + this.$toast.show(message, this.toastOptions); + }, + }, + labels: { + modalTitle: s__('InviteMembersModal|Invite team members'), + userToInvite: s__('InviteMembersModal|GitLab member or Email address'), + userPlaceholder: s__('InviteMembersModal|Search for members to invite'), + accessLevel: s__('InviteMembersModal|Choose a role permission'), + accessExpireDate: s__('InviteMembersModal|Access expiration date (optional)'), + toastMessageSuccessful: s__('InviteMembersModal|Users were succesfully added'), + toastMessageUnsuccessful: s__('InviteMembersModal|User not invited. Feature coming soon!'), + readMoreText: s__(`InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions`), + inviteButtonText: s__('InviteMembersModal|Invite'), + cancelButtonText: s__('InviteMembersModal|Cancel'), + }, +}; +</script> +<template> + <gl-modal :modal-id="modalId" size="sm" :title="$options.labels.modalTitle"> + <div class="gl-ml-5 gl-mr-5"> + <div>{{ introText }}</div> + + <label class="gl-font-weight-bold gl-mt-5">{{ $options.labels.userToInvite }}</label> + <div class="gl-mt-2"> + <gl-search-box-by-type + v-model="newUsersToInvite" + :placeholder="$options.labels.userPlaceholder" + type="text" + autocomplete="off" + autocorrect="off" + autocapitalize="off" + spellcheck="false" + /> + </div> + + <label class="gl-font-weight-bold gl-mt-5">{{ $options.labels.accessLevel }}</label> + <div class="gl-mt-2 gl-w-half gl-xs-w-full"> + <gl-dropdown + menu-class="dropdown-menu-selectable" + class="gl-shadow-none gl-w-full" + v-bind="$attrs" + :text="selectedRoleName" + > + <template v-for="(key, item) in accessLevels"> + <gl-dropdown-item + :key="key" + active-class="is-active" + :is-checked="key === selectedAccessLevel" + @click="changeSelectedItem(key)" + > + <div>{{ item }}</div> + </gl-dropdown-item> + </template> + </gl-dropdown> + </div> + + <div class="gl-mt-2"> + <gl-sprintf :message="$options.labels.readMoreText"> + <template #link="{content}"> + <gl-link :href="helpLink" target="_blank">{{ content }}</gl-link> + </template> + </gl-sprintf> + </div> + + <label class="gl-font-weight-bold gl-mt-5" for="expires_at">{{ + $options.labels.accessExpireDate + }}</label> + <div class="gl-mt-2 gl-w-half gl-xs-w-full gl-display-inline-block"> + <gl-datepicker + v-model="selectedDate" + class="gl-display-inline!" + :min-date="new Date()" + :target="null" + > + <template #default="{ formattedDate }"> + <gl-form-input + class="gl-w-full" + :value="formattedDate" + :placeholder="__(`YYYY-MM-DD`)" + /> + </template> + </gl-datepicker> + </div> + </div> + + <template #modal-footer> + <div class="gl-display-flex gl-flex-direction-row gl-justify-content-end gl-flex-wrap gl-p-3"> + <gl-button ref="cancelButton" @click="cancelInvite"> + {{ $options.labels.cancelButtonText }} + </gl-button> + <div class="gl-mr-3"></div> + <gl-button ref="inviteButton" variant="success" @click="sendInvite">{{ + $options.labels.inviteButtonText + }}</gl-button> + </div> + </template> + </gl-modal> +</template> diff --git a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue new file mode 100644 index 00000000000..d133e3655e3 --- /dev/null +++ b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue @@ -0,0 +1,38 @@ +<script> +import { GlLink, GlIcon } from '@gitlab/ui'; +import { s__ } from '~/locale'; +import eventHub from '../event_hub'; + +export default { + components: { + GlLink, + GlIcon, + }, + props: { + displayText: { + type: String, + required: false, + default: s__('InviteMembers|Invite team members'), + }, + icon: { + type: String, + required: false, + default: '', + }, + }, + methods: { + openModal() { + eventHub.$emit('openModal'); + }, + }, +}; +</script> + +<template> + <gl-link @click="openModal"> + <div v-if="icon" class="nav-icon-container"> + <gl-icon :size="16" :name="icon" /> + </div> + <span class="nav-item-name"> {{ displayText }} </span> + </gl-link> +</template> diff --git a/app/assets/javascripts/invite_members/event_hub.js b/app/assets/javascripts/invite_members/event_hub.js new file mode 100644 index 00000000000..e31806ad199 --- /dev/null +++ b/app/assets/javascripts/invite_members/event_hub.js @@ -0,0 +1,3 @@ +import createEventHub from '~/helpers/event_hub_factory'; + +export default createEventHub(); diff --git a/app/assets/javascripts/invite_members/init_invite_members_modal.js b/app/assets/javascripts/invite_members/init_invite_members_modal.js new file mode 100644 index 00000000000..92aa3187fc3 --- /dev/null +++ b/app/assets/javascripts/invite_members/init_invite_members_modal.js @@ -0,0 +1,25 @@ +import Vue from 'vue'; +import { GlToast } from '@gitlab/ui'; +import InviteMembersModal from '~/invite_members/components/invite_members_modal.vue'; + +Vue.use(GlToast); + +export default function initInviteMembersModal() { + const el = document.querySelector('.js-invite-members-modal'); + + if (!el) { + return false; + } + + return new Vue({ + el, + render: createElement => + createElement(InviteMembersModal, { + props: { + ...el.dataset, + accessLevels: JSON.parse(el.dataset.accessLevels), + groupName: el.dataset.groupName.toUpperCase(), + }, + }), + }); +} diff --git a/app/assets/javascripts/invite_members/init_invite_members_trigger.js b/app/assets/javascripts/invite_members/init_invite_members_trigger.js new file mode 100644 index 00000000000..bee4f1c0f72 --- /dev/null +++ b/app/assets/javascripts/invite_members/init_invite_members_trigger.js @@ -0,0 +1,20 @@ +import Vue from 'vue'; +import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue'; + +export default function initInviteMembersTrigger() { + const el = document.querySelector('.js-invite-members-trigger'); + + if (!el) { + return false; + } + + return new Vue({ + el, + render: createElement => + createElement(InviteMembersTrigger, { + props: { + ...el.dataset, + }, + }), + }); +} |