import {Fragment, memo, useEffect, useMemo, useState} from 'react'; import styled from '@emotion/styled'; import {Button, ButtonProps} from 'sentry/components/button'; import {CompactSelect} from 'sentry/components/compactSelect'; import Input from 'sentry/components/input'; import LoadingIndicator from 'sentry/components/loadingIndicator'; import PageFilterBar from 'sentry/components/organizations/pageFilterBar'; import Tag from 'sentry/components/tag'; import { IconCheckmark, IconClose, IconLightning, IconReleases, IconSliders, } from 'sentry/icons'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import {MetricMeta, MRI} from 'sentry/types'; import { isAllowedOp, isCustomMetric, isMeasurement, isTransactionDuration, } from 'sentry/utils/metrics'; import {getReadableMetricType} from 'sentry/utils/metrics/formatters'; import { MetricDisplayType, MetricsQuery, MetricsQuerySubject, MetricWidgetQueryParams, } from 'sentry/utils/metrics/types'; import {useMetricsMeta} from 'sentry/utils/metrics/useMetricsMeta'; import {useMetricsTags} from 'sentry/utils/metrics/useMetricsTags'; import {MetricSearchBar} from 'sentry/views/ddm/metricSearchBar'; import {formatMRI} from '../../../../utils/metrics/mri'; type InlineEditorProps = { displayType: MetricDisplayType; isEdit: boolean; metricsQuery: MetricsQuerySubject; onCancel: () => void; onChange: (data: Partial) => void; onSubmit: () => void; projects: number[]; title: string; onTitleChange?: (title: string) => void; powerUserMode?: boolean; size?: 'xs' | 'sm'; }; const isShownByDefault = (metric: MetricMeta) => isMeasurement(metric) || isCustomMetric(metric) || isTransactionDuration(metric); export const InlineEditor = memo(function InlineEditor({ metricsQuery, projects, displayType, onChange, onCancel, onSubmit, onTitleChange, title, isEdit, size = 'sm', }: InlineEditorProps) { const [editingName, setEditingName] = useState(false); const {data: meta, isLoading: isMetaLoading} = useMetricsMeta(projects); const {data: tags = []} = useMetricsTags(metricsQuery.mri, projects); const displayedMetrics = useMemo(() => { const isSelected = (metric: MetricMeta) => metric.mri === metricsQuery.mri; return meta .filter(metric => isShownByDefault(metric) || isSelected(metric)) .sort(metric => (isSelected(metric) ? -1 : 1)); }, [meta, metricsQuery.mri]); const selectedMeta = useMemo(() => { return meta.find(metric => metric.mri === metricsQuery.mri); }, [meta, metricsQuery.mri]); // Reset the query data if the selected metric is no longer available useEffect(() => { if ( metricsQuery.mri && !isMetaLoading && !displayedMetrics.find(metric => metric.mri === metricsQuery.mri) ) { onChange({mri: '' as MRI, op: '', groupBy: []}); } }, [isMetaLoading, displayedMetrics, metricsQuery.mri, onChange]); const [loading, setIsLoading] = useState(false); useEffect(() => { if (loading && !isEdit) { setIsLoading(false); } }, [isEdit, loading]); return ( {editingName && ( { onTitleChange?.(e.target.value); }} /> )} setEditingName(curr => !curr)} aria-label="edit name" /> {!editingName && ( id.toString())} mri={metricsQuery.mri} disabled={!metricsQuery.mri} onChange={query => { onChange({query}); }} query={metricsQuery.query} /> )} { onSubmit(); setIsLoading(true); }} aria-label="apply" />