mirror of
https://github.com/logto-io/logto.git
synced 2025-03-03 22:15:32 -05:00
refactor(console,phrases): improve invite email input (#5661)
This commit is contained in:
parent
06083296c1
commit
6e980b3b50
19 changed files with 142 additions and 32 deletions
|
@ -1,11 +1,12 @@
|
||||||
import { emailRegEx } from '@logto/core-kit';
|
import { emailRegEx } from '@logto/core-kit';
|
||||||
|
import { OrganizationInvitationStatus } from '@logto/schemas';
|
||||||
import { conditional, conditionalArray, conditionalString } from '@silverhand/essentials';
|
import { conditional, conditionalArray, conditionalString } from '@silverhand/essentials';
|
||||||
import { useCallback, useContext } from 'react';
|
import { useCallback, useContext } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
|
|
||||||
import { useAuthedCloudApi } from '@/cloud/hooks/use-cloud-api';
|
import { useAuthedCloudApi } from '@/cloud/hooks/use-cloud-api';
|
||||||
import { type TenantMemberResponse } from '@/cloud/types/router';
|
import { type TenantInvitationResponse, type TenantMemberResponse } from '@/cloud/types/router';
|
||||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||||
import { type RequestError } from '@/hooks/use-api';
|
import { type RequestError } from '@/hooks/use-api';
|
||||||
|
|
||||||
|
@ -22,6 +23,12 @@ const useEmailInputUtils = () => {
|
||||||
cloudApi.get('/api/tenants/:tenantId/members', { params: { tenantId: currentTenantId } })
|
cloudApi.get('/api/tenants/:tenantId/members', { params: { tenantId: currentTenantId } })
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { data: existingInvitations = [] } = useSWR<TenantInvitationResponse[], RequestError>(
|
||||||
|
'api/tenants/:tenantId/invitations',
|
||||||
|
async () =>
|
||||||
|
cloudApi.get('/api/tenants/:tenantId/invitations', { params: { tenantId: currentTenantId } })
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find duplicated and invalid formatted email addresses.
|
* Find duplicated and invalid formatted email addresses.
|
||||||
*
|
*
|
||||||
|
@ -31,18 +38,31 @@ const useEmailInputUtils = () => {
|
||||||
const findDuplicatedOrInvalidEmails = useCallback(
|
const findDuplicatedOrInvalidEmails = useCallback(
|
||||||
(emails: string[] = []) => {
|
(emails: string[] = []) => {
|
||||||
const duplicatedEmails = new Set<string>();
|
const duplicatedEmails = new Set<string>();
|
||||||
|
const conflictMemberEmails = new Set<string>();
|
||||||
|
const conflictInvitationEmails = new Set<string>();
|
||||||
const invalidEmails = new Set<string>();
|
const invalidEmails = new Set<string>();
|
||||||
const validEmails = new Set<string>(
|
const validEmails = new Set<string>();
|
||||||
|
|
||||||
|
const existingMemberEmails = new Set<string>(
|
||||||
existingMembers.map(({ primaryEmail }) => primaryEmail ?? '').filter(Boolean)
|
existingMembers.map(({ primaryEmail }) => primaryEmail ?? '').filter(Boolean)
|
||||||
);
|
);
|
||||||
|
const existingInvitationEmails = new Set<string>(
|
||||||
|
existingInvitations
|
||||||
|
.filter(({ status }) => status === OrganizationInvitationStatus.Pending)
|
||||||
|
.map(({ invitee }) => invitee)
|
||||||
|
);
|
||||||
|
|
||||||
for (const email of emails) {
|
for (const email of emails) {
|
||||||
if (!emailRegEx.test(email)) {
|
if (!emailRegEx.test(email)) {
|
||||||
invalidEmails.add(email);
|
invalidEmails.add(email);
|
||||||
}
|
}
|
||||||
|
// Check email collisions
|
||||||
if (validEmails.has(email)) {
|
if (validEmails.has(email)) {
|
||||||
duplicatedEmails.add(email);
|
duplicatedEmails.add(email);
|
||||||
|
} else if (existingInvitationEmails.has(email)) {
|
||||||
|
conflictInvitationEmails.add(email);
|
||||||
|
} else if (existingMemberEmails.has(email)) {
|
||||||
|
conflictMemberEmails.add(email);
|
||||||
} else {
|
} else {
|
||||||
validEmails.add(email);
|
validEmails.add(email);
|
||||||
}
|
}
|
||||||
|
@ -50,10 +70,12 @@ const useEmailInputUtils = () => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
duplicatedEmails,
|
duplicatedEmails,
|
||||||
|
conflictMemberEmails,
|
||||||
|
conflictInvitationEmails,
|
||||||
invalidEmails,
|
invalidEmails,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[existingMembers]
|
[existingInvitations, existingMembers]
|
||||||
);
|
);
|
||||||
|
|
||||||
const parseEmailOptions = useCallback(
|
const parseEmailOptions = useCallback(
|
||||||
|
@ -63,30 +85,44 @@ const useEmailInputUtils = () => {
|
||||||
values: InviteeEmailItem[];
|
values: InviteeEmailItem[];
|
||||||
errorMessage?: string;
|
errorMessage?: string;
|
||||||
} => {
|
} => {
|
||||||
const { duplicatedEmails, invalidEmails } = findDuplicatedOrInvalidEmails(
|
const { duplicatedEmails, conflictInvitationEmails, conflictMemberEmails, invalidEmails } =
|
||||||
inputValues.map((email) => email.value)
|
findDuplicatedOrInvalidEmails(inputValues.map((email) => email.value));
|
||||||
);
|
|
||||||
// Show error message and update the inputs' status for error display.
|
// Show error message and update the inputs' status for error display.
|
||||||
if (duplicatedEmails.size > 0 || invalidEmails.size > 0) {
|
if (
|
||||||
|
duplicatedEmails.size > 0 ||
|
||||||
|
conflictInvitationEmails.size > 0 ||
|
||||||
|
conflictMemberEmails.size > 0 ||
|
||||||
|
invalidEmails.size > 0
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
values: inputValues.map(({ status, ...rest }) => ({
|
values: inputValues.map(({ status, ...rest }) => ({
|
||||||
...rest,
|
...rest,
|
||||||
...conditional(
|
...conditional(
|
||||||
(duplicatedEmails.has(rest.value) || invalidEmails.has(rest.value)) && {
|
(duplicatedEmails.has(rest.value) ||
|
||||||
status: 'info',
|
conflictInvitationEmails.has(rest.value) ||
|
||||||
|
conflictMemberEmails.has(rest.value) ||
|
||||||
|
invalidEmails.has(rest.value)) && {
|
||||||
|
status: 'error',
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
})),
|
})),
|
||||||
errorMessage: conditionalArray(
|
errorMessage: conditionalArray(
|
||||||
conditionalString(duplicatedEmails.size > 0 && t('tenant_members.errors.user_exists')),
|
conditionalString(duplicatedEmails.size > 0 && t('tenant_members.errors.email_exists')),
|
||||||
|
conditionalString(
|
||||||
|
conflictInvitationEmails.size > 0 &&
|
||||||
|
t('tenant_members.errors.pending_invitation_exists')
|
||||||
|
),
|
||||||
|
conditionalString(
|
||||||
|
conflictMemberEmails.size > 0 && t('tenant_members.errors.member_exists')
|
||||||
|
),
|
||||||
conditionalString(invalidEmails.size > 0 && t('tenant_members.errors.invalid_email'))
|
conditionalString(invalidEmails.size > 0 && t('tenant_members.errors.invalid_email'))
|
||||||
).join(' '),
|
).join('\n'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return { values: inputValues };
|
return { values: inputValues };
|
||||||
},
|
},
|
||||||
[findDuplicatedOrInvalidEmails]
|
[findDuplicatedOrInvalidEmails, t]
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
background: var(--color-overlay-default-focused);
|
background: var(--color-overlay-default-focused);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.info {
|
&.error {
|
||||||
background: var(--color-error-container);
|
background: var(--color-error-container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,4 +91,5 @@ canvas {
|
||||||
font: var(--font-body-2);
|
font: var(--font-body-2);
|
||||||
color: var(--color-error);
|
color: var(--color-error);
|
||||||
margin-top: _.unit(1);
|
margin-top: _.unit(1);
|
||||||
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ function InviteEmailsInput({
|
||||||
{
|
{
|
||||||
value,
|
value,
|
||||||
id: generateStandardShortId(),
|
id: generateStandardShortId(),
|
||||||
...conditional(!emailRegEx.test(value) && { status: 'info' }),
|
...conditional(!emailRegEx.test(value) && { status: 'error' }),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
onChange(newValues);
|
onChange(newValues);
|
||||||
|
@ -129,7 +129,7 @@ function InviteEmailsInput({
|
||||||
ref={ref}
|
ref={ref}
|
||||||
placeholder={conditional(values.length === 0 && placeholder)}
|
placeholder={conditional(values.length === 0 && placeholder)}
|
||||||
value={currentValue}
|
value={currentValue}
|
||||||
style={{ minWidth: `${minInputWidth}px` }}
|
style={{ minWidth: `${minInputWidth + 10}px` }}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
if (event.key === 'Backspace' && currentValue === '') {
|
if (event.key === 'Backspace' && currentValue === '') {
|
||||||
if (focusedValueId) {
|
if (focusedValueId) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ export type InviteeEmailItem = {
|
||||||
* - undefined: valid email
|
* - undefined: valid email
|
||||||
* - 'info': duplicated email or invalid email format.
|
* - 'info': duplicated email or invalid email format.
|
||||||
*/
|
*/
|
||||||
status?: Extract<TagProps['status'], 'info'>;
|
status?: Extract<TagProps['status'], 'error'>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type InviteMemberForm = {
|
export type InviteMemberForm = {
|
||||||
|
|
|
@ -87,7 +87,12 @@ const tenant_members = {
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
|
|
|
@ -50,7 +50,10 @@ const tenant_members = {
|
||||||
},
|
},
|
||||||
errors: {
|
errors: {
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
max_member_limit: 'You have reached the maximum number of members ({{limit}}) for this tenant.',
|
max_member_limit: 'You have reached the maximum number of members ({{limit}}) for this tenant.',
|
||||||
},
|
},
|
||||||
|
|
|
@ -87,7 +87,12 @@ const tenant_members = {
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
|
|
|
@ -87,7 +87,12 @@ const tenant_members = {
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
|
|
|
@ -87,7 +87,12 @@ const tenant_members = {
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
|
|
|
@ -87,7 +87,12 @@ const tenant_members = {
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
|
|
|
@ -87,7 +87,12 @@ const tenant_members = {
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
|
|
|
@ -87,7 +87,12 @@ const tenant_members = {
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
|
|
|
@ -87,7 +87,12 @@ const tenant_members = {
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
|
|
|
@ -87,7 +87,12 @@ const tenant_members = {
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
|
|
|
@ -87,7 +87,12 @@ const tenant_members = {
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
|
|
|
@ -87,7 +87,12 @@ const tenant_members = {
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
|
|
|
@ -87,7 +87,12 @@ const tenant_members = {
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
|
|
|
@ -87,7 +87,12 @@ const tenant_members = {
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
|
|
|
@ -87,7 +87,12 @@ const tenant_members = {
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
email_required: 'Invitee email is required.',
|
email_required: 'Invitee email is required.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
user_exists: 'This user is already invited to this organization.',
|
email_exists: 'Email address already exists.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
member_exists: 'This user is already a member of this organization.',
|
||||||
|
/** UNTRANSLATED */
|
||||||
|
pending_invitation_exists:
|
||||||
|
'Pending invitation exists. Delete related email or revoke the invitation.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
invalid_email: 'Email address is invalid. Please make sure it is in the right format.',
|
||||||
/** UNTRANSLATED */
|
/** UNTRANSLATED */
|
||||||
|
|
Loading…
Add table
Reference in a new issue