From 5a8c43276e5466c40159c8a204dfa5a40f7a11ed Mon Sep 17 00:00:00 2001 From: Jay Kumar Date: Wed, 20 Nov 2024 13:27:23 +0000 Subject: [PATCH] feat: manual enrich field integration --- keep-ui/app/alerts/EnrichAlertModal.tsx | 181 +++++++++++++++++++++--- keep-ui/app/alerts/alert-menu.tsx | 3 +- keep-ui/app/alerts/alerts.tsx | 3 +- 3 files changed, 169 insertions(+), 18 deletions(-) diff --git a/keep-ui/app/alerts/EnrichAlertModal.tsx b/keep-ui/app/alerts/EnrichAlertModal.tsx index 247116818..534beb369 100644 --- a/keep-ui/app/alerts/EnrichAlertModal.tsx +++ b/keep-ui/app/alerts/EnrichAlertModal.tsx @@ -1,9 +1,10 @@ import { AlertDto } from "./models"; import Modal from "@/components/ui/Modal"; -import { Button, TextInput } from "@tremor/react"; +import { Button, TextInput, Divider } from "@tremor/react"; import { useSession } from "next-auth/react"; import { useApiUrl } from "utils/hooks/useConfig"; -import React from "react"; +import React, { useEffect, useState } from "react"; +import { toast } from "react-toastify"; interface EnrichAlertModalProps { alert: AlertDto | null | undefined; @@ -11,6 +12,38 @@ interface EnrichAlertModalProps { mutate: () => void; } +const EXCLUDED_FIELDS = [ + "id", + "status", + "severity", + "lastReceived", + "fingerprint", + "isPartialDuplicate", + "isFullDuplicate", + "apiKeyRef", + "firingStartTime", + "enriched_fields", + "isNoisy", + "deleted", + "startedAt", + "incident", + "providerId", + "providerType", + "dismissUntil", + "dismissed", + "assignee", + "source", + "pushed", + "environment" +]; + +const transformAlertToEditableFields = (alert: AlertDto | null | undefined) => { + if (!alert) return []; + return Object.entries(alert) + .filter(([key]) => !EXCLUDED_FIELDS.includes(key)) + .map(([key, value]) => ({ key, value })); +}; + const EnrichAlertModal: React.FC = ({ alert, handleClose, @@ -20,41 +53,157 @@ const EnrichAlertModal: React.FC = ({ const { data: session } = useSession(); const apiUrl = useApiUrl(); - if (!alert) return null; + const [customFields, setCustomFields] = useState<{ key: string; value: string }[]>([]); + const [editedFields, setEditedFields] = useState<{ key: string; value: string }[]>([]); + const [finalData, setFinalData] = useState>({}); + + const addCustomField = () => { + setCustomFields((prev) => [...prev, { key: "", value: "" }]); + }; + + const updateCustomField = (index: number, field: "key" | "value", value: string) => { + setCustomFields((prev) => + prev.map((item, i) => (i === index ? { ...item, [field]: value } : item)) + ); + }; + + const removeCustomField = (index: number) => { + setCustomFields((prev) => prev.filter((_, i) => i !== index)); + }; + + const handleFieldChange = (key: string, value: string) => { + setEditedFields((prev) => + prev.map((item) => (item.key === key ? { ...item, value } : item)) + ); + }; + + useEffect(() => { + setCustomFields([]); + setEditedFields(transformAlertToEditableFields(alert)); + }, [alert]); + + useEffect(() => { + const calculateFinalData = () => { + const changedFields = editedFields.reduce((acc, field) => { + const key = field.key as keyof AlertDto; + const originalValue = alert ? alert[key] : undefined; + + if (String(originalValue) !== String(field.value)) { + acc[key] = field.value as any ?? null; + } + return acc; + }, {} as Partial); + + const customFieldData = customFields.reduce((acc, field) => { + if (field.key) { + acc[field.key] = field.value; + } + return acc; + }, {} as Record); + + return { ...changedFields, ...customFieldData }; + }; + + setFinalData(calculateFinalData()); + }, [customFields, editedFields, alert]); - const renderFormFields = () => { - return Object.entries(alert).map(([key, value]) => ( -
-