import {Fragment, useCallback, useMemo} from 'react'; import {css} from '@emotion/react'; import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator'; import { type ModalOptions, type ModalRenderProps, openModal, } from 'sentry/actionCreators/modal'; import {t} from 'sentry/locale'; import type {MetricsExtractionRule} from 'sentry/types/metrics'; import type {Organization} from 'sentry/types/organization'; import {trackAnalytics} from 'sentry/utils/analytics'; import {useCardinalityLimitedMetricVolume} from 'sentry/utils/metrics/useCardinalityLimitedMetricVolume'; import { aggregatesToGroups, createCondition as createExtractionCondition, explodeAggregateGroup, type FormData, MetricsExtractionRuleForm, } from 'sentry/views/settings/projectMetrics/metricsExtractionRuleForm'; import {useUpdateMetricsExtractionRules} from 'sentry/views/settings/projectMetrics/utils/useMetricsExtractionRules'; interface Props { /** * The extraction rule to edit */ metricExtractionRule: MetricsExtractionRule; organization: Organization; /** * Source parameter for analytics */ source: string; /** * Callback when the form is submitted successfully */ onSubmitSuccess?: (data: FormData) => void; } export function MetricsExtractionRuleEditModal({ Header, Body, closeModal, CloseButton, metricExtractionRule, organization, onSubmitSuccess: onSubmitSuccessProp, }: Props & ModalRenderProps) { const updateExtractionRuleMutation = useUpdateMetricsExtractionRules( organization.slug, metricExtractionRule.projectId ); const {data: cardinality} = useCardinalityLimitedMetricVolume({ projects: [metricExtractionRule.projectId], }); const initialData: FormData = useMemo(() => { return { spanAttribute: metricExtractionRule.spanAttribute, unit: metricExtractionRule.unit, aggregates: aggregatesToGroups(metricExtractionRule.aggregates), tags: metricExtractionRule.tags, conditions: metricExtractionRule.conditions.length ? metricExtractionRule.conditions : [createExtractionCondition()], }; }, [metricExtractionRule]); const handleSubmit = useCallback( ( data: FormData, onSubmitSuccess: (data: FormData) => void, onSubmitError: (error: any) => void ) => { const extractionRule: MetricsExtractionRule = { ...metricExtractionRule, spanAttribute: data.spanAttribute!, tags: data.tags, aggregates: data.aggregates.flatMap(explodeAggregateGroup), unit: data.unit, conditions: data.conditions, }; updateExtractionRuleMutation.mutate( { metricsExtractionRules: [extractionRule], }, { onSuccess: () => { onSubmitSuccess(data); onSubmitSuccessProp?.(data); addSuccessMessage(t('Metric extraction rule updated')); closeModal(); }, onError: error => { const message = error?.responseJSON?.detail ? (error.responseJSON.detail as string) : t('Unable to save your changes.'); onSubmitError(message); addErrorMessage(message); }, } ); onSubmitSuccess(data); }, [closeModal, metricExtractionRule, onSubmitSuccessProp, updateExtractionRuleMutation] ); return (

{t('Edit Metric')}

); } export const modalCss = css` width: 100%; max-width: 900px; `; export function openExtractionRuleEditModal(props: Props, options?: ModalOptions) { const {organization, metricExtractionRule, source, onSubmitSuccess} = props; trackAnalytics('ddm.span-metric.edit.open', { organization, hasFilters: metricExtractionRule.conditions.some(condition => condition.value), source, }); const handleClose: ModalOptions['onClose'] = reason => { if (reason && ['close-button', 'backdrop-click', 'escape-key'].includes(reason)) { trackAnalytics('ddm.span-metric.edit.cancel', {organization}); } options?.onClose?.(reason); }; const handleSubmitSuccess: Props['onSubmitSuccess'] = data => { trackAnalytics('ddm.span-metric.edit.success', { organization, hasFilters: data.conditions.some(condition => condition.value), }); onSubmitSuccess?.(data); }; openModal( modalProps => ( ), { modalCss, ...options, onClose: handleClose, } ); }