organizationCrumb.tsx 3.1 KB

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