import {Fragment, useCallback, useEffect, useState} from 'react'; import styled from '@emotion/styled'; import keyBy from 'lodash/keyBy'; import EventOrGroupExtraDetails from 'sentry/components/eventOrGroupExtraDetails'; import EventOrGroupHeader from 'sentry/components/eventOrGroupHeader'; import {PanelTable} from 'sentry/components/panels'; import Placeholder from 'sentry/components/placeholder'; import {DEFAULT_STREAM_GROUP_STATS_PERIOD} from 'sentry/components/stream/group'; import GroupChart from 'sentry/components/stream/groupChart'; import {t} from 'sentry/locale'; import space from 'sentry/styles/space'; import {Group, NewQuery} from 'sentry/types'; import DiscoverQuery from 'sentry/utils/discover/discoverQuery'; import EventView from 'sentry/utils/discover/eventView'; import theme from 'sentry/utils/theme'; import useApi from 'sentry/utils/useApi'; import {useLocation} from 'sentry/utils/useLocation'; import useMedia from 'sentry/utils/useMedia'; import useOrganization from 'sentry/utils/useOrganization'; import usePageFilters from 'sentry/utils/usePageFilters'; type Props = { projectId: string; replayId: string; }; const columns = [t('Issue'), t('Graph'), t('Events'), t('Users')]; function IssueList(props: Props) { const organization = useOrganization(); const location = useLocation(); const api = useApi(); const {selection} = usePageFilters(); const isScreenLarge = useMedia(`(min-width: ${theme.breakpoints.large})`); const [loadingIssueData, setLoadingIssueData] = useState(false); const [issuesById, setIssuesById] = useState>({}); const [issueStatsById, setIssuesStatsById] = useState>({}); const getEventView = () => { const eventQueryParams: NewQuery = { id: '', name: '', version: 2, fields: ['count(issue)', 'issue'], environment: selection.environments, projects: selection.projects, query: `replayId:${props.replayId} AND event.type:error`, }; const result = EventView.fromNewQueryWithLocation(eventQueryParams, location); return result; }; const fetchIssueData = useCallback(async () => { let issues; setLoadingIssueData(true); try { issues = await api.requestPromise(`/organizations/${organization.slug}/issues/`, { includeAllArgs: true, query: { project: props.projectId, query: `replayId:${props.replayId}`, }, }); setIssuesById(keyBy(issues[0], 'id')); } catch (error) { setIssuesById({}); setLoadingIssueData(false); return; } try { const issuesResults = await api.requestPromise( `/organizations/${organization.slug}/issues-stats/`, { includeAllArgs: true, query: { project: props.projectId, groups: issues[0]?.map(issue => issue.id), query: `replayId:${props.replayId}`, }, } ); setIssuesStatsById(keyBy(issuesResults[0], 'id')); } catch (error) { setIssuesStatsById({}); } finally { setLoadingIssueData(false); } }, [api, organization.slug, props.replayId, props.projectId]); useEffect(() => { fetchIssueData(); }, [fetchIssueData]); const renderTableRow = error => { const matchedIssue = issuesById[error['issue.id']]; const matchedIssueStats = issueStatsById[error['issue.id']]; if (!matchedIssue) { return null; } return ( {isScreenLarge && ( {matchedIssueStats?.stats ? ( ) : ( )} )} {matchedIssueStats?.count ? ( matchedIssueStats?.count ) : ( )} {matchedIssueStats?.userCount ? ( matchedIssueStats?.userCount ) : ( )} ); }; return ( {data => { return ( column !== t('Graph')) } > {data.tableData?.data.map(renderTableRow) || null} ); }} ); } const ChartWrapper = styled('div')` width: 200px; margin-left: -${space(2)}; padding-left: ${space(0)}; `; const Item = styled('div')` display: flex; align-items: center; `; const IssueDetailsWrapper = styled('div')` overflow: hidden; line-height: normal; `; const StyledPanelTable = styled(PanelTable)` /* overflow: visible allows the tooltip to be completely shown */ overflow: visible; grid-template-columns: minmax(1fr, max-content) repeat(3, max-content); @media (max-width: ${p => p.theme.breakpoints.large}) { grid-template-columns: minmax(0, 1fr) repeat(2, max-content); } `; export default IssueList;