import {useCallback, useMemo} from 'react'; import styled from '@emotion/styled'; import type {SelectKey, SelectOption} from 'sentry/components/compactSelect'; import {CompactSelect} from 'sentry/components/compactSelect'; import {Tooltip} from 'sentry/components/tooltip'; import {t} from 'sentry/locale'; import type {Sort} from 'sentry/utils/discover/fields'; import { classifyTagKey, parseFunction, prettifyParsedFunction, prettifyTagKey, } from 'sentry/utils/discover/fields'; import {TypeBadge} from 'sentry/views/explore/components/typeBadge'; import {useSpanTags} from 'sentry/views/explore/contexts/spanTagsContext'; import {useResultMode} from 'sentry/views/explore/hooks/useResultsMode'; import type {Field} from 'sentry/views/explore/hooks/useSampleFields'; import {Tab, useTab} from 'sentry/views/explore/hooks/useTab'; import {ToolbarHeader, ToolbarLabel, ToolbarRow, ToolbarSection} from './styles'; interface ToolbarSortByProps { fields: Field[]; setSorts: (newSorts: Sort[]) => void; sorts: Sort[]; } export function ToolbarSortBy({fields, setSorts, sorts}: ToolbarSortByProps) { const [resultMode] = useResultMode(); const [tab] = useTab(); // traces table is only sorted by timestamp so disable the sort by const disabled = resultMode === 'samples' && tab === Tab.TRACE; const numberTags = useSpanTags('number'); const stringTags = useSpanTags('string'); const fieldOptions: SelectOption[] = useMemo(() => { const uniqFields: Field[] = []; for (const field of fields) { if (!uniqFields.includes(field)) { uniqFields.push(field); } } const options = uniqFields.map(field => { const tag = stringTags[field] ?? numberTags[field] ?? null; if (tag) { return { label: tag.name, value: field, textValue: tag.name, trailingItems: , }; } const func = parseFunction(field); if (func) { const formatted = prettifyParsedFunction(func); return { label: formatted, value: field, textValue: formatted, trailingItems: , }; } return { label: prettifyTagKey(field), value: field, textValue: field, trailingItems: , }; }); options.sort((a, b) => { if (a.label < b.label) { return -1; } if (a.label > b.label) { return 1; } return 0; }); return options; }, [fields, numberTags, stringTags]); const setSortField = useCallback( (i: number, {value}: SelectOption) => { if (sorts[i] && typeof value === 'string') { setSorts([ { field: value, kind: sorts[i].kind, }, ]); } }, [setSorts, sorts] ); const kindOptions: SelectOption[] = useMemo(() => { return [ { label: 'Desc', value: 'desc', textValue: t('Descending'), }, { label: 'Asc', value: 'asc', textValue: t('Ascending'), }, ]; }, []); const setSortKind = useCallback( (i: number, {value}: SelectOption) => { if (sorts[i]) { setSorts([ { field: sorts[i].field, kind: value as Sort['kind'], }, ]); } }, [setSorts, sorts] ); let toolbarRow = ( setSortField(0, newSortField)} disabled={disabled} /> setSortKind(0, newSortKind)} disabled={disabled} /> ); if (disabled) { toolbarRow = ( {toolbarRow} ); } return ( {t('Sort By')}
{toolbarRow}
); } const FullWidthTooltip = styled(Tooltip)` width: 100%; `; const ColumnCompactSelect = styled(CompactSelect)` flex: 1 1; min-width: 0; > button { width: 100%; } `; const DirectionCompactSelect = styled(CompactSelect)` width: 90px; > button { width: 100%; } `;