diff --git a/messages/en-US.json b/messages/en-US.json index 30ed6c933..24446f5c8 100644 --- a/messages/en-US.json +++ b/messages/en-US.json @@ -1412,6 +1412,10 @@ "alertingActionWebhook": "Webhook", "alertingActionWebhookDescription": "Send an HTTP request to a custom endpoint", "alertingExternalIntegration": "External Integration", + "alertingExternalPagerDutyDescription": "Send alerts to PagerDuty for incident management", + "alertingExternalOpsgenieDescription": "Route alerts to Opsgenie for on-call management", + "alertingExternalServiceNowDescription": "Create ServiceNow incidents from alert events", + "alertingExternalIncidentIoDescription": "Trigger Incident.io workflows from alert events", "alertingActionType": "Action type", "alertingNotifyUsers": "Users", "alertingNotifyRoles": "Roles", diff --git a/src/components/alert-rule-editor/AlertRuleFields.tsx b/src/components/alert-rule-editor/AlertRuleFields.tsx index 32fbbc5f1..e92980171 100644 --- a/src/components/alert-rule-editor/AlertRuleFields.tsx +++ b/src/components/alert-rule-editor/AlertRuleFields.tsx @@ -52,134 +52,107 @@ import type { Control, UseFormReturn } from "react-hook-form"; import { useFormContext, useWatch } from "react-hook-form"; import { useDebounce } from "use-debounce"; -const EXTERNAL_INTEGRATIONS = [ - { - id: "pagerduty", - name: "PagerDuty", - logo: "/third-party/pgd.png" - }, - { - id: "opsgenie", - name: "Opsgenie", - logo: "/third-party/opsgenie.png" - }, - { - id: "servicenow", - name: "ServiceNow", - logo: "/third-party/servicenow.png" - }, - { - id: "incidentio", - name: "Incident.io", - logo: "/third-party/incidentio.png" - } -] as const; - -const EXTERNAL_IDS = EXTERNAL_INTEGRATIONS.map((i) => i.id); - -export function DropdownAddAction({ +export function AddActionPanel({ onAdd }: { onAdd: (type: AlertRuleFormAction["type"]) => void; }) { const t = useTranslations(); - const [open, setOpen] = useState(false); - const [salesFor, setSalesFor] = useState(null); + + + const EXTERNAL_INTEGRATIONS = [ + { + id: "pagerduty", + name: "PagerDuty", + logo: "/third-party/pgd.png", + description: "Send alerts to PagerDuty for incident management", + descriptionKey: t("alertingExternalPagerDutyDescription") + }, + { + id: "opsgenie", + name: "Opsgenie", + logo: "/third-party/opsgenie.png", + description: "Route alerts to Opsgenie for on-call management", + descriptionKey: t("alertingExternalOpsgenieDescription") + }, + { + id: "servicenow", + name: "ServiceNow", + logo: "/third-party/servicenow.png", + description: "Create ServiceNow incidents from alert events", + descriptionKey: t("alertingExternalServiceNowDescription") + }, + { + id: "incidentio", + name: "Incident.io", + logo: "/third-party/incidentio.png", + description: "Trigger Incident.io workflows from alert events", + descriptionKey: t("alertingExternalIncidentIoDescription") + } + ] as const; + + const EXTERNAL_IDS = EXTERNAL_INTEGRATIONS.map((i) => i.id); + + const [selected, setSelected] = useState(null); + + const isPremiumSelected = + selected !== null && EXTERNAL_IDS.includes(selected as any); + const isBuiltInSelected = selected !== null && !isPremiumSelected; + + const actionTypeOptions = [ + { + id: "notify", + title: t("alertingActionNotify"), + description: t("alertingActionNotifyDescription"), + icon: + }, + { + id: "webhook", + title: t("alertingActionWebhook"), + description: t("alertingActionWebhookDescription"), + icon: + }, + ...EXTERNAL_INTEGRATIONS.map((integration) => ({ + id: integration.id, + title: integration.name, + description: integration.description, + icon: ( + {integration.name} + ) + })) + ]; + + const handleAdd = () => { + if (!isBuiltInSelected) return; + onAdd(selected as AlertRuleFormAction["type"]); + setSelected(null); + }; + return ( - { - setOpen(o); - if (!o) setSalesFor(null); - }} - > - - - - - {salesFor ? ( -
-
- i.id === salesFor - )?.logo - } - alt={salesFor} - className="h-5 w-5 object-contain" - /> - - { - EXTERNAL_INTEGRATIONS.find( - (i) => i.id === salesFor - )?.name - } - -
- - -
- ) : ( - - - - { - onAdd("notify"); - setOpen(false); - }} - > - - {t("alertingActionNotify")} - - { - onAdd("webhook"); - setOpen(false); - }} - > - - {t("alertingActionWebhook")} - - - - {EXTERNAL_INTEGRATIONS.map((integration) => ( - - setSalesFor(integration.id) - } - > - {integration.name} - {integration.name} - - ))} - - - - )} -
-
+ )} + ); } @@ -470,42 +443,19 @@ export function ActionBlock({ }) { const t = useTranslations(); const type = useWatch({ control, name: `actions.${index}.type` }); - const [displayType, setDisplayType] = useState(type ?? "notify"); - useEffect(() => { - if (!EXTERNAL_IDS.includes(displayType as any)) { - setDisplayType(type ?? "notify"); - } - }, [type]); - - const isPremium = EXTERNAL_IDS.includes(displayType as any); - - const actionTypeOptions = [ - { - id: "notify", - title: t("alertingActionNotify"), - description: t("alertingActionNotifyDescription"), - icon: - }, - { - id: "webhook", - title: t("alertingActionWebhook"), - description: t("alertingActionWebhookDescription"), - icon: - }, - ...EXTERNAL_INTEGRATIONS.map((integration) => ({ - id: integration.id, - title: integration.name, - description: t("alertingExternalIntegration"), - icon: ( - {integration.name} - ) - })) - ]; + const typeHeader = + type === "notify" ? ( +
+ + {t("alertingActionNotify")} +
+ ) : ( +
+ + {t("alertingActionWebhook")} +
+ ); return (
@@ -520,44 +470,8 @@ export function ActionBlock({ )} -
- - { - setDisplayType(v); - if (!EXTERNAL_IDS.includes(v as any)) { - const nt = v as AlertRuleFormAction["type"]; - if (nt === "notify") { - onUpdate({ - type: "notify", - userTags: [], - roleTags: [], - emailTags: [] - }); - } else { - onUpdate({ - type: "webhook", - url: "", - method: "POST", - headers: [], - authType: "none", - bearerToken: "", - basicCredentials: "", - customHeaderName: "", - customHeaderValue: "" - }); - } - } - }} - /> -
- {isPremium && } - {!isPremium && type === "notify" && ( + {typeHeader} + {type === "notify" && ( )} - {!isPremium && type === "webhook" && ( + {type === "webhook" && ( -
- - {t( - "alertingSectionActions" - )} - - { - const newIndex = - fields.length; - if (type === "notify") { - append({ - type: "notify", - userTags: [], - roleTags: [], - emailTags: [] - }); - } else { - append({ - type: "webhook", - url: "", - method: "POST", - headers: [ - { - key: "", - value: "" - } - ], - authType: "none", - bearerToken: "", - basicCredentials: "", - customHeaderName: "", - customHeaderValue: "" - }); - } - setSelectedStep( - `action-${newIndex}` - ); - }} - /> -
+ + {t("alertingSectionActions")} + + { + const newIndex = + fields.length; + if (type === "notify") { + append({ + type: "notify", + userTags: [], + roleTags: [], + emailTags: [] + }); + } else { + append({ + type: "webhook", + url: "", + method: "POST", + headers: [ + { + key: "", + value: "" + } + ], + authType: "none", + bearerToken: "", + basicCredentials: "", + customHeaderName: "", + customHeaderValue: "" + }); + } + setSelectedStep( + `action-${newIndex}` + ); + }} + /> {fields.map((f, index) => (