1- import { useContext , useEffect , useRef , useState } from 'react' ;
1+ import { useContext , useEffect , useMemo , useRef , useState } from 'react' ;
22import styled from '@emotion/styled' ;
33import type { LegendComponentOption } from 'echarts' ;
44import type { Location } from 'history' ;
@@ -9,6 +9,8 @@ import ErrorBoundary from 'sentry/components/errorBoundary';
99import { isWidgetViewerPath } from 'sentry/components/modals/widgetViewerModal/utils' ;
1010import PanelAlert from 'sentry/components/panels/panelAlert' ;
1111import Placeholder from 'sentry/components/placeholder' ;
12+ import { parseQueryBuilderValue } from 'sentry/components/searchQueryBuilder/utils' ;
13+ import { Token } from 'sentry/components/searchSyntax/parser' ;
1214import { t , tct } from 'sentry/locale' ;
1315import HookStore from 'sentry/stores/hookStore' ;
1416import { space } from 'sentry/styles/space' ;
@@ -19,6 +21,7 @@ import type {Confidence, Organization} from 'sentry/types/organization';
1921import type { TableDataWithTitle } from 'sentry/utils/discover/discoverQuery' ;
2022import type { AggregationOutputType , Sort } from 'sentry/utils/discover/fields' ;
2123import { statsPeriodToDays } from 'sentry/utils/duration/statsPeriodToDays' ;
24+ import { getFieldDefinition } from 'sentry/utils/fields' ;
2225import { hasOnDemandMetricWidgetFeature } from 'sentry/utils/onDemandMetrics/features' ;
2326import { useExtractionStatus } from 'sentry/utils/performance/contexts/metricsEnhancedPerformanceDataContext' ;
2427import { VisuallyCompleteWithData } from 'sentry/utils/performanceForSentry' ;
@@ -34,6 +37,7 @@ import withSentryRouter from 'sentry/utils/withSentryRouter';
3437import { DASHBOARD_CHART_GROUP } from 'sentry/views/dashboards/dashboard' ;
3538import type { DashboardFilters , Widget } from 'sentry/views/dashboards/types' ;
3639import {
40+ DashboardFilterKeys ,
3741 DisplayType ,
3842 OnDemandExtractionState ,
3943 WidgetType ,
@@ -199,6 +203,10 @@ function WidgetCard(props: Props) {
199203 const droppedColumnsWarning = useDroppedColumnsWarning ( widget ) ;
200204 const sessionDurationWarning = hasSessionDuration ? SESSION_DURATION_ALERT_TEXT : null ;
201205 const spanTimeRangeWarning = useTimeRangeWarning ( { widget} ) ;
206+ const conflictingFilterWarning = useConflictingFilterWarning ( {
207+ widget,
208+ dashboardFilters,
209+ } ) ;
202210
203211 const onDataFetchStart = ( ) => {
204212 if ( timeoutRef . current ) {
@@ -269,6 +277,7 @@ function WidgetCard(props: Props) {
269277 spanTimeRangeWarning ,
270278 transactionsDeprecationWarning ,
271279 droppedColumnsWarning ,
280+ conflictingFilterWarning ,
272281 ] . filter ( Boolean ) as string [ ] ;
273282
274283 const actionsDisabled = Boolean ( props . isPreview ) ;
@@ -436,6 +445,45 @@ function useTimeRangeWarning({widget}: {widget: Widget}) {
436445 return null ;
437446}
438447
448+ // Displays a warning message if there is a conflict between widget and global filters
449+ function useConflictingFilterWarning ( {
450+ widget,
451+ dashboardFilters,
452+ } : {
453+ dashboardFilters : DashboardFilters | undefined ;
454+ widget : Widget ;
455+ } ) {
456+ const conflictingFilterKeys = useMemo ( ( ) => {
457+ if ( ! dashboardFilters ) return [ ] ;
458+
459+ const widgetFilterKeys = widget . queries . flatMap ( query => {
460+ const parseResult = parseQueryBuilderValue ( query . conditions , getFieldDefinition ) ;
461+ if ( ! parseResult ) {
462+ return [ ] ;
463+ }
464+ return parseResult
465+ . filter ( token => token . type === Token . FILTER )
466+ . map ( token => token . key . text ) ;
467+ } ) ;
468+ const globalFilterKeys =
469+ dashboardFilters ?. [ DashboardFilterKeys . GLOBAL_FILTER ]
470+ ?. filter ( filter => filter . dataset === widget . widgetType )
471+ . map ( filter => filter . tag . key ) ?? [ ] ;
472+
473+ const widgetFilterKeySet = new Set ( widgetFilterKeys ) ;
474+ return globalFilterKeys . filter ( key => widgetFilterKeySet . has ( key ) ) ;
475+ } , [ widget . queries , widget . widgetType , dashboardFilters ] ) ;
476+
477+ if ( conflictingFilterKeys . length > 0 ) {
478+ return tct ( '[strong:Filter conflicts:] [filters]' , {
479+ strong : < strong /> ,
480+ filters : conflictingFilterKeys . join ( ', ' ) ,
481+ } ) ;
482+ }
483+
484+ return null ;
485+ }
486+
439487const ErrorCard = styled ( Placeholder ) `
440488 display: flex;
441489 align-items: center;
0 commit comments