|
@@ -1,21 +1,14 @@
|
|
|
-import styled from '@emotion/styled';
|
|
|
-import omit from 'lodash/omit';
|
|
|
-
|
|
|
-import UserAvatar from 'sentry/components/avatar/userAvatar';
|
|
|
-import type {LinkProps} from 'sentry/components/links/link';
|
|
|
-import Link from 'sentry/components/links/link';
|
|
|
-import {space} from 'sentry/styles/space';
|
|
|
import type {AvatarUser, Member} from 'sentry/types';
|
|
|
+import useOrganization from 'sentry/utils/useOrganization';
|
|
|
+
|
|
|
+import UserBadge, {type UserBadgeProps} from './userBadge';
|
|
|
|
|
|
-export interface MemberBadgeProps {
|
|
|
+export interface MemberBadgeProps extends Omit<UserBadgeProps, 'user'> {
|
|
|
member: Member;
|
|
|
- avatarSize?: React.ComponentProps<typeof UserAvatar>['size'];
|
|
|
- className?: string;
|
|
|
- displayEmail?: string;
|
|
|
- displayName?: React.ReactNode;
|
|
|
- hideEmail?: boolean;
|
|
|
- orgId?: string;
|
|
|
- useLink?: boolean;
|
|
|
+ /**
|
|
|
+ * Do not link to the members page
|
|
|
+ */
|
|
|
+ disableLink?: boolean;
|
|
|
}
|
|
|
|
|
|
function getMemberUser(member: Member): AvatarUser {
|
|
@@ -32,82 +25,16 @@ function getMemberUser(member: Member): AvatarUser {
|
|
|
};
|
|
|
}
|
|
|
|
|
|
-function MemberBadge({
|
|
|
- avatarSize = 24,
|
|
|
- useLink = true,
|
|
|
- hideEmail = false,
|
|
|
- displayName,
|
|
|
- displayEmail,
|
|
|
- member,
|
|
|
- orgId,
|
|
|
- className,
|
|
|
-}: MemberBadgeProps) {
|
|
|
+function MemberBadge({member, disableLink, ...props}: MemberBadgeProps) {
|
|
|
const user = getMemberUser(member);
|
|
|
- const title =
|
|
|
- displayName ||
|
|
|
- user.name ||
|
|
|
- user.email ||
|
|
|
- user.username ||
|
|
|
- user.ipAddress ||
|
|
|
- // Because this can be used to render EventUser models, or User *interface*
|
|
|
- // objects from serialized Event models. we try both ipAddress and ip_address.
|
|
|
- user.ip_address;
|
|
|
-
|
|
|
- return (
|
|
|
- <StyledUserBadge className={className}>
|
|
|
- <StyledAvatar user={user} size={avatarSize} />
|
|
|
- <StyledNameAndEmail>
|
|
|
- <StyledName
|
|
|
- useLink={useLink && !!orgId}
|
|
|
- hideEmail={hideEmail}
|
|
|
- to={(member && orgId && `/settings/${orgId}/members/${member.id}/`) || ''}
|
|
|
- >
|
|
|
- {title}
|
|
|
- </StyledName>
|
|
|
- {!hideEmail && <StyledEmail>{displayEmail || user.email}</StyledEmail>}
|
|
|
- </StyledNameAndEmail>
|
|
|
- </StyledUserBadge>
|
|
|
- );
|
|
|
-}
|
|
|
+ const org = useOrganization({allowNull: true});
|
|
|
|
|
|
-const StyledUserBadge = styled('div')`
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
-`;
|
|
|
+ const membersUrl =
|
|
|
+ member && org && !disableLink
|
|
|
+ ? `/settings/${org.slug}/members/${member.id}/`
|
|
|
+ : undefined;
|
|
|
|
|
|
-const StyledNameAndEmail = styled('div')`
|
|
|
- flex-shrink: 1;
|
|
|
- min-width: 0;
|
|
|
- line-height: 1;
|
|
|
-`;
|
|
|
-
|
|
|
-const StyledEmail = styled('div')`
|
|
|
- font-size: 0.875em;
|
|
|
- margin-top: ${space(0.25)};
|
|
|
- color: ${p => p.theme.gray300};
|
|
|
- ${p => p.theme.overflowEllipsis};
|
|
|
-`;
|
|
|
-
|
|
|
-interface NameProps {
|
|
|
- hideEmail: boolean;
|
|
|
- to: LinkProps['to'];
|
|
|
- useLink: boolean;
|
|
|
- children?: React.ReactNode;
|
|
|
+ return <UserBadge to={membersUrl} user={user} {...props} />;
|
|
|
}
|
|
|
|
|
|
-const StyledName = styled(({useLink, to, ...props}: NameProps) => {
|
|
|
- const forwardProps = omit(props, 'hideEmail');
|
|
|
- return useLink ? <Link to={to} {...forwardProps} /> : <span {...forwardProps} />;
|
|
|
-})`
|
|
|
- font-weight: ${(p: NameProps) => (p.hideEmail ? 'inherit' : 'bold')};
|
|
|
- line-height: 1.15em;
|
|
|
- ${p => p.theme.overflowEllipsis};
|
|
|
-`;
|
|
|
-
|
|
|
-const StyledAvatar = styled(UserAvatar)`
|
|
|
- min-width: ${space(3)};
|
|
|
- min-height: ${space(3)};
|
|
|
- margin-right: ${space(1)};
|
|
|
-`;
|
|
|
-
|
|
|
export default MemberBadge;
|