mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
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:
@@ -272,7 +272,7 @@ class DiscordAgent
|
|||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response.data,
|
response: e.response?.data,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@@ -170,7 +170,7 @@ class PushbulletAgent
|
|||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response.data,
|
response: e.response?.data,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@@ -196,7 +196,7 @@ class PushoverAgent
|
|||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response.data,
|
response: e.response?.data,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@@ -254,7 +254,7 @@ class SlackAgent
|
|||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response.data,
|
response: e.response?.data,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@@ -244,7 +244,7 @@ class TelegramAgent
|
|||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response.data,
|
response: e.response?.data,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@@ -154,7 +154,7 @@ class WebhookAgent
|
|||||||
type: Notification[type],
|
type: Notification[type],
|
||||||
subject: payload.subject,
|
subject: payload.subject,
|
||||||
errorMessage: e.message,
|
errorMessage: e.message,
|
||||||
response: e.response.data,
|
response: e.response?.data,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@@ -28,23 +28,30 @@ notificationRoutes.post('/discord', (req, res) => {
|
|||||||
res.status(200).json(settings.notifications.agents.discord);
|
res.status(200).json(settings.notifications.agents.discord);
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.post('/discord/test', (req, res, next) => {
|
notificationRoutes.post('/discord/test', async (req, res, next) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
return next({
|
return next({
|
||||||
status: 500,
|
status: 500,
|
||||||
message: 'User information missing from request',
|
message: 'User information is missing from the request.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const discordAgent = new DiscordAgent(req.body);
|
const discordAgent = new DiscordAgent(req.body);
|
||||||
discordAgent.send(Notification.TEST_NOTIFICATION, {
|
if (
|
||||||
notifyUser: req.user,
|
await discordAgent.send(Notification.TEST_NOTIFICATION, {
|
||||||
subject: 'Test Notification',
|
notifyUser: req.user,
|
||||||
message:
|
subject: 'Test Notification',
|
||||||
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
message:
|
||||||
});
|
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
||||||
|
})
|
||||||
return res.status(204).send();
|
) {
|
||||||
|
return res.status(204).send();
|
||||||
|
} else {
|
||||||
|
return next({
|
||||||
|
status: 500,
|
||||||
|
message: 'Failed to send Discord notification.',
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.get('/slack', (_req, res) => {
|
notificationRoutes.get('/slack', (_req, res) => {
|
||||||
@@ -62,23 +69,30 @@ notificationRoutes.post('/slack', (req, res) => {
|
|||||||
res.status(200).json(settings.notifications.agents.slack);
|
res.status(200).json(settings.notifications.agents.slack);
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.post('/slack/test', (req, res, next) => {
|
notificationRoutes.post('/slack/test', async (req, res, next) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
return next({
|
return next({
|
||||||
status: 500,
|
status: 500,
|
||||||
message: 'User information missing from request',
|
message: 'User information is missing from the request.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const slackAgent = new SlackAgent(req.body);
|
const slackAgent = new SlackAgent(req.body);
|
||||||
slackAgent.send(Notification.TEST_NOTIFICATION, {
|
if (
|
||||||
notifyUser: req.user,
|
await slackAgent.send(Notification.TEST_NOTIFICATION, {
|
||||||
subject: 'Test Notification',
|
notifyUser: req.user,
|
||||||
message:
|
subject: 'Test Notification',
|
||||||
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
message:
|
||||||
});
|
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
||||||
|
})
|
||||||
return res.status(204).send();
|
) {
|
||||||
|
return res.status(204).send();
|
||||||
|
} else {
|
||||||
|
return next({
|
||||||
|
status: 500,
|
||||||
|
message: 'Failed to send Slack notification.',
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.get('/telegram', (_req, res) => {
|
notificationRoutes.get('/telegram', (_req, res) => {
|
||||||
@@ -96,23 +110,30 @@ notificationRoutes.post('/telegram', (req, res) => {
|
|||||||
res.status(200).json(settings.notifications.agents.telegram);
|
res.status(200).json(settings.notifications.agents.telegram);
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.post('/telegram/test', (req, res, next) => {
|
notificationRoutes.post('/telegram/test', async (req, res, next) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
return next({
|
return next({
|
||||||
status: 500,
|
status: 500,
|
||||||
message: 'User information missing from request',
|
message: 'User information is missing from the request.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const telegramAgent = new TelegramAgent(req.body);
|
const telegramAgent = new TelegramAgent(req.body);
|
||||||
telegramAgent.send(Notification.TEST_NOTIFICATION, {
|
if (
|
||||||
notifyUser: req.user,
|
await telegramAgent.send(Notification.TEST_NOTIFICATION, {
|
||||||
subject: 'Test Notification',
|
notifyUser: req.user,
|
||||||
message:
|
subject: 'Test Notification',
|
||||||
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
message:
|
||||||
});
|
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
||||||
|
})
|
||||||
return res.status(204).send();
|
) {
|
||||||
|
return res.status(204).send();
|
||||||
|
} else {
|
||||||
|
return next({
|
||||||
|
status: 500,
|
||||||
|
message: 'Failed to send Telegram notification.',
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.get('/pushbullet', (_req, res) => {
|
notificationRoutes.get('/pushbullet', (_req, res) => {
|
||||||
@@ -130,23 +151,30 @@ notificationRoutes.post('/pushbullet', (req, res) => {
|
|||||||
res.status(200).json(settings.notifications.agents.pushbullet);
|
res.status(200).json(settings.notifications.agents.pushbullet);
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.post('/pushbullet/test', (req, res, next) => {
|
notificationRoutes.post('/pushbullet/test', async (req, res, next) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
return next({
|
return next({
|
||||||
status: 500,
|
status: 500,
|
||||||
message: 'User information missing from request',
|
message: 'User information is missing from the request.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const pushbulletAgent = new PushbulletAgent(req.body);
|
const pushbulletAgent = new PushbulletAgent(req.body);
|
||||||
pushbulletAgent.send(Notification.TEST_NOTIFICATION, {
|
if (
|
||||||
notifyUser: req.user,
|
await pushbulletAgent.send(Notification.TEST_NOTIFICATION, {
|
||||||
subject: 'Test Notification',
|
notifyUser: req.user,
|
||||||
message:
|
subject: 'Test Notification',
|
||||||
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
message:
|
||||||
});
|
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
||||||
|
})
|
||||||
return res.status(204).send();
|
) {
|
||||||
|
return res.status(204).send();
|
||||||
|
} else {
|
||||||
|
return next({
|
||||||
|
status: 500,
|
||||||
|
message: 'Failed to send Pushbullet notification.',
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.get('/pushover', (_req, res) => {
|
notificationRoutes.get('/pushover', (_req, res) => {
|
||||||
@@ -164,23 +192,30 @@ notificationRoutes.post('/pushover', (req, res) => {
|
|||||||
res.status(200).json(settings.notifications.agents.pushover);
|
res.status(200).json(settings.notifications.agents.pushover);
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.post('/pushover/test', (req, res, next) => {
|
notificationRoutes.post('/pushover/test', async (req, res, next) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
return next({
|
return next({
|
||||||
status: 500,
|
status: 500,
|
||||||
message: 'User information missing from request',
|
message: 'User information is missing from the request.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const pushoverAgent = new PushoverAgent(req.body);
|
const pushoverAgent = new PushoverAgent(req.body);
|
||||||
pushoverAgent.send(Notification.TEST_NOTIFICATION, {
|
if (
|
||||||
notifyUser: req.user,
|
await pushoverAgent.send(Notification.TEST_NOTIFICATION, {
|
||||||
subject: 'Test Notification',
|
notifyUser: req.user,
|
||||||
message:
|
subject: 'Test Notification',
|
||||||
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
message:
|
||||||
});
|
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
||||||
|
})
|
||||||
return res.status(204).send();
|
) {
|
||||||
|
return res.status(204).send();
|
||||||
|
} else {
|
||||||
|
return next({
|
||||||
|
status: 500,
|
||||||
|
message: 'Failed to send Pushover notification.',
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.get('/email', (_req, res) => {
|
notificationRoutes.get('/email', (_req, res) => {
|
||||||
@@ -198,23 +233,30 @@ notificationRoutes.post('/email', (req, res) => {
|
|||||||
res.status(200).json(settings.notifications.agents.email);
|
res.status(200).json(settings.notifications.agents.email);
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.post('/email/test', (req, res, next) => {
|
notificationRoutes.post('/email/test', async (req, res, next) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
return next({
|
return next({
|
||||||
status: 500,
|
status: 500,
|
||||||
message: 'User information missing from request',
|
message: 'User information is missing from the request.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const emailAgent = new EmailAgent(req.body);
|
const emailAgent = new EmailAgent(req.body);
|
||||||
emailAgent.send(Notification.TEST_NOTIFICATION, {
|
if (
|
||||||
notifyUser: req.user,
|
await emailAgent.send(Notification.TEST_NOTIFICATION, {
|
||||||
subject: 'Test Notification',
|
notifyUser: req.user,
|
||||||
message:
|
subject: 'Test Notification',
|
||||||
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
message:
|
||||||
});
|
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
||||||
|
})
|
||||||
return res.status(204).send();
|
) {
|
||||||
|
return res.status(204).send();
|
||||||
|
} else {
|
||||||
|
return next({
|
||||||
|
status: 500,
|
||||||
|
message: 'Failed to send email notification.',
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.get('/webpush', (_req, res) => {
|
notificationRoutes.get('/webpush', (_req, res) => {
|
||||||
@@ -232,7 +274,7 @@ notificationRoutes.post('/webpush', (req, res) => {
|
|||||||
res.status(200).json(settings.notifications.agents.webpush);
|
res.status(200).json(settings.notifications.agents.webpush);
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.post('/webpush/test', (req, res, next) => {
|
notificationRoutes.post('/webpush/test', async (req, res, next) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
return next({
|
return next({
|
||||||
status: 500,
|
status: 500,
|
||||||
@@ -241,14 +283,21 @@ notificationRoutes.post('/webpush/test', (req, res, next) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const webpushAgent = new WebPushAgent(req.body);
|
const webpushAgent = new WebPushAgent(req.body);
|
||||||
webpushAgent.send(Notification.TEST_NOTIFICATION, {
|
if (
|
||||||
notifyUser: req.user,
|
await webpushAgent.send(Notification.TEST_NOTIFICATION, {
|
||||||
subject: 'Test Notification',
|
notifyUser: req.user,
|
||||||
message:
|
subject: 'Test Notification',
|
||||||
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
message:
|
||||||
});
|
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
||||||
|
})
|
||||||
return res.status(204).send();
|
) {
|
||||||
|
return res.status(204).send();
|
||||||
|
} else {
|
||||||
|
return next({
|
||||||
|
status: 500,
|
||||||
|
message: 'Failed to send web push notification.',
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.get('/webhook', (_req, res) => {
|
notificationRoutes.get('/webhook', (_req, res) => {
|
||||||
@@ -296,11 +345,11 @@ notificationRoutes.post('/webhook', (req, res, next) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.post('/webhook/test', (req, res, next) => {
|
notificationRoutes.post('/webhook/test', async (req, res, next) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
return next({
|
return next({
|
||||||
status: 500,
|
status: 500,
|
||||||
message: 'User information missing from request',
|
message: 'User information is missing from the request.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,14 +369,21 @@ notificationRoutes.post('/webhook/test', (req, res, next) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const webhookAgent = new WebhookAgent(testBody);
|
const webhookAgent = new WebhookAgent(testBody);
|
||||||
webhookAgent.send(Notification.TEST_NOTIFICATION, {
|
if (
|
||||||
notifyUser: req.user,
|
await webhookAgent.send(Notification.TEST_NOTIFICATION, {
|
||||||
subject: 'Test Notification',
|
notifyUser: req.user,
|
||||||
message:
|
subject: 'Test Notification',
|
||||||
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
message:
|
||||||
});
|
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
||||||
|
})
|
||||||
return res.status(204).send();
|
) {
|
||||||
|
return res.status(204).send();
|
||||||
|
} else {
|
||||||
|
return next({
|
||||||
|
status: 500,
|
||||||
|
message: 'Failed to send webhook notification.',
|
||||||
|
});
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
next({ status: 500, message: e.message });
|
next({ status: 500, message: e.message });
|
||||||
}
|
}
|
||||||
@@ -348,7 +404,7 @@ notificationRoutes.post('/lunasea', (req, res) => {
|
|||||||
res.status(200).json(settings.notifications.agents.lunasea);
|
res.status(200).json(settings.notifications.agents.lunasea);
|
||||||
});
|
});
|
||||||
|
|
||||||
notificationRoutes.post('/lunasea/test', (req, res, next) => {
|
notificationRoutes.post('/lunasea/test', async (req, res, next) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
return next({
|
return next({
|
||||||
status: 500,
|
status: 500,
|
||||||
@@ -357,14 +413,21 @@ notificationRoutes.post('/lunasea/test', (req, res, next) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const lunaseaAgent = new LunaSeaAgent(req.body);
|
const lunaseaAgent = new LunaSeaAgent(req.body);
|
||||||
lunaseaAgent.send(Notification.TEST_NOTIFICATION, {
|
if (
|
||||||
notifyUser: req.user,
|
await lunaseaAgent.send(Notification.TEST_NOTIFICATION, {
|
||||||
subject: 'Test Notification',
|
notifyUser: req.user,
|
||||||
message:
|
subject: 'Test Notification',
|
||||||
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
message:
|
||||||
});
|
'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
|
||||||
|
})
|
||||||
return res.status(204).send();
|
) {
|
||||||
|
return res.status(204).send();
|
||||||
|
} else {
|
||||||
|
return next({
|
||||||
|
status: 500,
|
||||||
|
message: 'Failed to send web push notification.',
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default notificationRoutes;
|
export default notificationRoutes;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Field, Form, Formik } from 'formik';
|
import { Field, Form, Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
import { useToasts } from 'react-toast-notifications';
|
import { useToasts } from 'react-toast-notifications';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
@@ -18,13 +18,16 @@ const messages = defineMessages({
|
|||||||
webhookUrlPlaceholder: 'Server Settings → Integrations → Webhooks',
|
webhookUrlPlaceholder: 'Server Settings → Integrations → Webhooks',
|
||||||
discordsettingssaved: 'Discord notification settings saved successfully!',
|
discordsettingssaved: 'Discord notification settings saved successfully!',
|
||||||
discordsettingsfailed: 'Discord notification settings failed to save.',
|
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',
|
validationUrl: 'You must provide a valid URL',
|
||||||
});
|
});
|
||||||
|
|
||||||
const NotificationsDiscord: React.FC = () => {
|
const NotificationsDiscord: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { addToast } = useToasts();
|
const { addToast, removeToast } = useToasts();
|
||||||
|
const [isTesting, setIsTesting] = useState(false);
|
||||||
const { data, error, revalidate } = useSWR(
|
const { data, error, revalidate } = useSWR(
|
||||||
'/api/v1/settings/notifications/discord'
|
'/api/v1/settings/notifications/discord'
|
||||||
);
|
);
|
||||||
@@ -86,20 +89,47 @@ const NotificationsDiscord: React.FC = () => {
|
|||||||
>
|
>
|
||||||
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
|
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
|
||||||
const testSettings = async () => {
|
const testSettings = async () => {
|
||||||
await axios.post('/api/v1/settings/notifications/discord/test', {
|
setIsTesting(true);
|
||||||
enabled: true,
|
let toastId: string | undefined;
|
||||||
types: values.types,
|
try {
|
||||||
options: {
|
addToast(
|
||||||
botUsername: values.botUsername,
|
intl.formatMessage(messages.toastDiscordTestSending),
|
||||||
botAvatarUrl: values.botAvatarUrl,
|
{
|
||||||
webhookUrl: values.webhookUrl,
|
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), {
|
if (toastId) {
|
||||||
appearance: 'info',
|
removeToast(toastId);
|
||||||
autoDismiss: true,
|
}
|
||||||
});
|
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 (
|
return (
|
||||||
@@ -178,21 +208,22 @@ const NotificationsDiscord: React.FC = () => {
|
|||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="warning"
|
buttonType="warning"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
testSettings();
|
testSettings();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(globalMessages.test)}
|
{isTesting
|
||||||
|
? intl.formatMessage(globalMessages.testing)
|
||||||
|
: intl.formatMessage(globalMessages.test)}
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="primary"
|
buttonType="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
>
|
>
|
||||||
{isSubmitting
|
{isSubmitting
|
||||||
? intl.formatMessage(globalMessages.saving)
|
? intl.formatMessage(globalMessages.saving)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Field, Form, Formik } from 'formik';
|
import { Field, Form, Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
import { useToasts } from 'react-toast-notifications';
|
import { useToasts } from 'react-toast-notifications';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
@@ -24,7 +24,9 @@ const messages = defineMessages({
|
|||||||
authPass: 'SMTP Password',
|
authPass: 'SMTP Password',
|
||||||
emailsettingssaved: 'Email notification settings saved successfully!',
|
emailsettingssaved: 'Email notification settings saved successfully!',
|
||||||
emailsettingsfailed: 'Email notification settings failed to save.',
|
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',
|
allowselfsigned: 'Allow Self-Signed Certificates',
|
||||||
ssldisabletip:
|
ssldisabletip:
|
||||||
'SSL should be disabled on standard TLS connections (port 587)',
|
'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 NotificationsEmail: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { addToast } = useToasts();
|
const { addToast, removeToast } = useToasts();
|
||||||
|
const [isTesting, setIsTesting] = useState(false);
|
||||||
const { data, error, revalidate } = useSWR(
|
const { data, error, revalidate } = useSWR(
|
||||||
'/api/v1/settings/notifications/email'
|
'/api/v1/settings/notifications/email'
|
||||||
);
|
);
|
||||||
@@ -172,26 +175,53 @@ const NotificationsEmail: React.FC = () => {
|
|||||||
>
|
>
|
||||||
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
|
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
|
||||||
const testSettings = async () => {
|
const testSettings = async () => {
|
||||||
await axios.post('/api/v1/settings/notifications/email/test', {
|
setIsTesting(true);
|
||||||
enabled: true,
|
let toastId: string | undefined;
|
||||||
types: values.types,
|
try {
|
||||||
options: {
|
addToast(
|
||||||
emailFrom: values.emailFrom,
|
intl.formatMessage(messages.toastEmailTestSending),
|
||||||
smtpHost: values.smtpHost,
|
{
|
||||||
smtpPort: Number(values.smtpPort),
|
autoDismiss: false,
|
||||||
secure: values.secure,
|
appearance: 'info',
|
||||||
authUser: values.authUser,
|
},
|
||||||
authPass: values.authPass,
|
(id) => {
|
||||||
senderName: values.senderName,
|
toastId = id;
|
||||||
pgpPrivateKey: values.pgpPrivateKey,
|
}
|
||||||
pgpPassword: values.pgpPassword,
|
);
|
||||||
},
|
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), {
|
if (toastId) {
|
||||||
appearance: 'info',
|
removeToast(toastId);
|
||||||
autoDismiss: true,
|
}
|
||||||
});
|
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 (
|
return (
|
||||||
@@ -425,21 +455,22 @@ const NotificationsEmail: React.FC = () => {
|
|||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="warning"
|
buttonType="warning"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
testSettings();
|
testSettings();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(globalMessages.test)}
|
{isTesting
|
||||||
|
? intl.formatMessage(globalMessages.testing)
|
||||||
|
: intl.formatMessage(globalMessages.test)}
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="primary"
|
buttonType="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
>
|
>
|
||||||
{isSubmitting
|
{isSubmitting
|
||||||
? intl.formatMessage(globalMessages.saving)
|
? intl.formatMessage(globalMessages.saving)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Field, Form, Formik } from 'formik';
|
import { Field, Form, Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
import { useToasts } from 'react-toast-notifications';
|
import { useToasts } from 'react-toast-notifications';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
@@ -18,12 +18,15 @@ const messages = defineMessages({
|
|||||||
profileNameTip: 'Only required if not using the <code>default</code> profile',
|
profileNameTip: 'Only required if not using the <code>default</code> profile',
|
||||||
settingsSaved: 'LunaSea notification settings saved successfully!',
|
settingsSaved: 'LunaSea notification settings saved successfully!',
|
||||||
settingsFailed: 'LunaSea notification settings failed to save.',
|
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 NotificationsLunaSea: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { addToast } = useToasts();
|
const { addToast, removeToast } = useToasts();
|
||||||
|
const [isTesting, setIsTesting] = useState(false);
|
||||||
const { data, error, revalidate } = useSWR(
|
const { data, error, revalidate } = useSWR(
|
||||||
'/api/v1/settings/notifications/lunasea'
|
'/api/v1/settings/notifications/lunasea'
|
||||||
);
|
);
|
||||||
@@ -79,19 +82,46 @@ const NotificationsLunaSea: React.FC = () => {
|
|||||||
>
|
>
|
||||||
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
|
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
|
||||||
const testSettings = async () => {
|
const testSettings = async () => {
|
||||||
await axios.post('/api/v1/settings/notifications/lunasea/test', {
|
setIsTesting(true);
|
||||||
enabled: true,
|
let toastId: string | undefined;
|
||||||
types: values.types,
|
try {
|
||||||
options: {
|
addToast(
|
||||||
webhookUrl: values.webhookUrl,
|
intl.formatMessage(messages.toastLunaSeaTestSending),
|
||||||
profileName: values.profileName,
|
{
|
||||||
},
|
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), {
|
if (toastId) {
|
||||||
appearance: 'info',
|
removeToast(toastId);
|
||||||
autoDismiss: true,
|
}
|
||||||
});
|
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 (
|
return (
|
||||||
@@ -144,21 +174,22 @@ const NotificationsLunaSea: React.FC = () => {
|
|||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="warning"
|
buttonType="warning"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
testSettings();
|
testSettings();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(globalMessages.test)}
|
{isTesting
|
||||||
|
? intl.formatMessage(globalMessages.testing)
|
||||||
|
: intl.formatMessage(globalMessages.test)}
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="primary"
|
buttonType="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
>
|
>
|
||||||
{isSubmitting
|
{isSubmitting
|
||||||
? intl.formatMessage(globalMessages.saving)
|
? intl.formatMessage(globalMessages.saving)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Field, Form, Formik } from 'formik';
|
import { Field, Form, Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
import { useToasts } from 'react-toast-notifications';
|
import { useToasts } from 'react-toast-notifications';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
@@ -18,14 +18,17 @@ const messages = defineMessages({
|
|||||||
pushbulletSettingsSaved:
|
pushbulletSettingsSaved:
|
||||||
'Pushbullet notification settings saved successfully!',
|
'Pushbullet notification settings saved successfully!',
|
||||||
pushbulletSettingsFailed: 'Pushbullet notification settings failed to save.',
|
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:
|
settingUpPushbulletDescription:
|
||||||
'To configure Pushbullet notifications, you will need to <CreateAccessTokenLink>create an access token</CreateAccessTokenLink>.',
|
'To configure Pushbullet notifications, you will need to <CreateAccessTokenLink>create an access token</CreateAccessTokenLink>.',
|
||||||
});
|
});
|
||||||
|
|
||||||
const NotificationsPushbullet: React.FC = () => {
|
const NotificationsPushbullet: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { addToast } = useToasts();
|
const { addToast, removeToast } = useToasts();
|
||||||
|
const [isTesting, setIsTesting] = useState(false);
|
||||||
const { data, error, revalidate } = useSWR(
|
const { data, error, revalidate } = useSWR(
|
||||||
'/api/v1/settings/notifications/pushbullet'
|
'/api/v1/settings/notifications/pushbullet'
|
||||||
);
|
);
|
||||||
@@ -77,18 +80,45 @@ const NotificationsPushbullet: React.FC = () => {
|
|||||||
>
|
>
|
||||||
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
|
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
|
||||||
const testSettings = async () => {
|
const testSettings = async () => {
|
||||||
await axios.post('/api/v1/settings/notifications/pushbullet/test', {
|
setIsTesting(true);
|
||||||
enabled: true,
|
let toastId: string | undefined;
|
||||||
types: values.types,
|
try {
|
||||||
options: {
|
addToast(
|
||||||
accessToken: values.accessToken,
|
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), {
|
if (toastId) {
|
||||||
appearance: 'info',
|
removeToast(toastId);
|
||||||
autoDismiss: true,
|
}
|
||||||
});
|
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 (
|
return (
|
||||||
@@ -150,21 +180,22 @@ const NotificationsPushbullet: React.FC = () => {
|
|||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="warning"
|
buttonType="warning"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
testSettings();
|
testSettings();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(globalMessages.test)}
|
{isTesting
|
||||||
|
? intl.formatMessage(globalMessages.testing)
|
||||||
|
: intl.formatMessage(globalMessages.test)}
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="primary"
|
buttonType="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
>
|
>
|
||||||
{isSubmitting
|
{isSubmitting
|
||||||
? intl.formatMessage(globalMessages.saving)
|
? intl.formatMessage(globalMessages.saving)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Field, Form, Formik } from 'formik';
|
import { Field, Form, Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
import { useToasts } from 'react-toast-notifications';
|
import { useToasts } from 'react-toast-notifications';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
@@ -19,14 +19,17 @@ const messages = defineMessages({
|
|||||||
validationUserTokenRequired: 'You must provide a valid user key',
|
validationUserTokenRequired: 'You must provide a valid user key',
|
||||||
pushoversettingssaved: 'Pushover notification settings saved successfully!',
|
pushoversettingssaved: 'Pushover notification settings saved successfully!',
|
||||||
pushoversettingsfailed: 'Pushover notification settings failed to save.',
|
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:
|
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 NotificationsPushover: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { addToast } = useToasts();
|
const { addToast, removeToast } = useToasts();
|
||||||
|
const [isTesting, setIsTesting] = useState(false);
|
||||||
const { data, error, revalidate } = useSWR(
|
const { data, error, revalidate } = useSWR(
|
||||||
'/api/v1/settings/notifications/pushover'
|
'/api/v1/settings/notifications/pushover'
|
||||||
);
|
);
|
||||||
@@ -97,19 +100,46 @@ const NotificationsPushover: React.FC = () => {
|
|||||||
>
|
>
|
||||||
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
|
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
|
||||||
const testSettings = async () => {
|
const testSettings = async () => {
|
||||||
await axios.post('/api/v1/settings/notifications/pushover/test', {
|
setIsTesting(true);
|
||||||
enabled: true,
|
let toastId: string | undefined;
|
||||||
types: values.types,
|
try {
|
||||||
options: {
|
addToast(
|
||||||
accessToken: values.accessToken,
|
intl.formatMessage(messages.toastPushoverTestSending),
|
||||||
userToken: values.userToken,
|
{
|
||||||
},
|
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), {
|
if (toastId) {
|
||||||
appearance: 'info',
|
removeToast(toastId);
|
||||||
autoDismiss: true,
|
}
|
||||||
});
|
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 (
|
return (
|
||||||
@@ -199,21 +229,22 @@ const NotificationsPushover: React.FC = () => {
|
|||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="warning"
|
buttonType="warning"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
testSettings();
|
testSettings();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(globalMessages.test)}
|
{isTesting
|
||||||
|
? intl.formatMessage(globalMessages.testing)
|
||||||
|
: intl.formatMessage(globalMessages.test)}
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="primary"
|
buttonType="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
>
|
>
|
||||||
{isSubmitting
|
{isSubmitting
|
||||||
? intl.formatMessage(globalMessages.saving)
|
? intl.formatMessage(globalMessages.saving)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Field, Form, Formik } from 'formik';
|
import { Field, Form, Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
import { useToasts } from 'react-toast-notifications';
|
import { useToasts } from 'react-toast-notifications';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
@@ -16,7 +16,9 @@ const messages = defineMessages({
|
|||||||
webhookUrl: 'Webhook URL',
|
webhookUrl: 'Webhook URL',
|
||||||
slacksettingssaved: 'Slack notification settings saved successfully!',
|
slacksettingssaved: 'Slack notification settings saved successfully!',
|
||||||
slacksettingsfailed: 'Slack notification settings failed to save.',
|
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:
|
settingupslackDescription:
|
||||||
'To configure Slack notifications, you will need to create an <WebhookLink>Incoming Webhook</WebhookLink> integration and enter the webhook URL below.',
|
'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',
|
validationWebhookUrl: 'You must provide a valid URL',
|
||||||
@@ -24,7 +26,8 @@ const messages = defineMessages({
|
|||||||
|
|
||||||
const NotificationsSlack: React.FC = () => {
|
const NotificationsSlack: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { addToast } = useToasts();
|
const { addToast, removeToast } = useToasts();
|
||||||
|
const [isTesting, setIsTesting] = useState(false);
|
||||||
const { data, error, revalidate } = useSWR(
|
const { data, error, revalidate } = useSWR(
|
||||||
'/api/v1/settings/notifications/slack'
|
'/api/v1/settings/notifications/slack'
|
||||||
);
|
);
|
||||||
@@ -103,18 +106,45 @@ const NotificationsSlack: React.FC = () => {
|
|||||||
setFieldValue,
|
setFieldValue,
|
||||||
}) => {
|
}) => {
|
||||||
const testSettings = async () => {
|
const testSettings = async () => {
|
||||||
await axios.post('/api/v1/settings/notifications/slack/test', {
|
setIsTesting(true);
|
||||||
enabled: true,
|
let toastId: string | undefined;
|
||||||
types: values.types,
|
try {
|
||||||
options: {
|
addToast(
|
||||||
webhookUrl: values.webhookUrl,
|
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), {
|
if (toastId) {
|
||||||
appearance: 'info',
|
removeToast(toastId);
|
||||||
autoDismiss: true,
|
}
|
||||||
});
|
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 (
|
return (
|
||||||
@@ -150,21 +180,22 @@ const NotificationsSlack: React.FC = () => {
|
|||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="warning"
|
buttonType="warning"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
testSettings();
|
testSettings();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(globalMessages.test)}
|
{isTesting
|
||||||
|
? intl.formatMessage(globalMessages.testing)
|
||||||
|
: intl.formatMessage(globalMessages.test)}
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="primary"
|
buttonType="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
>
|
>
|
||||||
{isSubmitting
|
{isSubmitting
|
||||||
? intl.formatMessage(globalMessages.saving)
|
? intl.formatMessage(globalMessages.saving)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Field, Form, Formik } from 'formik';
|
import { Field, Form, Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
import { useToasts } from 'react-toast-notifications';
|
import { useToasts } from 'react-toast-notifications';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
@@ -22,7 +22,9 @@ const messages = defineMessages({
|
|||||||
validationChatIdRequired: 'You must provide a valid chat ID',
|
validationChatIdRequired: 'You must provide a valid chat ID',
|
||||||
telegramsettingssaved: 'Telegram notification settings saved successfully!',
|
telegramsettingssaved: 'Telegram notification settings saved successfully!',
|
||||||
telegramsettingsfailed: 'Telegram notification settings failed to save.',
|
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:
|
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.',
|
'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',
|
sendSilently: 'Send Silently',
|
||||||
@@ -31,7 +33,8 @@ const messages = defineMessages({
|
|||||||
|
|
||||||
const NotificationsTelegram: React.FC = () => {
|
const NotificationsTelegram: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { addToast } = useToasts();
|
const { addToast, removeToast } = useToasts();
|
||||||
|
const [isTesting, setIsTesting] = useState(false);
|
||||||
const { data, error, revalidate } = useSWR(
|
const { data, error, revalidate } = useSWR(
|
||||||
'/api/v1/settings/notifications/telegram'
|
'/api/v1/settings/notifications/telegram'
|
||||||
);
|
);
|
||||||
@@ -102,21 +105,48 @@ const NotificationsTelegram: React.FC = () => {
|
|||||||
>
|
>
|
||||||
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
|
{({ errors, touched, isSubmitting, values, isValid, setFieldValue }) => {
|
||||||
const testSettings = async () => {
|
const testSettings = async () => {
|
||||||
await axios.post('/api/v1/settings/notifications/telegram/test', {
|
setIsTesting(true);
|
||||||
enabled: true,
|
let toastId: string | undefined;
|
||||||
types: values.types,
|
try {
|
||||||
options: {
|
addToast(
|
||||||
botAPI: values.botAPI,
|
intl.formatMessage(messages.toastTelegramTestSending),
|
||||||
chatId: values.chatId,
|
{
|
||||||
sendSilently: values.sendSilently,
|
autoDismiss: false,
|
||||||
botUsername: values.botUsername,
|
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), {
|
if (toastId) {
|
||||||
appearance: 'info',
|
removeToast(toastId);
|
||||||
autoDismiss: true,
|
}
|
||||||
});
|
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 (
|
return (
|
||||||
@@ -245,21 +275,22 @@ const NotificationsTelegram: React.FC = () => {
|
|||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="warning"
|
buttonType="warning"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
testSettings();
|
testSettings();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(globalMessages.test)}
|
{isTesting
|
||||||
|
? intl.formatMessage(globalMessages.testing)
|
||||||
|
: intl.formatMessage(globalMessages.test)}
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="primary"
|
buttonType="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
>
|
>
|
||||||
{isSubmitting
|
{isSubmitting
|
||||||
? intl.formatMessage(globalMessages.saving)
|
? intl.formatMessage(globalMessages.saving)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Field, Form, Formik } from 'formik';
|
import { Field, Form, Formik } from 'formik';
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
import { useToasts } from 'react-toast-notifications';
|
import { useToasts } from 'react-toast-notifications';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
@@ -13,12 +13,15 @@ const messages = defineMessages({
|
|||||||
agentenabled: 'Enable Agent',
|
agentenabled: 'Enable Agent',
|
||||||
webpushsettingssaved: 'Web push notification settings saved successfully!',
|
webpushsettingssaved: 'Web push notification settings saved successfully!',
|
||||||
webpushsettingsfailed: 'Web push notification settings failed to save.',
|
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 NotificationsWebPush: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { addToast } = useToasts();
|
const { addToast, removeToast } = useToasts();
|
||||||
|
const [isTesting, setIsTesting] = useState(false);
|
||||||
const { data, error, revalidate } = useSWR(
|
const { data, error, revalidate } = useSWR(
|
||||||
'/api/v1/settings/notifications/webpush'
|
'/api/v1/settings/notifications/webpush'
|
||||||
);
|
);
|
||||||
@@ -57,16 +60,43 @@ const NotificationsWebPush: React.FC = () => {
|
|||||||
>
|
>
|
||||||
{({ isSubmitting, values, isValid, setFieldValue }) => {
|
{({ isSubmitting, values, isValid, setFieldValue }) => {
|
||||||
const testSettings = async () => {
|
const testSettings = async () => {
|
||||||
await axios.post('/api/v1/settings/notifications/webpush/test', {
|
setIsTesting(true);
|
||||||
enabled: true,
|
let toastId: string | undefined;
|
||||||
types: values.types,
|
try {
|
||||||
options: {},
|
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), {
|
if (toastId) {
|
||||||
appearance: 'info',
|
removeToast(toastId);
|
||||||
autoDismiss: true,
|
}
|
||||||
});
|
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 (
|
return (
|
||||||
@@ -88,21 +118,22 @@ const NotificationsWebPush: React.FC = () => {
|
|||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="warning"
|
buttonType="warning"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
testSettings();
|
testSettings();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(globalMessages.test)}
|
{isTesting
|
||||||
|
? intl.formatMessage(globalMessages.testing)
|
||||||
|
: intl.formatMessage(globalMessages.test)}
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="primary"
|
buttonType="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
>
|
>
|
||||||
{isSubmitting
|
{isSubmitting
|
||||||
? intl.formatMessage(globalMessages.saving)
|
? intl.formatMessage(globalMessages.saving)
|
||||||
|
@@ -2,7 +2,7 @@ import { QuestionMarkCircleIcon, RefreshIcon } from '@heroicons/react/solid';
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Field, Form, Formik } from 'formik';
|
import { Field, Form, Formik } from 'formik';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
import { useToasts } from 'react-toast-notifications';
|
import { useToasts } from 'react-toast-notifications';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
@@ -46,7 +46,9 @@ const messages = defineMessages({
|
|||||||
validationJsonPayloadRequired: 'You must provide a valid JSON payload',
|
validationJsonPayloadRequired: 'You must provide a valid JSON payload',
|
||||||
webhooksettingssaved: 'Webhook notification settings saved successfully!',
|
webhooksettingssaved: 'Webhook notification settings saved successfully!',
|
||||||
webhooksettingsfailed: 'Webhook notification settings failed to save.',
|
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',
|
resetPayload: 'Reset to Default',
|
||||||
resetPayloadSuccess: 'JSON payload reset successfully!',
|
resetPayloadSuccess: 'JSON payload reset successfully!',
|
||||||
customJson: 'JSON Payload',
|
customJson: 'JSON Payload',
|
||||||
@@ -56,7 +58,8 @@ const messages = defineMessages({
|
|||||||
|
|
||||||
const NotificationsWebhook: React.FC = () => {
|
const NotificationsWebhook: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { addToast } = useToasts();
|
const { addToast, removeToast } = useToasts();
|
||||||
|
const [isTesting, setIsTesting] = useState(false);
|
||||||
const { data, error, revalidate } = useSWR(
|
const { data, error, revalidate } = useSWR(
|
||||||
'/api/v1/settings/notifications/webhook'
|
'/api/v1/settings/notifications/webhook'
|
||||||
);
|
);
|
||||||
@@ -157,20 +160,47 @@ const NotificationsWebhook: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const testSettings = async () => {
|
const testSettings = async () => {
|
||||||
await axios.post('/api/v1/settings/notifications/webhook/test', {
|
setIsTesting(true);
|
||||||
enabled: true,
|
let toastId: string | undefined;
|
||||||
types: values.types,
|
try {
|
||||||
options: {
|
addToast(
|
||||||
webhookUrl: values.webhookUrl,
|
intl.formatMessage(messages.toastWebhookTestSending),
|
||||||
jsonPayload: JSON.stringify(values.jsonPayload),
|
{
|
||||||
authHeader: values.authHeader,
|
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), {
|
if (toastId) {
|
||||||
appearance: 'info',
|
removeToast(toastId);
|
||||||
autoDismiss: true,
|
}
|
||||||
});
|
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 (
|
return (
|
||||||
@@ -257,21 +287,22 @@ const NotificationsWebhook: React.FC = () => {
|
|||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="warning"
|
buttonType="warning"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
testSettings();
|
testSettings();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(globalMessages.test)}
|
{isTesting
|
||||||
|
? intl.formatMessage(globalMessages.testing)
|
||||||
|
: intl.formatMessage(globalMessages.test)}
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
<Button
|
<Button
|
||||||
buttonType="primary"
|
buttonType="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isSubmitting || !isValid}
|
disabled={isSubmitting || !isValid || isTesting}
|
||||||
>
|
>
|
||||||
{isSubmitting
|
{isSubmitting
|
||||||
? intl.formatMessage(globalMessages.saving)
|
? intl.formatMessage(globalMessages.saving)
|
||||||
|
@@ -19,8 +19,6 @@ const messages = defineMessages({
|
|||||||
notificationsettings: 'Notification Settings',
|
notificationsettings: 'Notification Settings',
|
||||||
email: 'Email',
|
email: 'Email',
|
||||||
webpush: 'Web Push',
|
webpush: 'Web Push',
|
||||||
toastSettingsSuccess: 'Notification settings saved successfully!',
|
|
||||||
toastSettingsFailure: 'Something went wrong while saving settings.',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const UserNotificationSettings: React.FC = ({ children }) => {
|
const UserNotificationSettings: React.FC = ({ children }) => {
|
||||||
|
@@ -250,7 +250,9 @@
|
|||||||
"components.Settings.Notifications.NotificationsLunaSea.profileNameTip": "Only required if not using the <code>default</code> profile",
|
"components.Settings.Notifications.NotificationsLunaSea.profileNameTip": "Only required if not using the <code>default</code> profile",
|
||||||
"components.Settings.Notifications.NotificationsLunaSea.settingsFailed": "LunaSea notification settings failed to save.",
|
"components.Settings.Notifications.NotificationsLunaSea.settingsFailed": "LunaSea notification settings failed to save.",
|
||||||
"components.Settings.Notifications.NotificationsLunaSea.settingsSaved": "LunaSea notification settings saved successfully!",
|
"components.Settings.Notifications.NotificationsLunaSea.settingsSaved": "LunaSea notification settings saved successfully!",
|
||||||
"components.Settings.Notifications.NotificationsLunaSea.testSent": "LunaSea test notification sent!",
|
"components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestFailed": "LunaSea test notification failed to send.",
|
||||||
|
"components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestSending": "Sending LunaSea test notification…",
|
||||||
|
"components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestSuccess": "LunaSea test notification sent!",
|
||||||
"components.Settings.Notifications.NotificationsLunaSea.validationWebhookUrl": "You must provide a valid URL",
|
"components.Settings.Notifications.NotificationsLunaSea.validationWebhookUrl": "You must provide a valid URL",
|
||||||
"components.Settings.Notifications.NotificationsLunaSea.webhookUrl": "Webhook URL",
|
"components.Settings.Notifications.NotificationsLunaSea.webhookUrl": "Webhook URL",
|
||||||
"components.Settings.Notifications.NotificationsPushbullet.accessToken": "Access Token",
|
"components.Settings.Notifications.NotificationsPushbullet.accessToken": "Access Token",
|
||||||
@@ -258,14 +260,18 @@
|
|||||||
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsFailed": "Pushbullet notification settings failed to save.",
|
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsFailed": "Pushbullet notification settings failed to save.",
|
||||||
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsSaved": "Pushbullet notification settings saved successfully!",
|
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsSaved": "Pushbullet notification settings saved successfully!",
|
||||||
"components.Settings.Notifications.NotificationsPushbullet.settingUpPushbulletDescription": "To configure Pushbullet notifications, you will need to <CreateAccessTokenLink>create an access token</CreateAccessTokenLink>.",
|
"components.Settings.Notifications.NotificationsPushbullet.settingUpPushbulletDescription": "To configure Pushbullet notifications, you will need to <CreateAccessTokenLink>create an access token</CreateAccessTokenLink>.",
|
||||||
"components.Settings.Notifications.NotificationsPushbullet.testSent": "Pushbullet test notification sent!",
|
"components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestFailed": "Pushbullet test notification failed to send.",
|
||||||
|
"components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestSending": "Sending Pushbullet test notification…",
|
||||||
|
"components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestSuccess": "Pushbullet test notification sent!",
|
||||||
"components.Settings.Notifications.NotificationsPushbullet.validationAccessTokenRequired": "You must provide an access token",
|
"components.Settings.Notifications.NotificationsPushbullet.validationAccessTokenRequired": "You must provide an access token",
|
||||||
"components.Settings.Notifications.NotificationsPushover.accessToken": "Application/API Token",
|
"components.Settings.Notifications.NotificationsPushover.accessToken": "Application/API Token",
|
||||||
"components.Settings.Notifications.NotificationsPushover.agentenabled": "Enable Agent",
|
"components.Settings.Notifications.NotificationsPushover.agentenabled": "Enable Agent",
|
||||||
"components.Settings.Notifications.NotificationsPushover.pushoversettingsfailed": "Pushover notification settings failed to save.",
|
"components.Settings.Notifications.NotificationsPushover.pushoversettingsfailed": "Pushover notification settings failed to save.",
|
||||||
"components.Settings.Notifications.NotificationsPushover.pushoversettingssaved": "Pushover notification settings saved successfully!",
|
"components.Settings.Notifications.NotificationsPushover.pushoversettingssaved": "Pushover notification settings saved successfully!",
|
||||||
"components.Settings.Notifications.NotificationsPushover.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>.)",
|
"components.Settings.Notifications.NotificationsPushover.settinguppushoverDescription": "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>.)",
|
||||||
"components.Settings.Notifications.NotificationsPushover.testsent": "Pushover test notification sent!",
|
"components.Settings.Notifications.NotificationsPushover.toastPushoverTestFailed": "Pushover test notification failed to send.",
|
||||||
|
"components.Settings.Notifications.NotificationsPushover.toastPushoverTestSending": "Sending Pushover test notification…",
|
||||||
|
"components.Settings.Notifications.NotificationsPushover.toastPushoverTestSuccess": "Pushover test notification sent!",
|
||||||
"components.Settings.Notifications.NotificationsPushover.userToken": "User or Group Key",
|
"components.Settings.Notifications.NotificationsPushover.userToken": "User or Group Key",
|
||||||
"components.Settings.Notifications.NotificationsPushover.validationAccessTokenRequired": "You must provide a valid application token",
|
"components.Settings.Notifications.NotificationsPushover.validationAccessTokenRequired": "You must provide a valid application token",
|
||||||
"components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "You must provide a valid user key",
|
"components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "You must provide a valid user key",
|
||||||
@@ -273,11 +279,15 @@
|
|||||||
"components.Settings.Notifications.NotificationsSlack.settingupslackDescription": "To configure Slack notifications, you will need to create an <WebhookLink>Incoming Webhook</WebhookLink> integration and enter the webhook URL below.",
|
"components.Settings.Notifications.NotificationsSlack.settingupslackDescription": "To configure Slack notifications, you will need to create an <WebhookLink>Incoming Webhook</WebhookLink> integration and enter the webhook URL below.",
|
||||||
"components.Settings.Notifications.NotificationsSlack.slacksettingsfailed": "Slack notification settings failed to save.",
|
"components.Settings.Notifications.NotificationsSlack.slacksettingsfailed": "Slack notification settings failed to save.",
|
||||||
"components.Settings.Notifications.NotificationsSlack.slacksettingssaved": "Slack notification settings saved successfully!",
|
"components.Settings.Notifications.NotificationsSlack.slacksettingssaved": "Slack notification settings saved successfully!",
|
||||||
"components.Settings.Notifications.NotificationsSlack.testsent": "Slack test notification sent!",
|
"components.Settings.Notifications.NotificationsSlack.toastSlackTestFailed": "Slack test notification failed to send.",
|
||||||
|
"components.Settings.Notifications.NotificationsSlack.toastSlackTestSending": "Sending Slack test notification…",
|
||||||
|
"components.Settings.Notifications.NotificationsSlack.toastSlackTestSuccess": "Slack test notification sent!",
|
||||||
"components.Settings.Notifications.NotificationsSlack.validationWebhookUrl": "You must provide a valid URL",
|
"components.Settings.Notifications.NotificationsSlack.validationWebhookUrl": "You must provide a valid URL",
|
||||||
"components.Settings.Notifications.NotificationsSlack.webhookUrl": "Webhook URL",
|
"components.Settings.Notifications.NotificationsSlack.webhookUrl": "Webhook URL",
|
||||||
"components.Settings.Notifications.NotificationsWebPush.agentenabled": "Enable Agent",
|
"components.Settings.Notifications.NotificationsWebPush.agentenabled": "Enable Agent",
|
||||||
"components.Settings.Notifications.NotificationsWebPush.testsent": "Web push test notification sent!",
|
"components.Settings.Notifications.NotificationsWebPush.toastWebPushTestFailed": "Web push test notification failed to send.",
|
||||||
|
"components.Settings.Notifications.NotificationsWebPush.toastWebPushTestSending": "Sending web push test notification…",
|
||||||
|
"components.Settings.Notifications.NotificationsWebPush.toastWebPushTestSuccess": "Web push test notification sent!",
|
||||||
"components.Settings.Notifications.NotificationsWebPush.webpushsettingsfailed": "Web push notification settings failed to save.",
|
"components.Settings.Notifications.NotificationsWebPush.webpushsettingsfailed": "Web push notification settings failed to save.",
|
||||||
"components.Settings.Notifications.NotificationsWebPush.webpushsettingssaved": "Web push notification settings saved successfully!",
|
"components.Settings.Notifications.NotificationsWebPush.webpushsettingssaved": "Web push notification settings saved successfully!",
|
||||||
"components.Settings.Notifications.NotificationsWebhook.agentenabled": "Enable Agent",
|
"components.Settings.Notifications.NotificationsWebhook.agentenabled": "Enable Agent",
|
||||||
@@ -286,7 +296,9 @@
|
|||||||
"components.Settings.Notifications.NotificationsWebhook.resetPayload": "Reset to Default",
|
"components.Settings.Notifications.NotificationsWebhook.resetPayload": "Reset to Default",
|
||||||
"components.Settings.Notifications.NotificationsWebhook.resetPayloadSuccess": "JSON payload reset successfully!",
|
"components.Settings.Notifications.NotificationsWebhook.resetPayloadSuccess": "JSON payload reset successfully!",
|
||||||
"components.Settings.Notifications.NotificationsWebhook.templatevariablehelp": "Template Variable Help",
|
"components.Settings.Notifications.NotificationsWebhook.templatevariablehelp": "Template Variable Help",
|
||||||
"components.Settings.Notifications.NotificationsWebhook.testsent": "Webhook test notification sent!",
|
"components.Settings.Notifications.NotificationsWebhook.toastWebhookTestFailed": "Webhook test notification failed to send.",
|
||||||
|
"components.Settings.Notifications.NotificationsWebhook.toastWebhookTestSending": "Sending webhook test notification…",
|
||||||
|
"components.Settings.Notifications.NotificationsWebhook.toastWebhookTestSuccess": "Webhook test notification sent!",
|
||||||
"components.Settings.Notifications.NotificationsWebhook.validationJsonPayloadRequired": "You must provide a valid JSON payload",
|
"components.Settings.Notifications.NotificationsWebhook.validationJsonPayloadRequired": "You must provide a valid JSON payload",
|
||||||
"components.Settings.Notifications.NotificationsWebhook.validationWebhookUrl": "You must provide a valid URL",
|
"components.Settings.Notifications.NotificationsWebhook.validationWebhookUrl": "You must provide a valid URL",
|
||||||
"components.Settings.Notifications.NotificationsWebhook.webhookUrl": "Webhook URL",
|
"components.Settings.Notifications.NotificationsWebhook.webhookUrl": "Webhook URL",
|
||||||
@@ -303,13 +315,11 @@
|
|||||||
"components.Settings.Notifications.chatId": "Chat ID",
|
"components.Settings.Notifications.chatId": "Chat ID",
|
||||||
"components.Settings.Notifications.discordsettingsfailed": "Discord notification settings failed to save.",
|
"components.Settings.Notifications.discordsettingsfailed": "Discord notification settings failed to save.",
|
||||||
"components.Settings.Notifications.discordsettingssaved": "Discord notification settings saved successfully!",
|
"components.Settings.Notifications.discordsettingssaved": "Discord notification settings saved successfully!",
|
||||||
"components.Settings.Notifications.discordtestsent": "Discord test notification sent!",
|
|
||||||
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "<strong>Media Requested</strong>, <strong>Media Automatically Approved</strong>, and <strong>Media Failed</strong> email notifications are sent to all users with the <strong>Manage Requests</strong> permission.",
|
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "<strong>Media Requested</strong>, <strong>Media Automatically Approved</strong>, and <strong>Media Failed</strong> email notifications are sent to all users with the <strong>Manage Requests</strong> permission.",
|
||||||
"components.Settings.Notifications.emailNotificationTypesAlertDescriptionPt2": "<strong>Media Approved</strong>, <strong>Media Declined</strong>, and <strong>Media Available</strong> email notifications are sent to the user who submitted the request.",
|
"components.Settings.Notifications.emailNotificationTypesAlertDescriptionPt2": "<strong>Media Approved</strong>, <strong>Media Declined</strong>, and <strong>Media Available</strong> email notifications are sent to the user who submitted the request.",
|
||||||
"components.Settings.Notifications.emailsender": "Sender Address",
|
"components.Settings.Notifications.emailsender": "Sender Address",
|
||||||
"components.Settings.Notifications.emailsettingsfailed": "Email notification settings failed to save.",
|
"components.Settings.Notifications.emailsettingsfailed": "Email notification settings failed to save.",
|
||||||
"components.Settings.Notifications.emailsettingssaved": "Email notification settings saved successfully!",
|
"components.Settings.Notifications.emailsettingssaved": "Email notification settings saved successfully!",
|
||||||
"components.Settings.Notifications.emailtestsent": "Email test notification sent!",
|
|
||||||
"components.Settings.Notifications.enableSsl": "Enable SSL",
|
"components.Settings.Notifications.enableSsl": "Enable SSL",
|
||||||
"components.Settings.Notifications.pgpPassword": "PGP Password",
|
"components.Settings.Notifications.pgpPassword": "PGP Password",
|
||||||
"components.Settings.Notifications.pgpPasswordTip": "Sign encrypted email messages using <OpenPgpLink>OpenPGP</OpenPgpLink>",
|
"components.Settings.Notifications.pgpPasswordTip": "Sign encrypted email messages using <OpenPgpLink>OpenPGP</OpenPgpLink>",
|
||||||
@@ -324,7 +334,15 @@
|
|||||||
"components.Settings.Notifications.ssldisabletip": "SSL should be disabled on standard TLS connections (port 587)",
|
"components.Settings.Notifications.ssldisabletip": "SSL should be disabled on standard TLS connections (port 587)",
|
||||||
"components.Settings.Notifications.telegramsettingsfailed": "Telegram notification settings failed to save.",
|
"components.Settings.Notifications.telegramsettingsfailed": "Telegram notification settings failed to save.",
|
||||||
"components.Settings.Notifications.telegramsettingssaved": "Telegram notification settings saved successfully!",
|
"components.Settings.Notifications.telegramsettingssaved": "Telegram notification settings saved successfully!",
|
||||||
"components.Settings.Notifications.telegramtestsent": "Telegram test notification sent!",
|
"components.Settings.Notifications.toastDiscordTestFailed": "Discord test notification failed to send.",
|
||||||
|
"components.Settings.Notifications.toastDiscordTestSending": "Sending Discord test notification…",
|
||||||
|
"components.Settings.Notifications.toastDiscordTestSuccess": "Discord test notification sent!",
|
||||||
|
"components.Settings.Notifications.toastEmailTestFailed": "Email test notification failed to send.",
|
||||||
|
"components.Settings.Notifications.toastEmailTestSending": "Sending email test notification…",
|
||||||
|
"components.Settings.Notifications.toastEmailTestSuccess": "Email test notification sent!",
|
||||||
|
"components.Settings.Notifications.toastTelegramTestFailed": "Telegram test notification failed to send.",
|
||||||
|
"components.Settings.Notifications.toastTelegramTestSending": "Sending Telegram test notification…",
|
||||||
|
"components.Settings.Notifications.toastTelegramTestSuccess": "Telegram test notification sent!",
|
||||||
"components.Settings.Notifications.validationBotAPIRequired": "You must provide a bot authentication token",
|
"components.Settings.Notifications.validationBotAPIRequired": "You must provide a bot authentication token",
|
||||||
"components.Settings.Notifications.validationChatIdRequired": "You must provide a valid chat ID",
|
"components.Settings.Notifications.validationChatIdRequired": "You must provide a valid chat ID",
|
||||||
"components.Settings.Notifications.validationEmail": "You must provide a valid email address",
|
"components.Settings.Notifications.validationEmail": "You must provide a valid email address",
|
||||||
@@ -748,8 +766,6 @@
|
|||||||
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTipLong": "<TelegramBotLink>Start a chat</TelegramBotLink>, add <GetIdBotLink>@get_id_bot</GetIdBotLink>, and issue the <code>/my_id</code> command",
|
"components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTipLong": "<TelegramBotLink>Start a chat</TelegramBotLink>, add <GetIdBotLink>@get_id_bot</GetIdBotLink>, and issue the <code>/my_id</code> command",
|
||||||
"components.UserProfile.UserSettings.UserNotificationSettings.telegramsettingsfailed": "Telegram notification settings failed to save.",
|
"components.UserProfile.UserSettings.UserNotificationSettings.telegramsettingsfailed": "Telegram notification settings failed to save.",
|
||||||
"components.UserProfile.UserSettings.UserNotificationSettings.telegramsettingssaved": "Telegram notification settings saved successfully!",
|
"components.UserProfile.UserSettings.UserNotificationSettings.telegramsettingssaved": "Telegram notification settings saved successfully!",
|
||||||
"components.UserProfile.UserSettings.UserNotificationSettings.toastSettingsFailure": "Something went wrong while saving settings.",
|
|
||||||
"components.UserProfile.UserSettings.UserNotificationSettings.toastSettingsSuccess": "Notification settings saved successfully!",
|
|
||||||
"components.UserProfile.UserSettings.UserNotificationSettings.validationDiscordId": "You must provide a valid user ID",
|
"components.UserProfile.UserSettings.UserNotificationSettings.validationDiscordId": "You must provide a valid user ID",
|
||||||
"components.UserProfile.UserSettings.UserNotificationSettings.validationPgpPublicKey": "You must provide a valid PGP public key",
|
"components.UserProfile.UserSettings.UserNotificationSettings.validationPgpPublicKey": "You must provide a valid PGP public key",
|
||||||
"components.UserProfile.UserSettings.UserNotificationSettings.validationTelegramChatId": "You must provide a valid chat ID",
|
"components.UserProfile.UserSettings.UserNotificationSettings.validationTelegramChatId": "You must provide a valid chat ID",
|
||||||
|
Reference in New Issue
Block a user