organizationCrumb.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import {browserHistory, RouteComponentProps} from 'react-router';
  2. import styled from '@emotion/styled';
  3. import IdBadge from 'sentry/components/idBadge';
  4. import {Organization} from 'sentry/types';
  5. import recreateRoute from 'sentry/utils/recreateRoute';
  6. import withLatestContext from 'sentry/utils/withLatestContext';
  7. import BreadcrumbDropdown from 'sentry/views/settings/components/settingsBreadcrumb/breadcrumbDropdown';
  8. import findFirstRouteWithoutRouteParam from 'sentry/views/settings/components/settingsBreadcrumb/findFirstRouteWithoutRouteParam';
  9. import MenuItem from 'sentry/views/settings/components/settingsBreadcrumb/menuItem';
  10. import {RouteWithName} from './types';
  11. import {CrumbLink} from '.';
  12. type Props = RouteComponentProps<{projectId?: string}, {}> & {
  13. organization: Organization;
  14. organizations: Organization[];
  15. route: RouteWithName;
  16. routes: RouteWithName[];
  17. };
  18. const OrganizationCrumb = ({
  19. organization,
  20. organizations,
  21. params,
  22. routes,
  23. route,
  24. ...props
  25. }: Props) => {
  26. const handleSelect = (item: {value: string}) => {
  27. // If we are currently in a project context, and we're attempting to switch organizations,
  28. // then we need to default to index route (e.g. `route`)
  29. //
  30. // Otherwise, find the last route without a router param
  31. // e.g. if you are on API details, we want the API listing
  32. // This fails if our route tree is not nested
  33. const hasProjectParam = !!params.projectId;
  34. let destination = hasProjectParam
  35. ? route
  36. : findFirstRouteWithoutRouteParam(routes.slice(routes.indexOf(route)));
  37. // It's possible there is no route without route params (e.g. organization settings index),
  38. // in which case, we can use the org settings index route (e.g. `route`)
  39. if (!hasProjectParam && typeof destination === 'undefined') {
  40. destination = route;
  41. }
  42. if (destination === undefined) {
  43. return;
  44. }
  45. browserHistory.push(
  46. recreateRoute(destination, {
  47. routes,
  48. params: {...params, orgId: item.value},
  49. })
  50. );
  51. };
  52. if (!organization) {
  53. return null;
  54. }
  55. const hasMenu = organizations.length > 1;
  56. return (
  57. <BreadcrumbDropdown
  58. name={
  59. <CrumbLink
  60. to={recreateRoute(route, {
  61. routes,
  62. params: {...params, orgId: organization.slug},
  63. })}
  64. >
  65. <BadgeWrapper>
  66. <IdBadge avatarSize={18} organization={organization} />
  67. </BadgeWrapper>
  68. </CrumbLink>
  69. }
  70. onSelect={handleSelect}
  71. hasMenu={hasMenu}
  72. route={route}
  73. items={organizations.map((org, index) => ({
  74. index,
  75. value: org.slug,
  76. label: (
  77. <MenuItem>
  78. <IdBadge organization={org} />
  79. </MenuItem>
  80. ),
  81. }))}
  82. {...props}
  83. />
  84. );
  85. };
  86. const BadgeWrapper = styled('div')`
  87. display: flex;
  88. align-items: center;
  89. `;
  90. export {OrganizationCrumb};
  91. export default withLatestContext(OrganizationCrumb);