organizationCrumb.tsx 2.8 KB

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