feat(notif): show success/failure toast for test notifications (#1442)

* feat(notif): show success/failure toast for test notifications

* fix(lang): remove 'successfully' from test notif success strings
This commit is contained in:
TheCatLady
2021-04-26 06:01:31 -04:00
committed by GitHub
parent 4faddf3810
commit 079645c2c7
18 changed files with 642 additions and 286 deletions

View File

@@ -1,6 +1,6 @@
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import React from 'react';
import React, { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
@@ -18,13 +18,16 @@ const messages = defineMessages({
webhookUrlPlaceholder: 'Server Settings → Integrations → Webhooks',
discordsettingssaved: 'Discord notification settings saved successfully!',
discordsettingsfailed: 'Discord notification settings failed to save.',
discordtestsent: 'Discord test notification sent!',
toastDiscordTestSending: 'Sending Discord test notification',
toastDiscordTestSuccess: 'Discord test notification sent!',
toastDiscordTestFailed: 'Discord test notification failed to send.',
validationUrl: 'You must provide a valid URL',
});
const NotificationsDiscord: React.FC = () => {
const intl = useIntl();
const { addToast } = useToasts();
const { addToast, removeToast } = useToasts();
const [isTesting, setIsTesting] = useState(false);
const { data, error, revalidate } = useSWR(
'/api/v1/settings/notifications/discord'
);
@@ -86,20 +89,47 @@ const NotificationsDiscord: React.FC = () => {
>
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
const testSettings = async () => {
await axios.post('/api/v1/settings/notifications/discord/test', {
enabled: true,
types: values.types,
options: {
botUsername: values.botUsername,
botAvatarUrl: values.botAvatarUrl,
webhookUrl: values.webhookUrl,
},
});
setIsTesting(true);
let toastId: string | undefined;
try {
addToast(
intl.formatMessage(messages.toastDiscordTestSending),
{
autoDismiss: false,
appearance: 'info',
},
(id) => {
toastId = id;
}
);
await axios.post('/api/v1/settings/notifications/discord/test', {
enabled: true,
types: values.types,
options: {
botUsername: values.botUsername,
botAvatarUrl: values.botAvatarUrl,
webhookUrl: values.webhookUrl,
},
});
addToast(intl.formatMessage(messages.discordtestsent), {
appearance: 'info',
autoDismiss: true,
});
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastDiscordTestSuccess), {
autoDismiss: true,
appearance: 'success',
});
} catch (e) {
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastDiscordTestFailed), {
autoDismiss: true,
appearance: 'error',
});
} finally {
setIsTesting(false);
}
};
return (
@@ -178,21 +208,22 @@ const NotificationsDiscord: React.FC = () => {
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="warning"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
onClick={(e) => {
e.preventDefault();
testSettings();
}}
>
{intl.formatMessage(globalMessages.test)}
{isTesting
? intl.formatMessage(globalMessages.testing)
: intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="primary"
type="submit"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
>
{isSubmitting
? intl.formatMessage(globalMessages.saving)

View File

@@ -1,6 +1,6 @@
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import React from 'react';
import React, { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
@@ -24,7 +24,9 @@ const messages = defineMessages({
authPass: 'SMTP Password',
emailsettingssaved: 'Email notification settings saved successfully!',
emailsettingsfailed: 'Email notification settings failed to save.',
emailtestsent: 'Email test notification sent!',
toastEmailTestSending: 'Sending email test notification',
toastEmailTestSuccess: 'Email test notification sent!',
toastEmailTestFailed: 'Email test notification failed to send.',
allowselfsigned: 'Allow Self-Signed Certificates',
ssldisabletip:
'SSL should be disabled on standard TLS connections (port 587)',
@@ -56,7 +58,8 @@ export function OpenPgpLink(msg: string): JSX.Element {
const NotificationsEmail: React.FC = () => {
const intl = useIntl();
const { addToast } = useToasts();
const { addToast, removeToast } = useToasts();
const [isTesting, setIsTesting] = useState(false);
const { data, error, revalidate } = useSWR(
'/api/v1/settings/notifications/email'
);
@@ -172,26 +175,53 @@ const NotificationsEmail: React.FC = () => {
>
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
const testSettings = async () => {
await axios.post('/api/v1/settings/notifications/email/test', {
enabled: true,
types: values.types,
options: {
emailFrom: values.emailFrom,
smtpHost: values.smtpHost,
smtpPort: Number(values.smtpPort),
secure: values.secure,
authUser: values.authUser,
authPass: values.authPass,
senderName: values.senderName,
pgpPrivateKey: values.pgpPrivateKey,
pgpPassword: values.pgpPassword,
},
});
setIsTesting(true);
let toastId: string | undefined;
try {
addToast(
intl.formatMessage(messages.toastEmailTestSending),
{
autoDismiss: false,
appearance: 'info',
},
(id) => {
toastId = id;
}
);
await axios.post('/api/v1/settings/notifications/email/test', {
enabled: true,
types: values.types,
options: {
emailFrom: values.emailFrom,
smtpHost: values.smtpHost,
smtpPort: Number(values.smtpPort),
secure: values.secure,
authUser: values.authUser,
authPass: values.authPass,
senderName: values.senderName,
pgpPrivateKey: values.pgpPrivateKey,
pgpPassword: values.pgpPassword,
},
});
addToast(intl.formatMessage(messages.emailtestsent), {
appearance: 'info',
autoDismiss: true,
});
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastEmailTestSuccess), {
autoDismiss: true,
appearance: 'success',
});
} catch (e) {
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastEmailTestFailed), {
autoDismiss: true,
appearance: 'error',
});
} finally {
setIsTesting(false);
}
};
return (
@@ -425,21 +455,22 @@ const NotificationsEmail: React.FC = () => {
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="warning"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
onClick={(e) => {
e.preventDefault();
testSettings();
}}
>
{intl.formatMessage(globalMessages.test)}
{isTesting
? intl.formatMessage(globalMessages.testing)
: intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="primary"
type="submit"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
>
{isSubmitting
? intl.formatMessage(globalMessages.saving)

View File

@@ -1,6 +1,6 @@
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import React from 'react';
import React, { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
@@ -18,12 +18,15 @@ const messages = defineMessages({
profileNameTip: 'Only required if not using the <code>default</code> profile',
settingsSaved: 'LunaSea notification settings saved successfully!',
settingsFailed: 'LunaSea notification settings failed to save.',
testSent: 'LunaSea test notification sent!',
toastLunaSeaTestSending: 'Sending LunaSea test notification',
toastLunaSeaTestSuccess: 'LunaSea test notification sent!',
toastLunaSeaTestFailed: 'LunaSea test notification failed to send.',
});
const NotificationsLunaSea: React.FC = () => {
const intl = useIntl();
const { addToast } = useToasts();
const { addToast, removeToast } = useToasts();
const [isTesting, setIsTesting] = useState(false);
const { data, error, revalidate } = useSWR(
'/api/v1/settings/notifications/lunasea'
);
@@ -79,19 +82,46 @@ const NotificationsLunaSea: React.FC = () => {
>
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
const testSettings = async () => {
await axios.post('/api/v1/settings/notifications/lunasea/test', {
enabled: true,
types: values.types,
options: {
webhookUrl: values.webhookUrl,
profileName: values.profileName,
},
});
setIsTesting(true);
let toastId: string | undefined;
try {
addToast(
intl.formatMessage(messages.toastLunaSeaTestSending),
{
autoDismiss: false,
appearance: 'info',
},
(id) => {
toastId = id;
}
);
await axios.post('/api/v1/settings/notifications/lunasea/test', {
enabled: true,
types: values.types,
options: {
webhookUrl: values.webhookUrl,
profileName: values.profileName,
},
});
addToast(intl.formatMessage(messages.testSent), {
appearance: 'info',
autoDismiss: true,
});
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastLunaSeaTestSuccess), {
autoDismiss: true,
appearance: 'success',
});
} catch (e) {
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastLunaSeaTestFailed), {
autoDismiss: true,
appearance: 'error',
});
} finally {
setIsTesting(false);
}
};
return (
@@ -144,21 +174,22 @@ const NotificationsLunaSea: React.FC = () => {
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="warning"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
onClick={(e) => {
e.preventDefault();
testSettings();
}}
>
{intl.formatMessage(globalMessages.test)}
{isTesting
? intl.formatMessage(globalMessages.testing)
: intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="primary"
type="submit"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
>
{isSubmitting
? intl.formatMessage(globalMessages.saving)

View File

@@ -1,6 +1,6 @@
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import React from 'react';
import React, { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
@@ -18,14 +18,17 @@ const messages = defineMessages({
pushbulletSettingsSaved:
'Pushbullet notification settings saved successfully!',
pushbulletSettingsFailed: 'Pushbullet notification settings failed to save.',
testSent: 'Pushbullet test notification sent!',
toastPushbulletTestSending: 'Sending Pushbullet test notification',
toastPushbulletTestSuccess: 'Pushbullet test notification sent!',
toastPushbulletTestFailed: 'Pushbullet test notification failed to send.',
settingUpPushbulletDescription:
'To configure Pushbullet notifications, you will need to <CreateAccessTokenLink>create an access token</CreateAccessTokenLink>.',
});
const NotificationsPushbullet: React.FC = () => {
const intl = useIntl();
const { addToast } = useToasts();
const { addToast, removeToast } = useToasts();
const [isTesting, setIsTesting] = useState(false);
const { data, error, revalidate } = useSWR(
'/api/v1/settings/notifications/pushbullet'
);
@@ -77,18 +80,45 @@ const NotificationsPushbullet: React.FC = () => {
>
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
const testSettings = async () => {
await axios.post('/api/v1/settings/notifications/pushbullet/test', {
enabled: true,
types: values.types,
options: {
accessToken: values.accessToken,
},
});
setIsTesting(true);
let toastId: string | undefined;
try {
addToast(
intl.formatMessage(messages.toastPushbulletTestSending),
{
autoDismiss: false,
appearance: 'info',
},
(id) => {
toastId = id;
}
);
await axios.post('/api/v1/settings/notifications/pushbullet/test', {
enabled: true,
types: values.types,
options: {
accessToken: values.accessToken,
},
});
addToast(intl.formatMessage(messages.testSent), {
appearance: 'info',
autoDismiss: true,
});
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastPushbulletTestSuccess), {
autoDismiss: true,
appearance: 'success',
});
} catch (e) {
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastPushbulletTestFailed), {
autoDismiss: true,
appearance: 'error',
});
} finally {
setIsTesting(false);
}
};
return (
@@ -150,21 +180,22 @@ const NotificationsPushbullet: React.FC = () => {
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="warning"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
onClick={(e) => {
e.preventDefault();
testSettings();
}}
>
{intl.formatMessage(globalMessages.test)}
{isTesting
? intl.formatMessage(globalMessages.testing)
: intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="primary"
type="submit"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
>
{isSubmitting
? intl.formatMessage(globalMessages.saving)

View File

@@ -1,6 +1,6 @@
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import React from 'react';
import React, { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
@@ -19,14 +19,17 @@ const messages = defineMessages({
validationUserTokenRequired: 'You must provide a valid user key',
pushoversettingssaved: 'Pushover notification settings saved successfully!',
pushoversettingsfailed: 'Pushover notification settings failed to save.',
testsent: 'Pushover test notification sent!',
toastPushoverTestSending: 'Sending Pushover test notification',
toastPushoverTestSuccess: 'Pushover test notification sent!',
toastPushoverTestFailed: 'Pushover test notification failed to send.',
settinguppushoverDescription:
'To configure Pushover notifications, you will need to <RegisterApplicationLink>register an application</RegisterApplicationLink> and enter the API token below. (You can use one of the <IconLink>official Overseerr icons on GitHub</IconLink>.)',
'To configure Pushover notifications, you will need to <RegisterApplicationLink>register an application</RegisterApplicationLink>. (You can use one of the <IconLink>official Overseerr icons on GitHub</IconLink>.)',
});
const NotificationsPushover: React.FC = () => {
const intl = useIntl();
const { addToast } = useToasts();
const { addToast, removeToast } = useToasts();
const [isTesting, setIsTesting] = useState(false);
const { data, error, revalidate } = useSWR(
'/api/v1/settings/notifications/pushover'
);
@@ -97,19 +100,46 @@ const NotificationsPushover: React.FC = () => {
>
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
const testSettings = async () => {
await axios.post('/api/v1/settings/notifications/pushover/test', {
enabled: true,
types: values.types,
options: {
accessToken: values.accessToken,
userToken: values.userToken,
},
});
setIsTesting(true);
let toastId: string | undefined;
try {
addToast(
intl.formatMessage(messages.toastPushoverTestSending),
{
autoDismiss: false,
appearance: 'info',
},
(id) => {
toastId = id;
}
);
await axios.post('/api/v1/settings/notifications/pushover/test', {
enabled: true,
types: values.types,
options: {
accessToken: values.accessToken,
userToken: values.userToken,
},
});
addToast(intl.formatMessage(messages.testsent), {
appearance: 'info',
autoDismiss: true,
});
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastPushoverTestSuccess), {
autoDismiss: true,
appearance: 'success',
});
} catch (e) {
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastPushoverTestFailed), {
autoDismiss: true,
appearance: 'error',
});
} finally {
setIsTesting(false);
}
};
return (
@@ -199,21 +229,22 @@ const NotificationsPushover: React.FC = () => {
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="warning"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
onClick={(e) => {
e.preventDefault();
testSettings();
}}
>
{intl.formatMessage(globalMessages.test)}
{isTesting
? intl.formatMessage(globalMessages.testing)
: intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="primary"
type="submit"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
>
{isSubmitting
? intl.formatMessage(globalMessages.saving)

View File

@@ -1,6 +1,6 @@
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import React from 'react';
import React, { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
@@ -16,7 +16,9 @@ const messages = defineMessages({
webhookUrl: 'Webhook URL',
slacksettingssaved: 'Slack notification settings saved successfully!',
slacksettingsfailed: 'Slack notification settings failed to save.',
testsent: 'Slack test notification sent!',
toastSlackTestSending: 'Sending Slack test notification',
toastSlackTestSuccess: 'Slack test notification sent!',
toastSlackTestFailed: 'Slack test notification failed to send.',
settingupslackDescription:
'To configure Slack notifications, you will need to create an <WebhookLink>Incoming Webhook</WebhookLink> integration and enter the webhook URL below.',
validationWebhookUrl: 'You must provide a valid URL',
@@ -24,7 +26,8 @@ const messages = defineMessages({
const NotificationsSlack: React.FC = () => {
const intl = useIntl();
const { addToast } = useToasts();
const { addToast, removeToast } = useToasts();
const [isTesting, setIsTesting] = useState(false);
const { data, error, revalidate } = useSWR(
'/api/v1/settings/notifications/slack'
);
@@ -103,18 +106,45 @@ const NotificationsSlack: React.FC = () => {
setFieldValue,
}) => {
const testSettings = async () => {
await axios.post('/api/v1/settings/notifications/slack/test', {
enabled: true,
types: values.types,
options: {
webhookUrl: values.webhookUrl,
},
});
setIsTesting(true);
let toastId: string | undefined;
try {
addToast(
intl.formatMessage(messages.toastSlackTestSending),
{
autoDismiss: false,
appearance: 'info',
},
(id) => {
toastId = id;
}
);
await axios.post('/api/v1/settings/notifications/slack/test', {
enabled: true,
types: values.types,
options: {
webhookUrl: values.webhookUrl,
},
});
addToast(intl.formatMessage(messages.testsent), {
appearance: 'info',
autoDismiss: true,
});
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastSlackTestSuccess), {
autoDismiss: true,
appearance: 'success',
});
} catch (e) {
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastSlackTestFailed), {
autoDismiss: true,
appearance: 'error',
});
} finally {
setIsTesting(false);
}
};
return (
@@ -150,21 +180,22 @@ const NotificationsSlack: React.FC = () => {
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="warning"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
onClick={(e) => {
e.preventDefault();
testSettings();
}}
>
{intl.formatMessage(globalMessages.test)}
{isTesting
? intl.formatMessage(globalMessages.testing)
: intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="primary"
type="submit"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
>
{isSubmitting
? intl.formatMessage(globalMessages.saving)

View File

@@ -1,6 +1,6 @@
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import React from 'react';
import React, { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
@@ -22,7 +22,9 @@ const messages = defineMessages({
validationChatIdRequired: 'You must provide a valid chat ID',
telegramsettingssaved: 'Telegram notification settings saved successfully!',
telegramsettingsfailed: 'Telegram notification settings failed to save.',
telegramtestsent: 'Telegram test notification sent!',
toastTelegramTestSending: 'Sending Telegram test notification',
toastTelegramTestSuccess: 'Telegram test notification sent!',
toastTelegramTestFailed: 'Telegram test notification failed to send.',
settinguptelegramDescription:
'To configure Telegram notifications, you will need to <CreateBotLink>create a bot</CreateBotLink> and get the bot API key. Additionally, you will need the chat ID for the chat to which you would like to send notifications. You can find this by adding <GetIdBotLink>@get_id_bot</GetIdBotLink> to the chat and issuing the <code>/my_id</code> command.',
sendSilently: 'Send Silently',
@@ -31,7 +33,8 @@ const messages = defineMessages({
const NotificationsTelegram: React.FC = () => {
const intl = useIntl();
const { addToast } = useToasts();
const { addToast, removeToast } = useToasts();
const [isTesting, setIsTesting] = useState(false);
const { data, error, revalidate } = useSWR(
'/api/v1/settings/notifications/telegram'
);
@@ -102,21 +105,48 @@ const NotificationsTelegram: React.FC = () => {
>
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
const testSettings = async () => {
await axios.post('/api/v1/settings/notifications/telegram/test', {
enabled: true,
types: values.types,
options: {
botAPI: values.botAPI,
chatId: values.chatId,
sendSilently: values.sendSilently,
botUsername: values.botUsername,
},
});
setIsTesting(true);
let toastId: string | undefined;
try {
addToast(
intl.formatMessage(messages.toastTelegramTestSending),
{
autoDismiss: false,
appearance: 'info',
},
(id) => {
toastId = id;
}
);
await axios.post('/api/v1/settings/notifications/telegram/test', {
enabled: true,
types: values.types,
options: {
botAPI: values.botAPI,
chatId: values.chatId,
sendSilently: values.sendSilently,
botUsername: values.botUsername,
},
});
addToast(intl.formatMessage(messages.telegramtestsent), {
appearance: 'info',
autoDismiss: true,
});
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastTelegramTestSuccess), {
autoDismiss: true,
appearance: 'success',
});
} catch (e) {
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastTelegramTestFailed), {
autoDismiss: true,
appearance: 'error',
});
} finally {
setIsTesting(false);
}
};
return (
@@ -245,21 +275,22 @@ const NotificationsTelegram: React.FC = () => {
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="warning"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
onClick={(e) => {
e.preventDefault();
testSettings();
}}
>
{intl.formatMessage(globalMessages.test)}
{isTesting
? intl.formatMessage(globalMessages.testing)
: intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="primary"
type="submit"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
>
{isSubmitting
? intl.formatMessage(globalMessages.saving)

View File

@@ -1,6 +1,6 @@
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import React from 'react';
import React, { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
@@ -13,12 +13,15 @@ const messages = defineMessages({
agentenabled: 'Enable Agent',
webpushsettingssaved: 'Web push notification settings saved successfully!',
webpushsettingsfailed: 'Web push notification settings failed to save.',
testsent: 'Web push test notification sent!',
toastWebPushTestSending: 'Sending web push test notification',
toastWebPushTestSuccess: 'Web push test notification sent!',
toastWebPushTestFailed: 'Web push test notification failed to send.',
});
const NotificationsWebPush: React.FC = () => {
const intl = useIntl();
const { addToast } = useToasts();
const { addToast, removeToast } = useToasts();
const [isTesting, setIsTesting] = useState(false);
const { data, error, revalidate } = useSWR(
'/api/v1/settings/notifications/webpush'
);
@@ -57,16 +60,43 @@ const NotificationsWebPush: React.FC = () => {
>
{({ isSubmitting, values, isValid, setFieldValue }) => {
const testSettings = async () => {
await axios.post('/api/v1/settings/notifications/webpush/test', {
enabled: true,
types: values.types,
options: {},
});
setIsTesting(true);
let toastId: string | undefined;
try {
addToast(
intl.formatMessage(messages.toastWebPushTestSending),
{
autoDismiss: false,
appearance: 'info',
},
(id) => {
toastId = id;
}
);
await axios.post('/api/v1/settings/notifications/webpush/test', {
enabled: true,
types: values.types,
options: {},
});
addToast(intl.formatMessage(messages.testsent), {
appearance: 'info',
autoDismiss: true,
});
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastWebPushTestSuccess), {
autoDismiss: true,
appearance: 'success',
});
} catch (e) {
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastWebPushTestFailed), {
autoDismiss: true,
appearance: 'error',
});
} finally {
setIsTesting(false);
}
};
return (
@@ -88,21 +118,22 @@ const NotificationsWebPush: React.FC = () => {
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="warning"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
onClick={(e) => {
e.preventDefault();
testSettings();
}}
>
{intl.formatMessage(globalMessages.test)}
{isTesting
? intl.formatMessage(globalMessages.testing)
: intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="primary"
type="submit"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
>
{isSubmitting
? intl.formatMessage(globalMessages.saving)

View File

@@ -2,7 +2,7 @@ import { QuestionMarkCircleIcon, RefreshIcon } from '@heroicons/react/solid';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import dynamic from 'next/dynamic';
import React from 'react';
import React, { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
@@ -46,7 +46,9 @@ const messages = defineMessages({
validationJsonPayloadRequired: 'You must provide a valid JSON payload',
webhooksettingssaved: 'Webhook notification settings saved successfully!',
webhooksettingsfailed: 'Webhook notification settings failed to save.',
testsent: 'Webhook test notification sent!',
toastWebhookTestSending: 'Sending webhook test notification',
toastWebhookTestSuccess: 'Webhook test notification sent!',
toastWebhookTestFailed: 'Webhook test notification failed to send.',
resetPayload: 'Reset to Default',
resetPayloadSuccess: 'JSON payload reset successfully!',
customJson: 'JSON Payload',
@@ -56,7 +58,8 @@ const messages = defineMessages({
const NotificationsWebhook: React.FC = () => {
const intl = useIntl();
const { addToast } = useToasts();
const { addToast, removeToast } = useToasts();
const [isTesting, setIsTesting] = useState(false);
const { data, error, revalidate } = useSWR(
'/api/v1/settings/notifications/webhook'
);
@@ -157,20 +160,47 @@ const NotificationsWebhook: React.FC = () => {
};
const testSettings = async () => {
await axios.post('/api/v1/settings/notifications/webhook/test', {
enabled: true,
types: values.types,
options: {
webhookUrl: values.webhookUrl,
jsonPayload: JSON.stringify(values.jsonPayload),
authHeader: values.authHeader,
},
});
setIsTesting(true);
let toastId: string | undefined;
try {
addToast(
intl.formatMessage(messages.toastWebhookTestSending),
{
autoDismiss: false,
appearance: 'info',
},
(id) => {
toastId = id;
}
);
await axios.post('/api/v1/settings/notifications/webhook/test', {
enabled: true,
types: values.types,
options: {
webhookUrl: values.webhookUrl,
jsonPayload: JSON.stringify(values.jsonPayload),
authHeader: values.authHeader,
},
});
addToast(intl.formatMessage(messages.testsent), {
appearance: 'info',
autoDismiss: true,
});
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastWebhookTestSuccess), {
autoDismiss: true,
appearance: 'success',
});
} catch (e) {
if (toastId) {
removeToast(toastId);
}
addToast(intl.formatMessage(messages.toastWebhookTestFailed), {
autoDismiss: true,
appearance: 'error',
});
} finally {
setIsTesting(false);
}
};
return (
@@ -257,21 +287,22 @@ const NotificationsWebhook: React.FC = () => {
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="warning"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
onClick={(e) => {
e.preventDefault();
testSettings();
}}
>
{intl.formatMessage(globalMessages.test)}
{isTesting
? intl.formatMessage(globalMessages.testing)
: intl.formatMessage(globalMessages.test)}
</Button>
</span>
<span className="inline-flex ml-3 rounded-md shadow-sm">
<Button
buttonType="primary"
type="submit"
disabled={isSubmitting || !isValid}
disabled={isSubmitting || !isValid || isTesting}
>
{isSubmitting
? intl.formatMessage(globalMessages.saving)

View File

@@ -19,8 +19,6 @@ const messages = defineMessages({
notificationsettings: 'Notification Settings',
email: 'Email',
webpush: 'Web Push',
toastSettingsSuccess: 'Notification settings saved successfully!',
toastSettingsFailure: 'Something went wrong while saving settings.',
});
const UserNotificationSettings: React.FC = ({ children }) => {