toolbarSortBy.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import {useCallback, useMemo} from 'react';
  2. import type {SelectOption} from 'sentry/components/compactSelect';
  3. import {CompactSelect} from 'sentry/components/compactSelect';
  4. import {Tooltip} from 'sentry/components/tooltip';
  5. import {t} from 'sentry/locale';
  6. import type {Sort} from 'sentry/utils/discover/fields';
  7. import {formatParsedFunction, parseFunction} from 'sentry/utils/discover/fields';
  8. import {TypeBadge} from 'sentry/views/explore/components/typeBadge';
  9. import {useSpanTags} from 'sentry/views/explore/contexts/spanTagsContext';
  10. import type {Field} from 'sentry/views/explore/hooks/useSampleFields';
  11. import {ToolbarHeader, ToolbarLabel, ToolbarRow, ToolbarSection} from './styles';
  12. interface ToolbarSortByProps {
  13. fields: Field[];
  14. setSorts: (newSorts: Sort[]) => void;
  15. sorts: Sort[];
  16. }
  17. export function ToolbarSortBy({fields, setSorts, sorts}: ToolbarSortByProps) {
  18. const numberTags = useSpanTags('number');
  19. const stringTags = useSpanTags('string');
  20. const fieldOptions: SelectOption<Field>[] = useMemo(() => {
  21. return fields.map(field => {
  22. const tag = stringTags[field] ?? numberTags[field] ?? null;
  23. if (tag) {
  24. return {
  25. label: tag.name,
  26. value: field,
  27. textValue: tag.name,
  28. trailingItems: <TypeBadge tag={tag} />,
  29. };
  30. }
  31. const func = parseFunction(field);
  32. if (func) {
  33. const formatted = formatParsedFunction(func);
  34. return {
  35. label: formatted,
  36. value: field,
  37. textValue: formatted,
  38. trailingItems: <TypeBadge func={func} />,
  39. };
  40. }
  41. // not a tag, maybe it's an aggregate
  42. return {
  43. label: field,
  44. value: field,
  45. textValue: field,
  46. trailingItems: <TypeBadge tag={tag} />,
  47. };
  48. });
  49. }, [fields, numberTags, stringTags]);
  50. const setSortField = useCallback(
  51. (i: number, {value}: SelectOption<Field>) => {
  52. if (sorts[i]) {
  53. setSorts([
  54. {
  55. field: value,
  56. kind: sorts[i].kind,
  57. },
  58. ]);
  59. }
  60. },
  61. [setSorts, sorts]
  62. );
  63. const kindOptions: SelectOption<Sort['kind']>[] = useMemo(() => {
  64. return [
  65. {
  66. label: 'Desc',
  67. value: 'desc',
  68. textValue: t('Descending'),
  69. },
  70. {
  71. label: 'Asc',
  72. value: 'asc',
  73. textValue: t('Ascending'),
  74. },
  75. ];
  76. }, []);
  77. const setSortKind = useCallback(
  78. (i: number, {value}: SelectOption<Sort['kind']>) => {
  79. if (sorts[i]) {
  80. setSorts([
  81. {
  82. field: sorts[i].field,
  83. kind: value,
  84. },
  85. ]);
  86. }
  87. },
  88. [setSorts, sorts]
  89. );
  90. return (
  91. <ToolbarSection data-test-id="section-sort-by">
  92. <ToolbarHeader>
  93. <Tooltip
  94. position="right"
  95. title={t('Results you see first and last in your samples or aggregates.')}
  96. >
  97. <ToolbarLabel>{t('Sort By')}</ToolbarLabel>
  98. </Tooltip>
  99. </ToolbarHeader>
  100. <div>
  101. <ToolbarRow>
  102. <CompactSelect
  103. options={fieldOptions}
  104. value={sorts[0]?.field}
  105. onChange={newSortField => setSortField(0, newSortField)}
  106. />
  107. <CompactSelect
  108. options={kindOptions}
  109. value={sorts[0]?.kind}
  110. onChange={newSortKind => setSortKind(0, newSortKind)}
  111. />
  112. </ToolbarRow>
  113. </div>
  114. </ToolbarSection>
  115. );
  116. }