import {Fragment} from 'react';
// eslint-disable-next-line no-restricted-imports
import {withRouter, WithRouterProps} from 'react-router';
import {css} from '@emotion/react';
import styled from '@emotion/styled';
import capitalize from 'lodash/capitalize';
import ErrorBoundary from 'sentry/components/errorBoundary';
import EventOrGroupTitle from 'sentry/components/eventOrGroupTitle';
import GlobalSelectionLink from 'sentry/components/globalSelectionLink';
import Tooltip from 'sentry/components/tooltip';
import {IconMute, IconStar} from 'sentry/icons';
import {tct} from 'sentry/locale';
import space from 'sentry/styles/space';
import {Group, GroupTombstone, Level, Organization} from 'sentry/types';
import {Event} from 'sentry/types/event';
import {getLocation, getMessage} from 'sentry/utils/events';
import withOrganization from 'sentry/utils/withOrganization';
import {TagAndMessageWrapper} from 'sentry/views/organizationGroupDetails/unhandledTag';
import EventTitleError from './eventTitleError';
type Size = 'small' | 'normal';
type Props = WithRouterProps<{orgId: string}> & {
data: Event | Group | GroupTombstone;
organization: Organization;
className?: string;
/* is issue breakdown? */
grouping?: boolean;
hideIcons?: boolean;
hideLevel?: boolean;
includeLink?: boolean;
index?: number;
/** Group link clicked */
onClick?: () => void;
query?: string;
size?: Size;
source?: string;
};
/**
* Displays an event or group/issue title (i.e. in Stream)
*/
function EventOrGroupHeader({
data,
index,
organization,
params,
query,
onClick,
className,
hideIcons,
hideLevel,
includeLink = true,
size = 'normal',
grouping = false,
source,
...props
}: Props) {
const hasGroupingTreeUI = !!organization.features?.includes('grouping-tree-ui');
function getTitleChildren() {
const {level, status, isBookmarked, hasSeen} = data as Group;
return (
{!hideLevel && level && (
)}
{!hideIcons && status === 'ignored' && (
)}
{!hideIcons && isBookmarked && (
)}
} mini>
);
}
function getTitle() {
const orgId = params?.orgId;
const {id, status} = data as Group;
const {eventID, groupID} = data as Event;
const {location} = props;
const commonEleProps = {
'data-test-id': status === 'resolved' ? 'resolved-issue' : null,
style: status === 'resolved' ? {textDecoration: 'line-through'} : undefined,
};
if (includeLink) {
return (
{getTitleChildren()}
);
}
return {getTitleChildren()};
}
const location = getLocation(data);
const message = getMessage(data);
return (
{getTitle()}
{location && {location}}
{message && (
{message && {message}}
)}
);
}
const truncateStyles = css`
overflow: hidden;
max-width: 100%;
text-overflow: ellipsis;
white-space: nowrap;
`;
const getMargin = ({size}: {size: Size}) => {
if (size === 'small') {
return 'margin: 0;';
}
return 'margin: 0 0 5px';
};
const Title = styled('div')<{hasGroupingTreeUI: boolean; size: Size}>`
line-height: 1;
margin-bottom: ${space(0.25)};
& em {
font-size: ${p => p.theme.fontSizeMedium};
font-style: normal;
font-weight: 300;
color: ${p => p.theme.subText};
}
${p =>
!p.hasGroupingTreeUI
? css`
${truncateStyles}
`
: css`
> a:first-child {
display: inline-flex;
min-height: ${space(3)};
}
`}
`;
const LocationWrapper = styled('div')`
${truncateStyles};
${getMargin};
direction: rtl;
text-align: left;
font-size: ${p => p.theme.fontSizeMedium};
color: ${p => p.theme.subText};
span {
direction: ltr;
}
`;
function Location(props) {
const {children, ...rest} = props;
return (
{tct('in [location]', {
location: {children},
})}
);
}
const StyledTagAndMessageWrapper = styled(TagAndMessageWrapper)`
${getMargin};
line-height: 1.2;
`;
const Message = styled('div')`
${truncateStyles};
font-size: ${p => p.theme.fontSizeMedium};
`;
const IconWrapper = styled('span')`
position: relative;
display: flex;
margin-right: 5px;
`;
const GroupLevel = styled('div')<{level: Level}>`
position: absolute;
left: -1px;
width: 9px;
height: 15px;
border-radius: 0 3px 3px 0;
background-color: ${p => p.theme.level[p.level] ?? p.theme.level.default};
`;
export default withRouter(withOrganization(EventOrGroupHeader));
const StyledEventOrGroupTitle = styled(EventOrGroupTitle)<{
hasSeen: boolean;
}>`
font-weight: ${p => (p.hasSeen ? 400 : 600)};
`;