notifications
This commit is contained in:
1 parent
63dd455e4a
commit
22f7d002fd
7 files changed
+128
-107
No files matched your search
@@ -96,12 +96,13 @@ export const EmptyFallback = ({
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
{bullets?.map((bullet: string) => (
|
||||
<BulletPointCheck
|
||||
text={bullet}
|
||||
key={`${bullet}-${Math.random()}`}
|
||||
/>
|
||||
))}
|
||||
{Array.isArray(bullets) &&
|
||||
bullets?.map((bullet: string) => (
|
||||
<BulletPointCheck
|
||||
text={bullet}
|
||||
key={`${bullet}-${Math.random()}`}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
<Stack>
|
||||
<Button
|
||||
|
||||
@@ -6,9 +6,12 @@
|
||||
"delete": "Delete",
|
||||
"confirm": "Confirm",
|
||||
"cancel": "Cancel",
|
||||
"test": "Test",
|
||||
"save": "Save",
|
||||
"pause": "Pause",
|
||||
"resume": "Resume",
|
||||
"enable": "Enable",
|
||||
"disable": "Disable",
|
||||
"configure": "Configure",
|
||||
"createNew": "Create new",
|
||||
"toggleTheme": "Toggle theme",
|
||||
@@ -19,7 +22,9 @@
|
||||
"day": "Day",
|
||||
"week": "7 days",
|
||||
"month": "30 days"
|
||||
}
|
||||
},
|
||||
"yes": "Yes",
|
||||
"no": "No"
|
||||
},
|
||||
"dialog": {
|
||||
"delete": {
|
||||
@@ -104,6 +109,7 @@
|
||||
"table": {
|
||||
"headers": {
|
||||
"name": "Name",
|
||||
"active": "Active",
|
||||
"type": "Type",
|
||||
"status": "Status",
|
||||
"statusCode": "Status code",
|
||||
@@ -271,7 +277,58 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifications": {},
|
||||
"notificationChannels": {
|
||||
"infoBox": {
|
||||
"title": "Notification Channels",
|
||||
"description": "Configure where you want to receive notifications when monitors detect issues. Connect email, Slack, Discord, webhooks, and other channels to stay informed."
|
||||
},
|
||||
"fallback": {
|
||||
"actionButton": "Create a channel",
|
||||
"checks": [
|
||||
"Alert teams about downtime or performance issues",
|
||||
"Let engineers know when incidents happen",
|
||||
"Keep administrators informed of system changes"
|
||||
],
|
||||
"title": "Notification channles are used toto:"
|
||||
},
|
||||
"form": {
|
||||
"name": {
|
||||
"title": "Channel name",
|
||||
"description": "A descriptive name for the notification channel",
|
||||
"optionName": "Channel name",
|
||||
"placeholder": "e.g. Production Alerts"
|
||||
},
|
||||
"type": {
|
||||
"title": "Channel type",
|
||||
"description": "Select the type of notification channel to create.",
|
||||
"optionType": "Type"
|
||||
},
|
||||
"email": {
|
||||
"title": "Email configuration",
|
||||
"description": "Configure the email address where notifications will be sent",
|
||||
"option": "Destination email address",
|
||||
"placeholder": "e.g. john@example.com"
|
||||
},
|
||||
"slack": {
|
||||
"title": "Slack configuration",
|
||||
"description": "Configure your Slack webhook URL. Create one in Slack: Settings & administration → Manage apps → Custom Integrations → Incoming Webhooks",
|
||||
"option": "Webhook URL",
|
||||
"placeholder": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
|
||||
},
|
||||
"discord": {
|
||||
"title": "Discord configuration",
|
||||
"description": "Configure your Discord webhook URL. Create one in Discord: Settings & administration → Manage apps → Custom Integrations → Incoming Webhooks",
|
||||
"option": "Webhook URL",
|
||||
"placeholder": "https://discord.com/api/webhooks/YOUR/WEBHOOK/URL"
|
||||
},
|
||||
"webhook": {
|
||||
"title": "Webhook configuration",
|
||||
"description": "Configure the webhook URL endpoint where notifications will be sent",
|
||||
"option": "Webhook URL",
|
||||
"placeholder": "https://your-server.com/webhook"
|
||||
}
|
||||
}
|
||||
},
|
||||
"incidents": {},
|
||||
"checks": {},
|
||||
"statusPages": {}
|
||||
|
||||
@@ -50,7 +50,7 @@ const NotificationChannelsPage = () => {
|
||||
return [
|
||||
{
|
||||
id: 1,
|
||||
label: "Configure",
|
||||
label: t("monitors.common.actions.configure"),
|
||||
action: () => {
|
||||
navigate(`/notification-channels/${channel._id}/configure`);
|
||||
},
|
||||
@@ -58,7 +58,9 @@ const NotificationChannelsPage = () => {
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: channel.isActive ? "Disable" : "Enable",
|
||||
label: channel.isActive
|
||||
? t("common.buttons.disable")
|
||||
: t("common.buttons.enable"),
|
||||
action: async () => {
|
||||
const res = await patch(
|
||||
`/notification-channels/${channel._id}/active`,
|
||||
@@ -72,7 +74,11 @@ const NotificationChannelsPage = () => {
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
label: <Typography color={theme.palette.error.main}>Remove</Typography>,
|
||||
label: (
|
||||
<Typography color={theme.palette.error.main}>
|
||||
{t("common.buttons.delete")}
|
||||
</Typography>
|
||||
),
|
||||
action: async () => {
|
||||
setSelectedChannel(channel);
|
||||
},
|
||||
@@ -85,16 +91,18 @@ const NotificationChannelsPage = () => {
|
||||
const headers: Header<INotificationChannel>[] = [
|
||||
{
|
||||
id: "name",
|
||||
content: "Name",
|
||||
content: t("monitors.common.table.headers.name"),
|
||||
render: (row) => {
|
||||
return <Typography>{row?.name}</Typography>;
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "active",
|
||||
content: "Active",
|
||||
content: t("monitors.common.table.headers.active"),
|
||||
render: (row) => {
|
||||
const active = row.isActive ? "Yes" : "No";
|
||||
const active = row.isActive
|
||||
? t("common.buttons.yes")
|
||||
: t("common.buttons.no");
|
||||
return <Typography>{active}</Typography>;
|
||||
},
|
||||
},
|
||||
@@ -109,7 +117,7 @@ const NotificationChannelsPage = () => {
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
content: t("actions"),
|
||||
content: t("monitors.common.table.headers.actions"),
|
||||
render: (row) => {
|
||||
return <ActionsMenu items={getActions(row)} />;
|
||||
},
|
||||
@@ -122,19 +130,21 @@ const NotificationChannelsPage = () => {
|
||||
|
||||
return (
|
||||
<BasePageWithStates
|
||||
page="Notification Channels"
|
||||
page={t("notificationChannels.fallback.title")}
|
||||
bullets={
|
||||
t("notifications.fallback.checks", { returnObjects: true }) as string[]
|
||||
t("notificationChannels.fallback.checks", {
|
||||
returnObjects: true,
|
||||
}) as string[]
|
||||
}
|
||||
loading={isValidating}
|
||||
error={error}
|
||||
items={notificationChannels}
|
||||
actionButtonText="Create a channel"
|
||||
actionButtonText={t("notificationChannels.fallback.actionButton")}
|
||||
actionLink="/notification-channels/create"
|
||||
>
|
||||
<InfoBox
|
||||
title="Alert Destinations"
|
||||
description="Configure where you want to receive alerts when monitors detect issues. Connect email, Slack, Discord, webhooks, and other channels to stay informed."
|
||||
title={t("notificationChannels.infoBox.title")}
|
||||
description={t("notificationChannels.infoBox.description")}
|
||||
/>
|
||||
<HeaderCreate
|
||||
label={"Create a new notification channel"}
|
||||
@@ -152,8 +162,8 @@ const NotificationChannelsPage = () => {
|
||||
/>
|
||||
|
||||
<Dialog
|
||||
title={t("createNotifications.dialogDeleteTitle")}
|
||||
content={t("createNotifications.dialogDeleteContent")}
|
||||
title={t("common.dialog.delete.title")}
|
||||
content={t("common.dialog.delete.description")}
|
||||
open={open}
|
||||
onConfirm={handleConfirm}
|
||||
onCancel={handleCancel}
|
||||
|
||||
@@ -73,8 +73,8 @@ export const NotificationChannelsForm = ({
|
||||
return (
|
||||
<BasePage component={"form"} onSubmit={handleSubmit(onSubmit, onError)}>
|
||||
<ConfigBox
|
||||
title={t("createNotifications.nameSettings.title")}
|
||||
subtitle={t("createNotifications.nameSettings.description")}
|
||||
title={t("notificationChannels.form.name.title")}
|
||||
subtitle={t("notificationChannels.form.name.description")}
|
||||
rightContent={
|
||||
<Controller
|
||||
name="name"
|
||||
@@ -83,8 +83,8 @@ export const NotificationChannelsForm = ({
|
||||
<TextInput
|
||||
{...field}
|
||||
type="text"
|
||||
fieldLabel={t("createNotifications.nameSettings.nameLabel")}
|
||||
placeholder="e.g. Production Alerts"
|
||||
fieldLabel={t("notificationChannels.form.name.optionName")}
|
||||
placeholder={t("notificationChannels.form.name.placeholder")}
|
||||
fullWidth
|
||||
error={!!errors.name}
|
||||
helperText={errors.name ? errors.name.message : ""}
|
||||
@@ -94,8 +94,8 @@ export const NotificationChannelsForm = ({
|
||||
}
|
||||
/>
|
||||
<ConfigBox
|
||||
title={t("createNotifications.typeSettings.title")}
|
||||
subtitle={t("createNotifications.typeSettings.description")}
|
||||
title={t("notificationChannels.form.type.title")}
|
||||
subtitle={t("notificationChannels.form.type.description")}
|
||||
rightContent={
|
||||
<Controller
|
||||
name="type"
|
||||
@@ -105,7 +105,7 @@ export const NotificationChannelsForm = ({
|
||||
return (
|
||||
<Select
|
||||
value={field.value}
|
||||
fieldLabel={t("createNotifications.typeSettings.title")}
|
||||
fieldLabel={t("notificationChannels.form.type.optionType")}
|
||||
error={!!errors.type}
|
||||
onChange={field.onChange}
|
||||
>
|
||||
@@ -125,18 +125,8 @@ export const NotificationChannelsForm = ({
|
||||
}
|
||||
/>
|
||||
<ConfigBox
|
||||
title={type ? `${type} configuration` : "Config"}
|
||||
subtitle={
|
||||
type === "email"
|
||||
? "Configure the email address where notifications will be sent"
|
||||
: type === "webhook"
|
||||
? "Configure the webhook URL endpoint where notifications will be sent"
|
||||
: type === "slack"
|
||||
? "Configure your Slack webhook URL. Create one in Slack: Settings & administration → Manage apps → Custom Integrations → Incoming Webhooks"
|
||||
: type === "discord"
|
||||
? "Configure your Discord webhook URL. Create one in Discord: Server Settings → Integrations → Webhooks → New Webhook"
|
||||
: "Configure notification channel settings"
|
||||
}
|
||||
title={t(`notificationChannels.form.${type}.title`)}
|
||||
subtitle={t(`notificationChannels.form.${type}.description`)}
|
||||
rightContent={
|
||||
type === "email" ? (
|
||||
<Controller
|
||||
@@ -148,10 +138,10 @@ export const NotificationChannelsForm = ({
|
||||
<TextInput
|
||||
{...field}
|
||||
type="text"
|
||||
fieldLabel={t(
|
||||
"createNotifications.emailSettings.description"
|
||||
fieldLabel={t(`notificationChannels.form.${type}.option`)}
|
||||
placeholder={t(
|
||||
`notificationChannels.form.${type}.placeholder`
|
||||
)}
|
||||
placeholder="e.g. john@example.com"
|
||||
fullWidth
|
||||
error={!!errors.config?.emailAddress}
|
||||
helperText={
|
||||
@@ -169,31 +159,14 @@ export const NotificationChannelsForm = ({
|
||||
control={control}
|
||||
defaultValue={defaults.config.url}
|
||||
render={({ field }) => {
|
||||
const getPlaceholder = () => {
|
||||
switch (type) {
|
||||
case "slack":
|
||||
return "https://hooks.slack.com/services/YOUR/WEBHOOK/URL";
|
||||
case "discord":
|
||||
return "https://discord.com/api/webhooks/YOUR/WEBHOOK/URL";
|
||||
case "webhook":
|
||||
return "https://your-server.com/webhook";
|
||||
default:
|
||||
return "https://example.com/webhook";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<TextInput
|
||||
{...field}
|
||||
type="text"
|
||||
fieldLabel={
|
||||
type
|
||||
? `${
|
||||
type.charAt(0).toUpperCase() + type.slice(1)
|
||||
} webhook URL`
|
||||
: "URL"
|
||||
}
|
||||
placeholder={getPlaceholder()}
|
||||
fieldLabel={t(`notificationChannels.form.${type}.option`)}
|
||||
placeholder={t(
|
||||
`notificationChannels.form.${type}.placeholder`
|
||||
)}
|
||||
fullWidth
|
||||
error={!!errors.config?.url}
|
||||
helperText={
|
||||
@@ -217,7 +190,7 @@ export const NotificationChannelsForm = ({
|
||||
onClick={handleTest}
|
||||
loading={isPosting || loading}
|
||||
>
|
||||
Test
|
||||
{t("common.buttons.test")}
|
||||
</Button>
|
||||
<Button
|
||||
loading={isPosting || loading}
|
||||
@@ -225,7 +198,7 @@ export const NotificationChannelsForm = ({
|
||||
variant="contained"
|
||||
color="primary"
|
||||
>
|
||||
{t("settingsSave")}
|
||||
{t("common.buttons.save")}
|
||||
</Button>
|
||||
</Stack>
|
||||
</BasePage>
|
||||
|
||||
Reference in new issue
Block a user