diff --git a/packages/console/src/consts/external-links.ts b/packages/console/src/consts/external-links.ts index beba94cd3..d9edadee3 100644 --- a/packages/console/src/consts/external-links.ts +++ b/packages/console/src/consts/external-links.ts @@ -1,4 +1,5 @@ export const discordLink = 'https://discord.gg/UEPaF3j5e6'; export const githubLink = 'https://github.com/logto-io/logto'; export const githubIssuesLink = 'https://github.com/logto-io/logto/issues'; -export const contactEmailLink = 'mailto:contact@logto.io'; +export const contactEmail = 'contact@logto.io'; +export const contactEmailLink = `mailto:${contactEmail}`; diff --git a/packages/console/src/onboarding/constants/index.ts b/packages/console/src/onboarding/constants/index.ts index e9d296404..6546e92db 100644 --- a/packages/console/src/onboarding/constants/index.ts +++ b/packages/console/src/onboarding/constants/index.ts @@ -1,10 +1,11 @@ +import { contactEmailLink } from '@/consts'; import { buildUrl } from '@/utils/url'; export const reservationLink = buildUrl('https://calendly.com/logto/30min', { // Note: month format is YYYY-MM month: new Date().toISOString().slice(0, 7), }); -export const emailUsLink = buildUrl('mailto:contact@logto.io', { +export const emailUsLink = buildUrl(contactEmailLink, { subject: 'Cloud pricing and special offer', }).replace(/\+/g, '%20'); diff --git a/packages/console/src/pages/Profile/containers/DeleteAccountModal/index.tsx b/packages/console/src/pages/Profile/containers/DeleteAccountModal/index.tsx index 48fc12f0b..ca7259d3a 100644 --- a/packages/console/src/pages/Profile/containers/DeleteAccountModal/index.tsx +++ b/packages/console/src/pages/Profile/containers/DeleteAccountModal/index.tsx @@ -4,6 +4,7 @@ import ReactModal from 'react-modal'; import Button from '@/components/Button'; import ModalLayout from '@/components/ModalLayout'; import TextLink from '@/components/TextLink'; +import { contactEmail, contactEmailLink } from '@/consts'; import * as modalStyles from '@/scss/modal.module.scss'; import * as styles from './index.module.scss'; @@ -13,8 +14,7 @@ type Props = { onClose: () => void; }; -const contactUsEmail = 'contact@logto.io'; -const mailToLink = `mailto:${contactUsEmail}?subject=Account%20Deletion%20Request`; +const mailToLink = `${contactEmailLink}?subject=Account%20Deletion%20Request`; function DeleteAccountModal({ isOpen, onClose }: Props) { const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); @@ -40,7 +40,7 @@ function DeleteAccountModal({ isOpen, onClose }: Props) { a: , }} > - {t('profile.delete_account.dialog_paragraph_2', { mail: contactUsEmail })} + {t('profile.delete_account.dialog_paragraph_2', { mail: contactEmail })}

{t('profile.delete_account.dialog_paragraph_3')}

diff --git a/packages/console/src/pages/Webhooks/components/CreateFormModal/index.tsx b/packages/console/src/pages/Webhooks/components/CreateFormModal/index.tsx index f7b56e5a9..22d997d2f 100644 --- a/packages/console/src/pages/Webhooks/components/CreateFormModal/index.tsx +++ b/packages/console/src/pages/Webhooks/components/CreateFormModal/index.tsx @@ -1,6 +1,11 @@ import { type Hook } from '@logto/schemas'; +import { webhookLimit } from '@logto/shared/universal'; +import { Trans, useTranslation } from 'react-i18next'; import Modal from 'react-modal'; +import ConfirmModal from '@/components/ConfirmModal'; +import TextLink from '@/components/TextLink'; +import { contactEmail, contactEmailLink } from '@/consts'; import * as modalStyles from '@/scss/modal.module.scss'; import CreateForm from './CreateForm'; @@ -8,9 +13,33 @@ import CreateForm from './CreateForm'; type Props = { isOpen: boolean; onClose: (createdHook?: Hook) => void; + existingHooksCount: number; }; -function CreateFormModal({ isOpen, onClose }: Props) { +function CreateFormModal({ isOpen, onClose, existingHooksCount }: Props) { + const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); + const shouldBlockCreation = existingHooksCount >= webhookLimit; + + if (shouldBlockCreation) { + return ( + { + onClose(); + }} + > + , + }} + > + {t('webhooks.create_form.block_description', { link: contactEmail })} + + + ); + } + return ( { if (createdHook) { diff --git a/packages/shared/src/constants.ts b/packages/shared/src/constants.ts new file mode 100644 index 000000000..0bf36d544 --- /dev/null +++ b/packages/shared/src/constants.ts @@ -0,0 +1 @@ +export const webhookLimit = 3; diff --git a/packages/shared/src/universal.ts b/packages/shared/src/universal.ts index 7bf661541..64b5349fc 100644 --- a/packages/shared/src/universal.ts +++ b/packages/shared/src/universal.ts @@ -1,2 +1,3 @@ export * from './database/index.js'; export * from './utils/index.js'; +export * from './constants.js';