useOwnerOptions.tsx 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import groupBy from 'lodash/groupBy';
  2. import Avatar from 'sentry/components/avatar';
  3. import type {BaseAvatarProps} from 'sentry/components/avatar/baseAvatar';
  4. import {t} from 'sentry/locale';
  5. import type {DetailedTeam, Team, User} from 'sentry/types';
  6. interface Options {
  7. /**
  8. * Props to pass to the leading avatar component
  9. */
  10. avatarProps?: BaseAvatarProps;
  11. /**
  12. * Filter teams that are not part of a the provided set of project slugs
  13. */
  14. memberOfProjectSlugs?: string[];
  15. /**
  16. * The users in the owner list
  17. */
  18. members?: User[];
  19. /**
  20. * The teams in the owners list
  21. */
  22. teams?: Team[];
  23. }
  24. /**
  25. * Hook to transform a list of users and teams into a options list, intdended
  26. * to be used with SelectControl or CompactSelect.
  27. */
  28. export function useOwnerOptions({
  29. teams,
  30. members,
  31. avatarProps,
  32. memberOfProjectSlugs,
  33. }: Options) {
  34. // XXX(epurkhiser): It would be nice to use an object as the value, but
  35. // frustratingly that is difficult likely because we're recreating this
  36. // object on every re-render.
  37. const memberOptions =
  38. members?.map(member => ({
  39. value: `user:${member.id}`,
  40. label: member.name,
  41. leadingItems: <Avatar user={member} {...avatarProps} />,
  42. })) ?? [];
  43. const makeTeamOption = (team: Team) => ({
  44. value: `team:${team.id}`,
  45. label: `#${team.slug}`,
  46. leadingItems: <Avatar team={team} {...avatarProps} />,
  47. });
  48. const makeDisabledTeamOption = (team: Team) => ({
  49. ...makeTeamOption(team),
  50. disabled: true,
  51. tooltip: t('%s is not a member of the selected projects', `#${team.slug}`),
  52. tooltipOptions: {position: 'left'},
  53. });
  54. const {disabledTeams, memberTeams, otherTeams} = groupBy(
  55. teams as DetailedTeam[],
  56. team => {
  57. if (
  58. memberOfProjectSlugs &&
  59. !team.projects.some(({slug}) => memberOfProjectSlugs.includes(slug))
  60. ) {
  61. return 'disabledTeams';
  62. }
  63. return team.isMember ? 'memberTeams' : 'otherTeams';
  64. }
  65. );
  66. const myTeamOptions = memberTeams?.map(makeTeamOption) ?? [];
  67. const otherTeamOptions = otherTeams?.map(makeTeamOption) ?? [];
  68. const disabledTeamOptions = disabledTeams?.map(makeDisabledTeamOption) ?? [];
  69. const options = [
  70. {
  71. label: t('My Teams'),
  72. options: myTeamOptions,
  73. },
  74. {
  75. label: t('Members'),
  76. options: memberOptions,
  77. },
  78. {
  79. label: t('Other Teams'),
  80. options: otherTeamOptions,
  81. },
  82. {
  83. label: t('Disabled Teams'),
  84. options: disabledTeamOptions,
  85. },
  86. ];
  87. return options;
  88. }