import {Fragment, useMemo} from 'react';
import styled from '@emotion/styled';
import countBy from 'lodash/countBy';
import Badge from 'sentry/components/badge';
import ProjectBadge from 'sentry/components/idBadge/projectBadge';
import Link from 'sentry/components/links/link';
import ContextIcon from 'sentry/components/replays/contextIcon';
import ErrorCount from 'sentry/components/replays/header/errorCount';
import HeaderPlaceholder from 'sentry/components/replays/header/headerPlaceholder';
import TimeSince from 'sentry/components/timeSince';
import {IconCalendar} from 'sentry/icons';
import {t} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import {Project} from 'sentry/types';
import {useLocation} from 'sentry/utils/useLocation';
import useProjects from 'sentry/utils/useProjects';
import type {ReplayError, ReplayRecord} from 'sentry/views/replays/types';
type Props = {
replayErrors: ReplayError[];
replayRecord: ReplayRecord | undefined;
};
function ReplayMetaData({replayRecord, replayErrors}: Props) {
const {pathname, query} = useLocation();
const {projects} = useProjects();
const errorsTabHref = {
pathname,
query: {
...query,
t_main: 'console',
f_c_logLevel: 'issue',
f_c_search: undefined,
},
};
const errorCountByProject = useMemo(
() =>
Object.entries(countBy(replayErrors, 'project.name'))
.map(([projectSlug, count]) => ({
project: projects.find(p => p.slug === projectSlug),
count,
}))
// sort to prioritize the replay errors first
.sort(a => (a.project?.id !== replayRecord?.project_id ? 1 : -1)),
[replayErrors, projects, replayRecord]
);
return (
{t('OS')}
{t('Browser')}
{t('Start Time')}
{replayRecord ? (
) : (
)}
{t('Errors')}
{replayRecord ? (
{errorCountByProject.length > 0 ? (
{errorCountByProject.length < 3 ? (
errorCountByProject.map(({project, count}, idx) => (
))
) : (
)}
) : (
)}
) : (
)}
);
}
function StackedErrorCount({
errorCounts,
}: {
errorCounts: Array<{count: number; project: Project | undefined}>;
}) {
const projectCount = errorCounts.length - 2;
const totalErrors = errorCounts.reduce((acc, val) => acc + val.count, 0);
return (
{errorCounts.slice(0, 2).map((v, idx) => {
if (!v.project) {
return null;
}
return ;
})}
+{projectCount}
);
}
const StackedProjectBadges = styled('div')`
display: flex;
align-items: center;
& * {
margin-left: 0;
margin-right: 0;
cursor: pointer;
}
& *:hover {
z-index: unset;
}
& > :not(:first-child) {
margin-left: -${space(0.5)};
}
`;
const KeyMetrics = styled('dl')`
display: grid;
grid-template-rows: max-content 1fr;
grid-template-columns: repeat(4, max-content);
grid-auto-flow: column;
gap: 0 ${space(3)};
align-items: center;
align-self: end;
color: ${p => p.theme.gray300};
margin: 0;
@media (min-width: ${p => p.theme.breakpoints.medium}) {
justify-self: flex-end;
}
`;
const KeyMetricLabel = styled('dt')`
font-size: ${p => p.theme.fontSizeMedium};
`;
const KeyMetricData = styled('dd')`
font-size: ${p => p.theme.fontSizeExtraLarge};
font-weight: normal;
display: flex;
align-items: center;
gap: ${space(1)};
line-height: ${p => p.theme.text.lineHeightBody};
`;
const StyledLink = styled(Link)`
display: flex;
gap: ${space(1)};
`;
export default ReplayMetaData;