1- import type { ReactNode } from 'react' ;
21import { Fragment , useEffect , useRef } from 'react' ;
32import { useTheme } from '@emotion/react' ;
43import styled from '@emotion/styled' ;
54
65import { openNavigateToExternalLinkModal } from 'sentry/actionCreators/modal' ;
76import AnalyticsArea from 'sentry/components/analyticsArea' ;
87import ErrorBoundary from 'sentry/components/errorBoundary' ;
8+ import { getOrderedContextItems } from 'sentry/components/events/contexts' ;
9+ import ContextCard from 'sentry/components/events/contexts/contextCard' ;
10+ import EventTagsTree from 'sentry/components/events/eventTags/eventTagsTree' ;
911import CrashReportSection from 'sentry/components/feedback/feedbackItem/crashReportSection' ;
1012import FeedbackActivitySection from 'sentry/components/feedback/feedbackItem/feedbackActivitySection' ;
1113import FeedbackItemHeader from 'sentry/components/feedback/feedbackItem/feedbackItemHeader' ;
12- import Section from 'sentry/components/feedback/feedbackItem/feedbackItemSection' ;
14+ import FeedbackItemSection from 'sentry/components/feedback/feedbackItem/feedbackItemSection' ;
1315import FeedbackReplay from 'sentry/components/feedback/feedbackItem/feedbackReplay' ;
1416import MessageSection from 'sentry/components/feedback/feedbackItem/messageSection' ;
15- import TagsSection from 'sentry/components/feedback/feedbackItem/tagsSection' ;
1617import TraceDataSection from 'sentry/components/feedback/feedbackItem/traceDataSection' ;
18+ import { KeyValueData } from 'sentry/components/keyValueData' ;
1719import PanelItem from 'sentry/components/panels/panelItem' ;
1820import QuestionTooltip from 'sentry/components/questionTooltip' ;
1921import TextCopyInput from 'sentry/components/textCopyInput' ;
@@ -22,16 +24,16 @@ import {t} from 'sentry/locale';
2224import { space } from 'sentry/styles/space' ;
2325import type { Event } from 'sentry/types/event' ;
2426import type { Group } from 'sentry/types/group' ;
27+ import type { Project } from 'sentry/types/project' ;
2528import type { FeedbackIssue } from 'sentry/utils/feedback/types' ;
2629import useOrganization from 'sentry/utils/useOrganization' ;
2730
2831interface Props {
2932 eventData : Event | undefined ;
3033 feedbackItem : FeedbackIssue ;
31- tags : Record < string , string | ReactNode > ;
3234}
3335
34- export default function FeedbackItem ( { feedbackItem, eventData, tags } : Props ) {
36+ export default function FeedbackItem ( { feedbackItem, eventData} : Props ) {
3537 const organization = useOrganization ( ) ;
3638 const url =
3739 eventData ?. contexts ?. feedback ?. url ??
@@ -59,12 +61,17 @@ export default function FeedbackItem({feedbackItem, eventData, tags}: Props) {
5961 < AnalyticsArea name = "details" >
6062 < FeedbackItemHeader eventData = { eventData } feedbackItem = { feedbackItem } />
6163 < OverflowPanelItem ref = { overflowRef } >
62- < Section >
64+ < FeedbackItemSection sectionKey = "message" >
6365 < MessageSection eventData = { eventData } feedbackItem = { feedbackItem } />
64- </ Section >
66+ </ FeedbackItemSection >
6567
6668 { ! crashReportId || ( crashReportId && url ) ? (
67- < Section icon = { < IconLink size = "xs" /> } title = { t ( 'URL' ) } >
69+ < FeedbackItemSection
70+ collapsible
71+ icon = { < IconLink size = "xs" /> }
72+ sectionKey = "url"
73+ title = { t ( 'URL' ) }
74+ >
6875 < TextCopyInput
6976 style = { urlIsLink ? { color : theme . blue400 } : undefined }
7077 onClick = {
@@ -78,19 +85,24 @@ export default function FeedbackItem({feedbackItem, eventData, tags}: Props) {
7885 >
7986 { displayUrl }
8087 </ TextCopyInput >
81- </ Section >
88+ </ FeedbackItemSection >
8289 ) : null }
8390
8491 { crashReportId && feedbackItem . project ? (
85- < Section icon = { < IconFire size = "xs" /> } title = { t ( 'Linked Error' ) } >
92+ < FeedbackItemSection
93+ collapsible
94+ icon = { < IconFire size = "xs" /> }
95+ sectionKey = "crash-report"
96+ title = { t ( 'Linked Error' ) }
97+ >
8698 < ErrorBoundary mini >
8799 < CrashReportSection
88100 organization = { organization }
89101 crashReportId = { crashReportId }
90102 projectSlug = { feedbackItem . project . slug }
91103 />
92104 </ ErrorBoundary >
93- </ Section >
105+ </ FeedbackItemSection >
94106 ) : null }
95107
96108 < FeedbackReplay
@@ -105,13 +117,41 @@ export default function FeedbackItem({feedbackItem, eventData, tags}: Props) {
105117 </ ErrorBoundary >
106118 ) : null }
107119
108- < Section icon = { < IconTag size = "xs" /> } title = { t ( 'Tags' ) } >
109- < TagsSection tags = { tags } />
110- </ Section >
120+ { eventData && feedbackItem . project ? (
121+ < FeedbackItemSection
122+ collapsible
123+ icon = { < IconTag size = "xs" /> }
124+ sectionKey = "tags"
125+ title = { t ( 'Tags' ) }
126+ >
127+ < EventTagsTree
128+ event = { eventData }
129+ projectSlug = { feedbackItem . project . slug }
130+ tags = { eventData . tags }
131+ />
132+ </ FeedbackItemSection >
133+ ) : null }
134+
135+ { eventData ? (
136+ < FeedbackItemSection
137+ collapsible
138+ icon = { < IconTag size = "xs" /> }
139+ sectionKey = "context"
140+ title = { t ( 'Context' ) }
141+ >
142+ < FeedbackItemContexts
143+ feedbackItem = { feedbackItem }
144+ eventData = { eventData }
145+ project = { feedbackItem . project }
146+ />
147+ </ FeedbackItemSection >
148+ ) : null }
111149
112150 { feedbackItem . project ? (
113- < Section
151+ < FeedbackItemSection
152+ collapsible
114153 icon = { < IconChat size = "xs" /> }
154+ sectionKey = "activity"
115155 title = {
116156 < Fragment >
117157 { t ( 'Internal Activity' ) }
@@ -125,14 +165,48 @@ export default function FeedbackItem({feedbackItem, eventData, tags}: Props) {
125165 }
126166 >
127167 < FeedbackActivitySection feedbackItem = { feedbackItem as unknown as Group } />
128- </ Section >
168+ </ FeedbackItemSection >
129169 ) : null }
130170 </ OverflowPanelItem >
131171 </ AnalyticsArea >
132172 </ Fragment >
133173 ) ;
134174}
135175
176+ function FeedbackItemContexts ( {
177+ eventData,
178+ feedbackItem,
179+ project,
180+ } : {
181+ eventData : Event ;
182+ feedbackItem : FeedbackIssue ;
183+ project : undefined | Project ;
184+ } ) {
185+ const cards = getOrderedContextItems ( eventData ) . map (
186+ ( { alias, type, value : contextValue } ) => (
187+ < ContextCard
188+ key = { alias }
189+ type = { type }
190+ alias = { alias }
191+ value = { contextValue }
192+ event = { eventData }
193+ group = { feedbackItem as unknown as Group }
194+ project = { project }
195+ />
196+ )
197+ ) ;
198+
199+ if ( ! cards . length ) {
200+ return null ;
201+ }
202+
203+ return (
204+ < ErrorBoundary mini message = { t ( 'There was a problem loading event context.' ) } >
205+ < KeyValueData . Container > { cards } </ KeyValueData . Container >
206+ </ ErrorBoundary >
207+ ) ;
208+ }
209+
136210// 0 padding-bottom because <ActivitySection> has space(2) built-in.
137211const OverflowPanelItem = styled ( PanelItem ) `
138212 overflow: auto;
0 commit comments