index.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import {Fragment, useCallback, useMemo} from 'react';
  2. import styled from '@emotion/styled';
  3. import {openModal} from 'sentry/actionCreators/modal';
  4. import {Button} from 'sentry/components/button';
  5. import {TabList, Tabs} from 'sentry/components/tabs';
  6. import {IconTable} from 'sentry/icons/iconTable';
  7. import {t} from 'sentry/locale';
  8. import {space} from 'sentry/styles/space';
  9. import {decodeScalar} from 'sentry/utils/queryString';
  10. import {useLocation} from 'sentry/utils/useLocation';
  11. import {useNavigate} from 'sentry/utils/useNavigate';
  12. import {useResultMode} from 'sentry/views/explore/hooks/useResultsMode';
  13. import {useSampleFields} from 'sentry/views/explore/hooks/useSampleFields';
  14. import {useSpanTags} from '../contexts/spanTagsContext';
  15. import {TracesTable} from './tracesTable/index';
  16. import {AggregatesTable} from './aggregatesTable';
  17. import {ColumnEditorModal} from './columnEditorModal';
  18. import {SpansTable} from './spansTable';
  19. enum Tab {
  20. SPAN = 'span',
  21. TRACE = 'trace',
  22. }
  23. function useTab(): [Tab, (tab: Tab) => void] {
  24. const location = useLocation();
  25. const navigate = useNavigate();
  26. const tab = useMemo(() => {
  27. const rawTab = decodeScalar(location.query.table);
  28. if (rawTab === 'trace') {
  29. return Tab.TRACE;
  30. }
  31. return Tab.SPAN;
  32. }, [location.query.table]);
  33. const setTab = useCallback(
  34. (newTab: Tab) => {
  35. navigate({
  36. ...location,
  37. query: {
  38. ...location.query,
  39. table: newTab,
  40. cursor: undefined,
  41. },
  42. });
  43. },
  44. [location, navigate]
  45. );
  46. return [tab, setTab];
  47. }
  48. interface ExploreTablesProps {}
  49. export function ExploreTables({}: ExploreTablesProps) {
  50. const [resultMode] = useResultMode();
  51. return (
  52. <Fragment>
  53. {resultMode === 'aggregate' && <ExploreAggregatesTable />}
  54. {resultMode === 'samples' && <ExploreSamplesTable />}
  55. </Fragment>
  56. );
  57. }
  58. function ExploreAggregatesTable() {
  59. return <AggregatesTable />;
  60. }
  61. function ExploreSamplesTable() {
  62. const [tab, setTab] = useTab();
  63. const [fields, setFields] = useSampleFields();
  64. const numberTags = useSpanTags('number');
  65. const stringTags = useSpanTags('string');
  66. const openColumnEditor = useCallback(() => {
  67. openModal(
  68. modalProps => (
  69. <ColumnEditorModal
  70. {...modalProps}
  71. columns={fields}
  72. onColumnsChange={setFields}
  73. stringTags={stringTags}
  74. numberTags={numberTags}
  75. />
  76. ),
  77. {closeEvents: 'escape-key'}
  78. );
  79. }, [fields, setFields, stringTags, numberTags]);
  80. return (
  81. <Fragment>
  82. <SamplesTableHeader>
  83. <Tabs value={tab} onChange={setTab}>
  84. <TabList hideBorder>
  85. <TabList.Item key={Tab.SPAN}>{t('Span Samples')}</TabList.Item>
  86. <TabList.Item key={Tab.TRACE}>{t('Trace Samples')}</TabList.Item>
  87. </TabList>
  88. </Tabs>
  89. <Button
  90. disabled={tab !== Tab.SPAN}
  91. onClick={openColumnEditor}
  92. icon={<IconTable />}
  93. >
  94. {t('Edit Table')}
  95. </Button>
  96. </SamplesTableHeader>
  97. {tab === Tab.SPAN && <SpansTable />}
  98. {tab === Tab.TRACE && <TracesTable />}
  99. </Fragment>
  100. );
  101. }
  102. const SamplesTableHeader = styled('div')`
  103. display: flex;
  104. flex-direction: row;
  105. justify-content: space-between;
  106. margin-bottom: ${space(2)};
  107. `;