organizationCrumb.tsx 3.1 KB

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