1- import { Fragment , useCallback , useMemo , useState } from 'react' ;
1+ import { Fragment } from 'react' ;
22import { closestCenter , DndContext } from '@dnd-kit/core' ;
33import { SortableContext , verticalListSortingStrategy } from '@dnd-kit/sortable' ;
44import styled from '@emotion/styled' ;
@@ -23,6 +23,7 @@ import {
2323import { ToolbarVisualizeAddChart } from 'sentry/views/explore/components/toolbar/toolbarVisualize' ;
2424import { useMetricsAnalytics } from 'sentry/views/explore/hooks/useAnalytics' ;
2525import { useMetricOptions } from 'sentry/views/explore/hooks/useMetricOptions' ;
26+ import { useEquationReferencedLabels } from 'sentry/views/explore/metrics/hooks/useEquationReferencedLabels' ;
2627import { useMetricReferences } from 'sentry/views/explore/metrics/hooks/useMetricReferences' ;
2728import { useSortableMetricQueries } from 'sentry/views/explore/metrics/hooks/useSortableMetricQueries' ;
2829import { MetricPanel } from 'sentry/views/explore/metrics/metricPanel' ;
@@ -47,81 +48,6 @@ import {
4748import { isVisualizeEquation } from 'sentry/views/explore/queryParams/visualize' ;
4849export const METRICS_CHART_GROUP = 'metrics-charts-group' ;
4950
50- /**
51- * Tracks which metric labels (A, B, etc.) are referenced by equations.
52- *
53- * On initial load, labels are precomputed by reverse-resolving each
54- * equation's stored expression against the referenceMap. When the user
55- * edits an equation, the EquationBuilder reports the exact labels that
56- * were typed, which override the precomputed values for that equation.
57- */
58- function useEquationReferencedLabels ( ) {
59- const metricQueries = useMultiMetricsQueryParams ( ) ;
60- const referenceMap = useMetricReferences ( ) ;
61-
62- // User-reported labels from equation edits override precomputed values
63- const [ userLabelsByEquation , setUserLabelsByEquation ] = useState <
64- Map < string , readonly string [ ] >
65- > ( ( ) => new Map ( ) ) ;
66-
67- const onEquationLabelsChange = useCallback (
68- ( equationLabel : string , labels : string [ ] ) => {
69- setUserLabelsByEquation ( prev => {
70- const current = prev . get ( equationLabel ) ;
71- if (
72- current ?. length === labels . length &&
73- current . every ( ( l , i ) => l === labels [ i ] )
74- ) {
75- return prev ;
76- }
77- const next = new Map ( prev ) ;
78- next . set ( equationLabel , labels ) ;
79- return next ;
80- } ) ;
81- } ,
82- [ ]
83- ) ;
84-
85- const referencedMetricLabels = useMemo ( ( ) => {
86- // Build reverse map (function string → first label) for precomputation
87- const reversedReferenceMap : Record < string , string > = { } ;
88- for ( const [ label , functionString ] of Object . entries ( referenceMap ) ) {
89- if ( ! reversedReferenceMap [ functionString ] ) {
90- reversedReferenceMap [ functionString ] = label ;
91- }
92- }
93-
94- const set = new Set < string > ( ) ;
95- for ( const q of metricQueries ) {
96- const v = q . queryParams . visualizes [ 0 ] ;
97- if ( ! v || ! isVisualizeEquation ( v ) ) {
98- continue ;
99- }
100-
101- const eqLabel = q . label ?? '' ;
102- const userLabels = userLabelsByEquation . get ( eqLabel ) ;
103-
104- if ( userLabels ) {
105- // Use user-reported labels (from explicit equation edits)
106- for ( const label of userLabels ) {
107- set . add ( label ) ;
108- }
109- } else {
110- // Precompute from stored expression via reverse-resolve
111- for ( const token of v . expression . tokens ) {
112- const referencedLabel = reversedReferenceMap [ token . text ] ;
113- if ( referencedLabel ) {
114- set . add ( referencedLabel ) ;
115- }
116- }
117- }
118- }
119- return set ;
120- } , [ metricQueries , referenceMap , userLabelsByEquation ] ) ;
121-
122- return { referencedMetricLabels, onEquationLabelsChange} ;
123- }
124-
12551type MetricsTabProps = {
12652 datePageFilterProps : DatePageFilterProps ;
12753} ;
0 commit comments