/* * Copyright (c) 2021 - 2025, Ludvig Lundgren and the autobrr contributors. * SPDX-License-Identifier: GPL-2.0-or-later */ import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild } from "@headlessui/react"; import { Fragment } from "react"; import type { FieldProps } from "formik"; import { Field, Form, Formik, FormikErrors, FormikValues } from "formik"; import { XMarkIcon } from "@heroicons/react/24/solid"; import Select from "react-select"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { APIClient } from "@api/APIClient"; import { NotificationKeys } from "@api/query_keys"; import { EventOptions, NotificationTypeOptions, SelectOption } from "@domain/constants"; import { DEBUG } from "@components/debug"; import { SlideOver } from "@components/panels"; import { ExternalLink } from "@components/ExternalLink"; import { toast } from "@components/hot-toast"; import Toast from "@components/notifications/Toast"; import * as common from "@components/inputs/common"; import { NumberFieldWide, PasswordFieldWide, SwitchGroupWide, TextFieldWide } from "@components/inputs"; import { componentMapType } from "./DownloadClientForms"; import { AddFormProps, UpdateFormProps } from "@forms/_shared"; function FormFieldsDiscord() { return (
Settings

{"Create a "} webhook integration {" in your server."}

); } function FormFieldsNotifiarr() { return (
Settings

Enable the autobrr integration and optionally create a new API Key.

); } function FormFieldsLunaSea() { return (
Settings

LunaSea offers notifications across all devices linked to your account (User-Based) or to a single device without an account, using a unique webhook per device (Device-Based).

{"Read the "} LunaSea docs {"."}

); } function FormFieldsTelegram() { return (
Settings

{"Read how to "} create a bot {"."}

); } function FormFieldsPushover() { return (
Settings

{"Register a new "} application {" and add its API Token here."}

); } function FormFieldsGotify() { return (
Settings
); } function FormFieldsNtfy() { return (
Settings
); } function FormFieldsShoutrrr() { return (
Settings

See full documentation

Services
} placeholder="smtp://username:password@host:port/?from=fromAddress&to=recipient1" required={true} /> ); } const componentMap: componentMapType = { DISCORD: , NOTIFIARR: , TELEGRAM: , PUSHOVER: , GOTIFY: , NTFY: , SHOUTRRR: , LUNASEA: }; interface NotificationAddFormValues { name: string; enabled: boolean; } export function NotificationAddForm({ isOpen, toggle }: AddFormProps) { const queryClient = useQueryClient(); const createMutation = useMutation({ mutationFn: (notification: ServiceNotification) => APIClient.notifications.create(notification), onSuccess: () => { queryClient.invalidateQueries({ queryKey: NotificationKeys.lists() }); toast.custom((t) => ); toggle(); }, onError: () => { toast.custom((t) => ); } }); const onSubmit = (formData: unknown) => createMutation.mutate(formData as ServiceNotification); const testMutation = useMutation({ mutationFn: (n: ServiceNotification) => APIClient.notifications.test(n), onError: (err) => { console.error(err); } }); const testNotification = (data: unknown) => testMutation.mutate(data as ServiceNotification); const validate = (values: NotificationAddFormValues) => { const errors = {} as FormikErrors; if (!values.name) errors.name = "Required"; return errors; }; return (
{({ values }) => (
Add Notifications

Trigger notifications on different events.

{({ field, form: { setFieldValue, resetForm } }: FieldProps) => ( ({ ...base, color: "unset" }) }} theme={(theme) => ({ ...theme, spacing: { ...theme.spacing, controlHeight: 30, baseUnit: 2 } })} value={field?.value && NotificationTypeOptions.find(o => o.value == field?.value)} onChange={(option: unknown) => { resetForm(); const opt = option as SelectOption; setFieldValue(field.name, opt.value ?? ""); }} options={NotificationTypeOptions} /> )}
Events

Select what events to trigger on

{componentMap[values.type]}
)} ); }