breadcrumb.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. import type {Location, LocationDescriptor} from 'history';
  2. import type {Crumb} from 'sentry/components/breadcrumbs';
  3. import Breadcrumbs from 'sentry/components/breadcrumbs';
  4. import {t} from 'sentry/locale';
  5. import type {Organization} from 'sentry/types/organization';
  6. import type {SpanSlug} from 'sentry/utils/performance/suspectSpans/types';
  7. import {decodeScalar} from 'sentry/utils/queryString';
  8. import type {DomainView} from 'sentry/views/insights/pages/useFilters';
  9. import Tab from './transactionSummary/tabs';
  10. import {eventsRouteWithQuery} from './transactionSummary/transactionEvents/utils';
  11. import {spansRouteWithQuery} from './transactionSummary/transactionSpans/utils';
  12. import {tagsRouteWithQuery} from './transactionSummary/transactionTags/utils';
  13. import {vitalsRouteWithQuery} from './transactionSummary/transactionVitals/utils';
  14. import {transactionSummaryRouteWithQuery} from './transactionSummary/utils';
  15. import {vitalDetailRouteWithQuery} from './vitalDetail/utils';
  16. import {getPerformanceLandingUrl} from './utils';
  17. type Props = {
  18. location: Location;
  19. organization: Organization;
  20. eventSlug?: string;
  21. spanSlug?: SpanSlug;
  22. tab?: Tab;
  23. traceSlug?: string;
  24. transaction?: {
  25. name: string;
  26. project: string;
  27. };
  28. vitalName?: string;
  29. };
  30. function Breadcrumb(props: Props) {
  31. function getCrumbs() {
  32. const crumbs: Crumb[] = [];
  33. const {
  34. organization,
  35. location,
  36. transaction,
  37. vitalName,
  38. spanSlug,
  39. eventSlug,
  40. traceSlug,
  41. tab,
  42. } = props;
  43. const performanceTarget: LocationDescriptor = {
  44. pathname: getPerformanceLandingUrl(organization),
  45. query: {
  46. ...location.query,
  47. // clear out the transaction name
  48. transaction: undefined,
  49. },
  50. };
  51. crumbs.push({
  52. to: performanceTarget,
  53. label: t('Performance'),
  54. preservePageFilters: true,
  55. });
  56. crumbs.push(
  57. ...getTabCrumbs({
  58. location,
  59. organization,
  60. transaction,
  61. vitalName,
  62. spanSlug,
  63. eventSlug,
  64. traceSlug,
  65. tab,
  66. })
  67. );
  68. return crumbs;
  69. }
  70. return <Breadcrumbs crumbs={getCrumbs()} />;
  71. }
  72. export const getTabCrumbs = ({
  73. location,
  74. organization,
  75. transaction,
  76. vitalName,
  77. spanSlug,
  78. eventSlug,
  79. traceSlug,
  80. tab,
  81. view,
  82. }: {
  83. location: Location;
  84. organization: Organization;
  85. eventSlug?: string;
  86. spanSlug?: SpanSlug;
  87. tab?: Tab;
  88. traceSlug?: string;
  89. transaction?: {
  90. name: string;
  91. project: string;
  92. };
  93. view?: DomainView;
  94. vitalName?: string;
  95. }) => {
  96. const crumbs: Crumb[] = [];
  97. if (vitalName) {
  98. const webVitalsTarget = vitalDetailRouteWithQuery({
  99. orgSlug: organization.slug,
  100. vitalName: 'fcp',
  101. projectID: decodeScalar(location.query.project),
  102. query: location.query,
  103. });
  104. crumbs.push({
  105. to: webVitalsTarget,
  106. label: t('Vital Detail'),
  107. preservePageFilters: true,
  108. });
  109. } else if (transaction) {
  110. const routeQuery = {
  111. orgSlug: organization.slug,
  112. transaction: transaction.name,
  113. projectID: transaction.project,
  114. query: location.query,
  115. view,
  116. };
  117. switch (tab) {
  118. case Tab.TAGS: {
  119. const tagsTarget = tagsRouteWithQuery(routeQuery);
  120. crumbs.push({
  121. to: tagsTarget,
  122. label: t('Tags'),
  123. preservePageFilters: true,
  124. });
  125. break;
  126. }
  127. case Tab.EVENTS: {
  128. const eventsTarget = eventsRouteWithQuery(routeQuery);
  129. crumbs.push({
  130. to: eventsTarget,
  131. label: t('All Events'),
  132. preservePageFilters: true,
  133. });
  134. break;
  135. }
  136. case Tab.WEB_VITALS: {
  137. const webVitalsTarget = vitalsRouteWithQuery(routeQuery);
  138. crumbs.push({
  139. to: webVitalsTarget,
  140. label: t('Web Vitals'),
  141. preservePageFilters: true,
  142. });
  143. break;
  144. }
  145. case Tab.SPANS: {
  146. const spansTarget = spansRouteWithQuery(routeQuery);
  147. crumbs.push({
  148. to: spansTarget,
  149. label: t('Spans'),
  150. preservePageFilters: true,
  151. });
  152. break;
  153. }
  154. case Tab.REPLAYS: {
  155. crumbs.push({
  156. label: t('Replays'),
  157. });
  158. break;
  159. }
  160. case Tab.PROFILING: {
  161. crumbs.push({
  162. label: t('Profiles'),
  163. });
  164. break;
  165. }
  166. case Tab.AGGREGATE_WATERFALL: {
  167. crumbs.push({
  168. label: t('Aggregate Spans'),
  169. });
  170. break;
  171. }
  172. case Tab.TRANSACTION_SUMMARY:
  173. default: {
  174. const summaryTarget = transactionSummaryRouteWithQuery(routeQuery);
  175. crumbs.push({
  176. to: summaryTarget,
  177. label: t('Transaction Summary'),
  178. preservePageFilters: true,
  179. });
  180. }
  181. }
  182. }
  183. if (transaction && spanSlug) {
  184. crumbs.push({
  185. to: '',
  186. label: t('Span Summary'),
  187. });
  188. } else if (transaction && eventSlug) {
  189. crumbs.push({
  190. to: '',
  191. label: t('Event Details'),
  192. });
  193. } else if (traceSlug) {
  194. crumbs.push({
  195. to: '',
  196. label: t('Trace Details'),
  197. });
  198. }
  199. return crumbs;
  200. };
  201. export default Breadcrumb;