import {Fragment, useEffect} from 'react';
import {css} from '@emotion/react';
import styled from '@emotion/styled';
import isEqual from 'lodash/isEqual';
import ArchivedBox from 'sentry/components/archivedBox';
import GroupEventDetailsLoadingError from 'sentry/components/errors/groupEventDetailsLoadingError';
import {withMeta} from 'sentry/components/events/meta/metaProxy';
import * as Layout from 'sentry/components/layouts/thirds';
import LoadingIndicator from 'sentry/components/loadingIndicator';
import {TransactionProfileIdProvider} from 'sentry/components/profiling/transactionProfileIdProvider';
import ResolutionBox from 'sentry/components/resolutionBox';
import useSentryAppComponentsData from 'sentry/stores/useSentryAppComponentsData';
import {space} from 'sentry/styles/space';
import type {Event} from 'sentry/types/event';
import type {Group, GroupActivityReprocess, GroupReprocessing} from 'sentry/types/group';
import type {RouteComponentProps} from 'sentry/types/legacyReactRouter';
import type {Project} from 'sentry/types/project';
import {defined} from 'sentry/utils';
import {browserHistory} from 'sentry/utils/browserHistory';
import {getConfigForIssueType} from 'sentry/utils/issueTypeConfig';
import {VisuallyCompleteWithData} from 'sentry/utils/performanceForSentry';
import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import useOrganization from 'sentry/utils/useOrganization';
import usePrevious from 'sentry/utils/usePrevious';
import GroupEventDetailsContent from 'sentry/views/issueDetails/groupEventDetails/groupEventDetailsContent';
import {GroupEventDetailsLoading} from 'sentry/views/issueDetails/groupEventDetails/groupEventDetailsLoading';
import GroupEventHeader from 'sentry/views/issueDetails/groupEventHeader';
import GroupSidebar from 'sentry/views/issueDetails/groupSidebar';
import ReprocessingProgress from '../reprocessingProgress';
import {
getEventEnvironment,
getGroupMostRecentActivity,
ReprocessingStatus,
useEnvironmentsFromUrl,
useHasStreamlinedUI,
} from '../utils';
export interface GroupEventDetailsProps
extends RouteComponentProps<{groupId: string; orgId: string; eventId?: string}, {}> {
eventError: boolean;
group: Group;
groupReprocessingStatus: ReprocessingStatus;
loadingEvent: boolean;
onRetry: () => void;
project: Project;
event?: Event;
}
function GroupEventDetails(props: GroupEventDetailsProps) {
const organization = useOrganization();
const {
group,
project,
location,
event,
groupReprocessingStatus,
loadingEvent,
onRetry,
eventError,
params,
} = props;
const projectId = project.id;
const environments = useEnvironmentsFromUrl();
const prevEnvironment = usePrevious(environments);
const prevEvent = usePrevious(event);
const hasStreamlinedUI = useHasStreamlinedUI();
// load the data
useSentryAppComponentsData({projectId});
// If environments are being actively changed and will no longer contain the
// current event's environment, redirect to latest
useEffect(() => {
const environmentsHaveChanged = !isEqual(prevEnvironment, environments);
// If environments are being actively changed and will no longer contain the
// current event's environment, redirect to latest
if (
environmentsHaveChanged &&
prevEvent &&
params.eventId &&
!['latest', 'oldest'].includes(params.eventId)
) {
const shouldRedirect =
environments.length > 0 &&
!environments.find(env => env === getEventEnvironment(prevEvent as Event));
if (shouldRedirect) {
browserHistory.replace(
normalizeUrl({
pathname: `/organizations/${organization.slug}/issues/${params.groupId}/`,
query: location.query,
})
);
return;
}
}
}, [
prevEnvironment,
environments,
location.query,
organization.slug,
params,
prevEvent,
]);
const renderGroupStatusBanner = () => {
if (group.status === 'ignored') {
return (
);
}
if (group.status === 'resolved') {
return (
);
}
return null;
};
const renderContent = () => {
if (loadingEvent) {
if (hasStreamlinedUI) {
return ;
}
return ;
}
if (eventError) {
return (
);
}
return (
);
};
const eventWithMeta = withMeta(event);
const issueTypeConfig = getConfigForIssueType(group, project);
const LayoutBody = hasStreamlinedUI ? 'div' : StyledLayoutBody;
const MainLayoutComponent = hasStreamlinedUI ? 'div' : StyledLayoutMain;
return (
{groupReprocessingStatus === ReprocessingStatus.REPROCESSING ? (
) : (
{!hasStreamlinedUI && renderGroupStatusBanner()}
{eventWithMeta && issueTypeConfig.stats.enabled && !hasStreamlinedUI && (
)}
{renderContent()}
{hasStreamlinedUI ? null : (
)}
)}
);
}
const StyledLayoutBody = styled(Layout.Body)`
/* Makes the borders align correctly */
padding: 0 !important;
@media (min-width: ${p => p.theme.breakpoints.large}) {
align-content: stretch;
}
`;
const GroupStatusBannerWrapper = styled('div')`
margin-bottom: ${space(2)};
`;
const StyledLayoutMain = styled(Layout.Main)`
padding-top: ${space(2)};
@media (max-width: ${p => p.theme.breakpoints.medium}) {
padding-top: ${space(1)};
}
@media (min-width: ${p => p.theme.breakpoints.large}) {
border-right: 1px solid ${p => p.theme.border};
padding-right: 0;
}
`;
const StyledLayoutSide = styled(Layout.Side)<{hasStreamlinedUi: boolean}>`
${p =>
p.hasStreamlinedUi
? css`
padding: ${space(1.5)} ${space(2)};
`
: css`
padding: ${space(3)} ${space(2)} ${space(3)};
@media (min-width: ${p.theme.breakpoints.large}) {
padding-right: ${space(4)};
}
`}
@media (min-width: ${p => p.theme.breakpoints.large}) {
padding-left: ${p => (p.hasStreamlinedUi ? space(0.5) : 0)};
}
`;
export default GroupEventDetails;