feat: Add user management invite links without SMTP set up (#5084)

* feat: update n8n-users-list to no longer use preset list of actions

* feat: prepared users settings for invite links feature

* refactor: Return invite link URLs when inviting users (#5079)

* refactor: Return invite link URLs when inviting users

* test: Refactor and add tests to mailer

* feat: Add FE inviteAcceptUrl integration (#5085)

* feat: update n8n-users-list to no longer use preset list of actions

* feat: prepared users settings for invite links feature

* feat: add integration with new inviteAcceptUrl changes

* feat: Add inviteAcceptUrl to user list for pending users

Co-authored-by: Alex Grozav <alex@grozav.com>

* fix conflicts

* fix lint issue

* test: Make sure inviteAcceptUrl is defined

* feat: update smtp setup suggestion

* feat: add invite link summary when inviting multiple users

* refactor: Add telemetry flag for when email is sent

* fix: add email_sent correctly to telemetry event

* feat: move SMTP info-tip to invite modal

Co-authored-by: Omar Ajoue <krynble@gmail.com>
This commit is contained in:
Alex Grozav
2023-01-05 17:10:08 +02:00
committed by GitHub
parent 11a46a4cbc
commit 2327563c44
22 changed files with 419 additions and 247 deletions

View File

@@ -3,27 +3,11 @@
<div>
<n8n-heading size="2xlarge">{{ $locale.baseText('settings.users') }}</n8n-heading>
<div :class="$style.buttonContainer" v-if="!usersStore.showUMSetupWarning">
<n8n-tooltip :disabled="settingsStore.isSmtpSetup" placement="bottom">
<template #content>
<i18n path="settings.users.setupSMTPToInviteUsers" tag="span">
<template #action>
<a
href="https://docs.n8n.io/reference/user-management.html#step-one-smtp"
target="_blank"
v-text="$locale.baseText('settings.users.setupSMTPToInviteUsers.instructions')"
/>
</template>
</i18n>
</template>
<div>
<n8n-button
:label="$locale.baseText('settings.users.invite')"
@click="onInvite"
size="large"
:disabled="!settingsStore.isSmtpSetup"
/>
</div>
</n8n-tooltip>
<n8n-button
:label="$locale.baseText('settings.users.invite')"
@click="onInvite"
size="large"
/>
</div>
</div>
<div v-if="usersStore.showUMSetupWarning" :class="$style.setupInfoContainer">
@@ -32,27 +16,25 @@
:buttonText="$locale.baseText('settings.users.setupMyAccount')"
:description="`${
isSharingEnabled ? '' : $locale.baseText('settings.users.setupToInviteUsersInfo')
}${$locale.baseText('settings.users.setupSMTPInfo')}`"
}`"
@click="redirectToSetup"
/>
</div>
<div :class="$style.usersContainer" v-else>
<PageAlert
v-if="!settingsStore.isSmtpSetup"
:message="$locale.baseText('settings.users.smtpToAddUsersWarning')"
:popupClass="$style.alert"
/>
<n8n-users-list
:actions="usersListActions"
:users="usersStore.allUsers"
:currentUserId="usersStore.currentUserId"
@delete="onDelete"
@reinvite="onReinvite"
@copyInviteLink="onCopyInviteLink"
/>
</div>
<feature-coming-soon
v-for="fakeDoorFeature in fakeDoorFeatures"
:key="fakeDoorFeature.id"
:featureId="fakeDoorFeature.id"
class="pb-3xl"
showTitle
/>
</div>
@@ -63,15 +45,16 @@ import { EnterpriseEditionFeature, INVITE_USER_MODAL_KEY, VIEWS } from '@/consta
import PageAlert from '../components/PageAlert.vue';
import FeatureComingSoon from '@/components/FeatureComingSoon.vue';
import { IFakeDoor, IUser } from '@/Interface';
import { IFakeDoor, IUser, IUserListAction } from '@/Interface';
import mixins from 'vue-typed-mixins';
import { showMessage } from '@/mixins/showMessage';
import { copyPaste } from '@/mixins/copyPaste';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui';
import { useSettingsStore } from '@/stores/settings';
import { useUsersStore } from '@/stores/users';
export default mixins(showMessage).extend({
export default mixins(showMessage, copyPaste).extend({
name: 'SettingsUsersView',
components: {
PageAlert,
@@ -87,6 +70,24 @@ export default mixins(showMessage).extend({
isSharingEnabled() {
return this.settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing);
},
usersListActions(): IUserListAction[] {
return [
{
label: this.$locale.baseText('settings.users.actions.copyInviteLink'),
value: 'copyInviteLink',
guard: (user) => !user.firstName && !!user.inviteAcceptUrl,
},
{
label: this.$locale.baseText('settings.users.actions.reinvite'),
value: 'reinvite',
guard: (user) => !user.firstName && this.settingsStore.isSmtpSetup,
},
{
label: this.$locale.baseText('settings.users.actions.delete'),
value: 'delete',
},
];
},
fakeDoorFeatures(): IFakeDoor[] {
return this.uiStore.getFakeDoorByLocation('settings/users');
},
@@ -122,6 +123,18 @@ export default mixins(showMessage).extend({
}
}
},
async onCopyInviteLink(userId: string) {
const user = this.usersStore.getUserById(userId) as IUser | null;
if (user?.inviteAcceptUrl) {
this.copyToClipboard(user.inviteAcceptUrl);
this.$showToast({
type: 'success',
title: this.$locale.baseText('settings.users.inviteUrlCreated'),
message: this.$locale.baseText('settings.users.inviteUrlCreated.message'),
});
}
},
},
});
</script>