import {Fragment} from 'react'; import styled from '@emotion/styled'; import { AssigneeSelectorDropdown, AssigneeSelectorDropdownProps, SuggestedAssignee, } from 'sentry/components/assigneeSelectorDropdown'; import ActorAvatar from 'sentry/components/avatar/actorAvatar'; import SuggestedAvatarStack from 'sentry/components/avatar/suggestedAvatarStack'; import ExternalLink from 'sentry/components/links/externalLink'; import LoadingIndicator from 'sentry/components/loadingIndicator'; import {Tooltip} from 'sentry/components/tooltip'; import {IconChevron, IconUser} from 'sentry/icons'; import {t, tct, tn} from 'sentry/locale'; import GroupStore from 'sentry/stores/groupStore'; import {useLegacyStore} from 'sentry/stores/useLegacyStore'; import {space} from 'sentry/styles/space'; import type {Actor, SuggestedOwnerReason} from 'sentry/types'; import useOrganization from 'sentry/utils/useOrganization'; interface AssigneeSelectorProps extends Omit< AssigneeSelectorDropdownProps, 'children' | 'organization' | 'assignedTo' > { noDropdown?: boolean; } function AssigneeAvatar({ assignedTo, suggestedActors = [], }: { assignedTo?: Actor | null; suggestedActors?: SuggestedAssignee[]; }) { const suggestedReasons: Record = { suspectCommit: tct('Based on [commit:commit data]', { commit: ( ), }), ownershipRule: t('Matching Issue Owners Rule'), projectOwnership: t('Matching Issue Owners Rule'), codeowners: t('Matching Codeowners Rule'), }; const assignedToSuggestion = suggestedActors.find(actor => actor.id === assignedTo?.id); if (assignedTo) { return ( {tct('Assigned to [name]', { name: assignedTo.type === 'team' ? `#${assignedTo.name}` : assignedTo.name, })} {assignedToSuggestion && suggestedReasons[assignedToSuggestion.suggestedReason] && ( {suggestedReasons[assignedToSuggestion.suggestedReason]} )} } /> ); } if (suggestedActors.length > 0) { return (
{tct('Suggestion: [name]', { name: suggestedActors[0].type === 'team' ? `#${suggestedActors[0].name}` : suggestedActors[0].name, })} {suggestedActors.length > 1 && tn(' + %s other', ' + %s others', suggestedActors.length - 1)}
{suggestedReasons[suggestedActors[0].suggestedReason]} } /> ); } return (
{t('Unassigned')}
{tct( 'You can auto-assign issues by adding [issueOwners:Issue Owner rules].', { issueOwners: ( ), } )} } >
); } function AssigneeSelector({noDropdown, ...props}: AssigneeSelectorProps) { const organization = useOrganization(); const groups = useLegacyStore(GroupStore); const group = groups.find(item => item.id === props.id); return ( {({loading, isOpen, getActorProps, suggestedAssignees}) => { const avatarElement = ( ); return ( {loading && ( )} {!loading && !noDropdown && ( {avatarElement} )} {!loading && noDropdown && avatarElement} ); }} ); } export default AssigneeSelector; const AssigneeWrapper = styled('div')` display: flex; justify-content: flex-end; /* manually align menu underneath dropdown caret */ `; const StyledIconUser = styled(IconUser)` /* We need this to center with Avatar */ margin-right: 2px; `; const StyledChevron = styled(IconChevron)` margin-left: ${space(1)}; `; const DropdownButton = styled('div')` display: flex; align-items: center; font-size: 20px; `; const TooltipWrapper = styled('div')` text-align: left; `; const TooltipSubtext = styled('div')` color: ${p => p.theme.subText}; `; const TooltipSubExternalLink = styled(ExternalLink)` color: ${p => p.theme.subText}; text-decoration: underline; :hover { color: ${p => p.theme.subText}; } `;