0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-30 20:33:54 -05:00

feat(console): add webhook creation limit reminder (#3852)

This commit is contained in:
Xiao Yijun 2023-05-17 16:17:00 +08:00 committed by GitHub
parent f953289f75
commit 1b6bb9b1cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 40 additions and 6 deletions

View file

@ -1,4 +1,5 @@
export const discordLink = 'https://discord.gg/UEPaF3j5e6'; export const discordLink = 'https://discord.gg/UEPaF3j5e6';
export const githubLink = 'https://github.com/logto-io/logto'; export const githubLink = 'https://github.com/logto-io/logto';
export const githubIssuesLink = 'https://github.com/logto-io/logto/issues'; 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}`;

View file

@ -1,10 +1,11 @@
import { contactEmailLink } from '@/consts';
import { buildUrl } from '@/utils/url'; import { buildUrl } from '@/utils/url';
export const reservationLink = buildUrl('https://calendly.com/logto/30min', { export const reservationLink = buildUrl('https://calendly.com/logto/30min', {
// Note: month format is YYYY-MM // Note: month format is YYYY-MM
month: new Date().toISOString().slice(0, 7), 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', subject: 'Cloud pricing and special offer',
}).replace(/\+/g, '%20'); }).replace(/\+/g, '%20');

View file

@ -4,6 +4,7 @@ import ReactModal from 'react-modal';
import Button from '@/components/Button'; import Button from '@/components/Button';
import ModalLayout from '@/components/ModalLayout'; import ModalLayout from '@/components/ModalLayout';
import TextLink from '@/components/TextLink'; import TextLink from '@/components/TextLink';
import { contactEmail, contactEmailLink } from '@/consts';
import * as modalStyles from '@/scss/modal.module.scss'; import * as modalStyles from '@/scss/modal.module.scss';
import * as styles from './index.module.scss'; import * as styles from './index.module.scss';
@ -13,8 +14,7 @@ type Props = {
onClose: () => void; onClose: () => void;
}; };
const contactUsEmail = 'contact@logto.io'; const mailToLink = `${contactEmailLink}?subject=Account%20Deletion%20Request`;
const mailToLink = `mailto:${contactUsEmail}?subject=Account%20Deletion%20Request`;
function DeleteAccountModal({ isOpen, onClose }: Props) { function DeleteAccountModal({ isOpen, onClose }: Props) {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
@ -40,7 +40,7 @@ function DeleteAccountModal({ isOpen, onClose }: Props) {
a: <TextLink href={mailToLink} className={styles.mail} />, a: <TextLink href={mailToLink} className={styles.mail} />,
}} }}
> >
{t('profile.delete_account.dialog_paragraph_2', { mail: contactUsEmail })} {t('profile.delete_account.dialog_paragraph_2', { mail: contactEmail })}
</Trans> </Trans>
</p> </p>
<p>{t('profile.delete_account.dialog_paragraph_3')}</p> <p>{t('profile.delete_account.dialog_paragraph_3')}</p>

View file

@ -1,6 +1,11 @@
import { type Hook } from '@logto/schemas'; import { type Hook } from '@logto/schemas';
import { webhookLimit } from '@logto/shared/universal';
import { Trans, useTranslation } from 'react-i18next';
import Modal from 'react-modal'; 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 * as modalStyles from '@/scss/modal.module.scss';
import CreateForm from './CreateForm'; import CreateForm from './CreateForm';
@ -8,9 +13,33 @@ import CreateForm from './CreateForm';
type Props = { type Props = {
isOpen: boolean; isOpen: boolean;
onClose: (createdHook?: Hook) => void; 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 (
<ConfirmModal
isOpen={isOpen}
cancelButtonText="general.got_it"
onCancel={() => {
onClose();
}}
>
<Trans
components={{
a: <TextLink to={contactEmailLink} />,
}}
>
{t('webhooks.create_form.block_description', { link: contactEmail })}
</Trans>
</ConfirmModal>
);
}
return ( return (
<Modal <Modal
shouldCloseOnOverlayClick shouldCloseOnOverlayClick

View file

@ -125,6 +125,7 @@ function Webhooks() {
}} }}
widgets={ widgets={
<CreateFormModal <CreateFormModal
existingHooksCount={data?.length ?? 0}
isOpen={isCreateNew} isOpen={isCreateNew}
onClose={(createdHook?: Hook) => { onClose={(createdHook?: Hook) => {
if (createdHook) { if (createdHook) {

View file

@ -0,0 +1 @@
export const webhookLimit = 3;

View file

@ -1,2 +1,3 @@
export * from './database/index.js'; export * from './database/index.js';
export * from './utils/index.js'; export * from './utils/index.js';
export * from './constants.js';