diff --git a/static/app/components/searchQueryBuilder/tokens/filter/valueCombobox.tsx b/static/app/components/searchQueryBuilder/tokens/filter/valueCombobox.tsx index e028933cc9ddef..e449c18adb2551 100644 --- a/static/app/components/searchQueryBuilder/tokens/filter/valueCombobox.tsx +++ b/static/app/components/searchQueryBuilder/tokens/filter/valueCombobox.tsx @@ -247,7 +247,7 @@ export function getPredefinedValues({ ]; } -function tokenSupportsMultipleValues( +export function tokenSupportsMultipleValues( token: TokenResult, keys: TagCollection, fieldDefinition: FieldDefinition | null diff --git a/static/app/views/dashboards/globalFilter/addFilter.tsx b/static/app/views/dashboards/globalFilter/addFilter.tsx index 208da08b79cbcd..ed1e2eeaf7f362 100644 --- a/static/app/views/dashboards/globalFilter/addFilter.tsx +++ b/static/app/views/dashboards/globalFilter/addFilter.tsx @@ -33,6 +33,7 @@ export const DATASET_CHOICES = new Map([ const UNSUPPORTED_FIELD_KINDS = [FieldKind.FUNCTION]; const UNSUPPORTED_FIELD_VALUE_TYPES = [FieldValueType.DATE]; +const IGNORE_DEFAULT_VALUES = [FieldValueType.STRING, FieldValueType.BOOLEAN]; export function getDatasetLabel(dataset: WidgetType) { return DATASET_CHOICES.get(dataset) ?? ''; @@ -129,7 +130,7 @@ function AddFilter({globalFilters, getSearchBarData, onAddFilter}: AddFilterProp const fieldDefinition = fieldDefinitionMap.get(selectedFilterKey.key) ?? null; const valueType = fieldDefinition?.valueType; - if (valueType && valueType !== FieldValueType.STRING) { + if (valueType && !IGNORE_DEFAULT_VALUES.includes(valueType)) { defaultFilterValue = getInitialFilterText( selectedFilterKey.key, fieldDefinition, diff --git a/static/app/views/dashboards/globalFilter/filterSelector.tsx b/static/app/views/dashboards/globalFilter/filterSelector.tsx index c3ff2fd2f4aa90..688f3258fdbc31 100644 --- a/static/app/views/dashboards/globalFilter/filterSelector.tsx +++ b/static/app/views/dashboards/globalFilter/filterSelector.tsx @@ -2,12 +2,15 @@ import {useEffect, useMemo, useState} from 'react'; import styled from '@emotion/styled'; import isEqual from 'lodash/isEqual'; -import type {SelectOption} from '@sentry/scraps/compactSelect'; +import {CompactSelect, type SelectOption} from '@sentry/scraps/compactSelect'; import {Flex} from '@sentry/scraps/layout'; import {Button} from 'sentry/components/core/button'; import {HybridFilter} from 'sentry/components/organizations/hybridFilter'; -import {getPredefinedValues} from 'sentry/components/searchQueryBuilder/tokens/filter/valueCombobox'; +import { + getPredefinedValues, + tokenSupportsMultipleValues, +} from 'sentry/components/searchQueryBuilder/tokens/filter/valueCombobox'; import {MutableSearch} from 'sentry/components/searchSyntax/mutableSearch'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; @@ -64,6 +67,10 @@ function FilterSelector({ [globalFilter, fieldDefinition] ); + const canSelectMultipleValues = filterToken + ? tokenSupportsMultipleValues(filterToken, datasetFilterKeys, fieldDefinition) + : true; + // Retrieve predefined values if the tag has any const predefinedValues = useMemo(() => { if (!filterToken) { @@ -105,6 +112,15 @@ function FilterSelector({ const {data: fetchedFilterValues, isFetching} = queryResult; const options = useMemo(() => { + if (predefinedValues && !canSelectMultipleValues) { + return predefinedValues.flatMap(section => + section.suggestions.map(suggestion => ({ + label: suggestion.value, + value: suggestion.value, + })) + ); + } + const optionMap = new Map>(); const fixedOptionMap = new Map>(); const addOption = (value: string, map: Map>) => @@ -139,6 +155,7 @@ function FilterSelector({ activeFilterValues, stagedFilterValues, searchQuery, + canSelectMultipleValues, ]); const handleChange = (opts: string[]) => { @@ -162,6 +179,64 @@ function FilterSelector({ }); }; + const renderMenuHeaderTrailingItems = ({closeOverlay}: any) => ( + + {activeFilterValues.length > 0 && ( + { + setSearchQuery(''); + handleChange([]); + closeOverlay(); + }} + > + {t('Clear')} + + )} + onRemoveFilter(globalFilter)} + > + {t('Remove Filter')} + + + ); + + const renderFilterSelectorTrigger = () => ( + + ); + + if (!canSelectMultipleValues) { + return ( + 0 ? activeFilterValues[0] : undefined} + onChange={option => { + const newValue = option?.value; + handleChange(newValue ? [newValue] : []); + }} + onClose={() => { + setStagedFilterValues([]); + }} + menuTitle={t('%s Filter', getDatasetLabel(dataset))} + menuHeaderTrailingItems={renderMenuHeaderTrailingItems} + triggerProps={{ + children: renderFilterSelectorTrigger(), + }} + /> + ); + } + return ( { setSearchQuery(''); setStagedFilterValues([]); @@ -187,40 +262,9 @@ function FilterSelector({ isFetching ? t('Loading filter values...') : t('No filter values found') } menuTitle={t('%s Filter', getDatasetLabel(dataset))} - menuHeaderTrailingItems={({closeOverlay}: any) => ( - - {activeFilterValues.length > 0 && ( - { - setSearchQuery(''); - handleChange([]); - closeOverlay(); - }} - > - {t('Clear')} - - )} - onRemoveFilter(globalFilter)} - > - {t('Remove Filter')} - - - )} + menuHeaderTrailingItems={renderMenuHeaderTrailingItems} triggerProps={{ - children: ( - - ), + children: renderFilterSelectorTrigger(), }} /> );