import { groupBy } from 'lodash'; import { FC, useCallback, useMemo, useState } from 'react'; import { Button, Icon, Modal, ModalProps, Spinner, Stack } from '@grafana/ui'; import { Trans } from 'app/core/internationalization'; import { AlertState, AlertmanagerGroup, ObjectMatcher, RouteWithID } from 'app/plugins/datasource/alertmanager/types'; import { FormAmRoute } from '../../types/amroutes'; import { MatcherFormatter } from '../../utils/matchers'; import { InsertPosition } from '../../utils/routeTree'; import { AlertGroup } from '../alert-groups/AlertGroup'; import { AlertGroupsSummary } from './AlertGroupsSummary'; import { AmRootRouteForm } from './EditDefaultPolicyForm'; import { AmRoutesExpandedForm } from './EditNotificationPolicyForm'; import { Matchers } from './Matchers'; import { NotificationPoliciesErrorAlert } from './PolicyUpdateErrorAlert'; type ModalHook = [JSX.Element, (item: T) => void, () => void]; type AddModalHook = [JSX.Element, (item: T, position: InsertPosition) => void, () => void]; type EditModalHook = [JSX.Element, (item: RouteWithID, isDefaultRoute?: boolean) => void, () => void]; const useAddPolicyModal = ( handleAdd: (route: Partial, referenceRoute: RouteWithID, position: InsertPosition) => Promise, loading: boolean ): AddModalHook => { const [showModal, setShowModal] = useState(false); const [insertPosition, setInsertPosition] = useState(undefined); const [referenceRoute, setReferenceRoute] = useState(); const handleDismiss = useCallback(() => { setReferenceRoute(undefined); setInsertPosition(undefined); setError(undefined); setShowModal(false); }, []); const handleShow = useCallback((referenceRoute: RouteWithID, position: InsertPosition) => { setReferenceRoute(referenceRoute); setInsertPosition(position); setShowModal(true); }, []); const [error, setError] = useState(undefined); const modalElement = useMemo( () => loading ? ( ) : ( {error && } { if (referenceRoute && insertPosition) { handleAdd(newRoute, referenceRoute, insertPosition).catch(setError); } }} actionButtons={ } /> ), [error, handleAdd, handleDismiss, insertPosition, loading, referenceRoute, showModal, setError] ); return [modalElement, handleShow, handleDismiss]; }; const useEditPolicyModal = ( alertManagerSourceName: string, handleUpdate: (route: Partial) => Promise, loading: boolean ): EditModalHook => { const [showModal, setShowModal] = useState(false); const [isDefaultPolicy, setIsDefaultPolicy] = useState(false); const [route, setRoute] = useState(); const [error, setError] = useState(undefined); const handleDismiss = useCallback(() => { setRoute(undefined); setShowModal(false); setError(undefined); }, []); const handleShow = useCallback((route: RouteWithID, isDefaultPolicy?: boolean) => { setIsDefaultPolicy(isDefaultPolicy ?? false); setRoute(route); setShowModal(true); }, []); const modalElement = useMemo( () => loading ? ( ) : ( {error && } {isDefaultPolicy && route && ( handleUpdate(values).catch(setError)} route={route} actionButtons={ } /> )} {!isDefaultPolicy && ( handleUpdate(values).catch(setError)} actionButtons={ } /> )} ), [loading, showModal, handleDismiss, error, isDefaultPolicy, route, alertManagerSourceName, handleUpdate, setError] ); return [modalElement, handleShow, handleDismiss]; }; const useDeletePolicyModal = ( handleDelete: (route: RouteWithID) => Promise, loading: boolean ): ModalHook => { const [showModal, setShowModal] = useState(false); const [route, setRoute] = useState(); const [error, setError] = useState(undefined); const handleDismiss = useCallback(() => { setRoute(undefined); setShowModal(false); setError(undefined); }, [setRoute]); const handleShow = useCallback((route: RouteWithID) => { setRoute(route); setShowModal(true); }, []); const modalElement = useMemo( () => loading ? ( ) : ( {error && } Deleting this notification policy will permanently remove it. {' '} Are you sure you want to delete this policy? ), [handleDismiss, loading, showModal, error, route, handleDelete] ); return [modalElement, handleShow, handleDismiss]; }; const useAlertGroupsModal = ( alertManagerSourceName: string ): [JSX.Element, (alertGroups: AlertmanagerGroup[], matchers?: ObjectMatcher[]) => void, () => void] => { const [showModal, setShowModal] = useState(false); const [alertGroups, setAlertGroups] = useState([]); const [matchers, setMatchers] = useState([]); const [formatter, setFormatter] = useState('default'); const handleDismiss = useCallback(() => { setShowModal(false); setAlertGroups([]); setMatchers([]); }, []); const handleShow = useCallback( (alertGroups: AlertmanagerGroup[], matchers?: ObjectMatcher[], formatter?: MatcherFormatter) => { setAlertGroups(alertGroups); if (matchers) { setMatchers(matchers); } if (formatter) { setFormatter(formatter); } setShowModal(true); }, [] ); const instancesByState = useMemo(() => { const instances = alertGroups.flatMap((group) => group.alerts); return groupBy(instances, (instance) => instance.status.state); }, [alertGroups]); const modalElement = useMemo( () => ( Matchers } >
{alertGroups.map((group, index) => ( ))}
), [alertGroups, handleDismiss, instancesByState, matchers, formatter, showModal, alertManagerSourceName] ); return [modalElement, handleShow, handleDismiss]; }; const UpdatingModal: FC> = ({ isOpen }) => ( {}} closeOnBackdropClick={false} closeOnEscape={false} title={ Updating... } > Please wait while we update your notification policies. ); export { useAddPolicyModal, useAlertGroupsModal, useDeletePolicyModal, useEditPolicyModal };