Skip to content

Commit da2996d

Browse files
authored
chore(issue summary): copy tweaks and less sections (#92155)
Addressing feedback: - in the sidebar, show less redundant info (and less info overall) by only showing possible cause section. All sections are still available inside the drawer. - copy tweaks, e.g. possible cause -> initial guess - remove color/bolding in drawer - remove unused thresholding code <img width="411" alt="Screenshot 2025-05-22 at 12 28 57 PM" src="https://github.com/user-attachments/assets/f75c1b44-ca88-4545-aa17-3660a5d6d1d6" /> <img width="709" alt="Screenshot 2025-05-22 at 1 39 03 PM" src="https://github.com/user-attachments/assets/992722df-fbea-424a-9dfb-f889e33d926c" />
1 parent 518c408 commit da2996d

File tree

5 files changed

+133
-85
lines changed

5 files changed

+133
-85
lines changed

static/app/components/group/groupSummary.spec.tsx

Lines changed: 12 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,6 @@ describe('GroupSummary', function () {
2929
},
3030
};
3131

32-
const mockSummaryDataWithLowScores = {
33-
groupId: '1',
34-
whatsWrong: 'Test whats wrong',
35-
trace: 'Test trace',
36-
possibleCause: 'Test possible cause',
37-
headline: 'Test headline',
38-
scores: {
39-
possibleCauseConfidence: 0.5,
40-
possibleCauseNovelty: 0.0,
41-
},
42-
};
43-
4432
const mockSummaryDataWithNullScores = {
4533
groupId: '1',
4634
whatsWrong: 'Test whats wrong',
@@ -89,12 +77,12 @@ describe('GroupSummary', function () {
8977
});
9078

9179
await waitFor(() => {
92-
expect(screen.getByText("What's Wrong")).toBeInTheDocument();
80+
expect(screen.getByText('What Happened')).toBeInTheDocument();
9381
});
9482
expect(await screen.findByText('Test whats wrong')).toBeInTheDocument();
9583
expect(screen.getByText('In the Trace')).toBeInTheDocument();
9684
expect(screen.getByText('Test trace')).toBeInTheDocument();
97-
expect(screen.getByText('Possible Cause')).toBeInTheDocument();
85+
expect(screen.getByText('Initial Guess')).toBeInTheDocument();
9886
expect(screen.getByText('Test possible cause')).toBeInTheDocument();
9987
});
10088

@@ -110,36 +98,15 @@ describe('GroupSummary', function () {
11098
});
11199

112100
await waitFor(() => {
113-
expect(screen.getByText("What's Wrong")).toBeInTheDocument();
101+
expect(screen.getByText('What Happened')).toBeInTheDocument();
114102
});
115103
expect(await screen.findByText('Test whats wrong')).toBeInTheDocument();
116104
expect(screen.getByText('In the Trace')).toBeInTheDocument();
117105
expect(screen.getByText('Test trace')).toBeInTheDocument();
118-
expect(screen.getByText('Possible Cause')).toBeInTheDocument();
106+
expect(screen.getByText('Initial Guess')).toBeInTheDocument();
119107
expect(screen.getByText('Test possible cause')).toBeInTheDocument();
120108
});
121109

122-
it('renders the summary without possible cause when scores are low', async function () {
123-
MockApiClient.addMockResponse({
124-
url: `/organizations/${mockProject.organization.slug}/issues/${mockGroup.id}/summarize/`,
125-
method: 'POST',
126-
body: mockSummaryDataWithLowScores,
127-
});
128-
129-
render(<GroupSummary event={mockEvent} group={mockGroup} project={mockProject} />, {
130-
organization,
131-
});
132-
133-
await waitFor(() => {
134-
expect(screen.getByText("What's Wrong")).toBeInTheDocument();
135-
});
136-
expect(await screen.findByText('Test whats wrong')).toBeInTheDocument();
137-
expect(screen.getByText('In the Trace')).toBeInTheDocument();
138-
expect(screen.getByText('Test trace')).toBeInTheDocument();
139-
expect(screen.queryByText('Possible Cause')).not.toBeInTheDocument();
140-
expect(screen.queryByText('Test possible cause')).not.toBeInTheDocument();
141-
});
142-
143110
it('shows loading state', function () {
144111
MockApiClient.addMockResponse({
145112
url: `/organizations/${mockProject.organization.slug}/issues/${mockGroup.id}/summarize/`,
@@ -187,11 +154,11 @@ describe('GroupSummary', function () {
187154
});
188155

189156
await waitFor(() => {
190-
expect(screen.getByText("What's Wrong")).toBeInTheDocument();
157+
expect(screen.getByText('What Happened')).toBeInTheDocument();
191158
});
192159
expect(await screen.findByText('Test whats wrong')).toBeInTheDocument();
193160
expect(screen.queryByText('In the Trace')).not.toBeInTheDocument();
194-
expect(screen.getByText('Possible Cause')).toBeInTheDocument();
161+
expect(screen.getByText('Initial Guess')).toBeInTheDocument();
195162
expect(screen.getByText('Test possible cause')).toBeInTheDocument();
196163
});
197164

@@ -208,8 +175,12 @@ describe('GroupSummary', function () {
208175
);
209176

210177
await waitFor(() => {
211-
expect(screen.getByText("What's Wrong")).toBeInTheDocument();
178+
expect(screen.getByText('Initial Guess')).toBeInTheDocument();
212179
});
213-
expect(await screen.findByText('Test whats wrong')).toBeInTheDocument();
180+
expect(await screen.findByText('Test possible cause')).toBeInTheDocument();
181+
expect(screen.queryByText('What Happened')).not.toBeInTheDocument();
182+
expect(screen.queryByText('Test whats wrong')).not.toBeInTheDocument();
183+
expect(screen.queryByText('In the Trace')).not.toBeInTheDocument();
184+
expect(screen.queryByText('Test trace')).not.toBeInTheDocument();
214185
});
215186
});

static/app/components/group/groupSummary.tsx

Lines changed: 112 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@ import {type ApiQueryKey, useApiQuery, useQueryClient} from 'sentry/utils/queryC
1616
import useOrganization from 'sentry/utils/useOrganization';
1717
import {useAiConfig} from 'sentry/views/issueDetails/streamline/hooks/useAiConfig';
1818

19-
const POSSIBLE_CAUSE_CONFIDENCE_THRESHOLD = 0.0;
20-
const POSSIBLE_CAUSE_NOVELTY_THRESHOLD = 0.0;
21-
2219
export interface GroupSummaryData {
2320
groupId: string;
2421
headline: string;
@@ -113,7 +110,6 @@ export function GroupSummary({
113110
project: Project;
114111
preview?: boolean;
115112
}) {
116-
const config = getConfigForIssueType(group, project);
117113
const queryClient = useQueryClient();
118114
const organization = useOrganization();
119115
const [forceEvent, setForceEvent] = useState(false);
@@ -150,18 +146,108 @@ export function GroupSummary({
150146
organization.slug,
151147
]);
152148

153-
const shouldShowPossibleCause =
154-
!data?.scores ||
155-
(data.scores.possibleCauseConfidence &&
156-
data.scores.possibleCauseConfidence >= POSSIBLE_CAUSE_CONFIDENCE_THRESHOLD &&
157-
data.scores.possibleCauseNovelty &&
158-
data.scores.possibleCauseNovelty >= POSSIBLE_CAUSE_NOVELTY_THRESHOLD);
149+
if (preview) {
150+
return <GroupSummaryPreview data={data} isPending={isPending} isError={isError} />;
151+
}
152+
return (
153+
<GroupSummaryFull
154+
group={group}
155+
project={project}
156+
data={data}
157+
isPending={isPending}
158+
isError={isError}
159+
setForceEvent={setForceEvent}
160+
preview={preview}
161+
event={event}
162+
/>
163+
);
164+
}
165+
166+
function GroupSummaryPreview({
167+
data,
168+
isPending,
169+
isError,
170+
}: {
171+
data: GroupSummaryData | undefined;
172+
isError: boolean;
173+
isPending: boolean;
174+
}) {
175+
const insightCards = [
176+
{
177+
id: 'possible_cause',
178+
title: t('Initial Guess'),
179+
insight: data?.possibleCause,
180+
icon: <IconFocus size="sm" />,
181+
showWhenLoading: true,
182+
},
183+
];
184+
185+
return (
186+
<div data-testid="group-summary-preview">
187+
{isError ? <div>{t('Error loading summary')}</div> : null}
188+
<Content>
189+
<InsightGrid>
190+
{insightCards.map(card => {
191+
if ((!isPending && !card.insight) || (isPending && !card.showWhenLoading)) {
192+
return null;
193+
}
194+
return (
195+
<InsightCard key={card.id}>
196+
<CardTitle>
197+
<CardTitleIcon>{card.icon}</CardTitleIcon>
198+
<CardTitleText>{card.title}</CardTitleText>
199+
</CardTitle>
200+
<CardContentContainer>
201+
<CardLineDecorationWrapper>
202+
<CardLineDecoration />
203+
</CardLineDecorationWrapper>
204+
{isPending ? (
205+
<CardContent>
206+
<Placeholder height="1.5rem" />
207+
</CardContent>
208+
) : (
209+
<CardContent>
210+
{card.insight && (
211+
<MarkedText text={card.insight.replace(/\*\*/g, '')} />
212+
)}
213+
</CardContent>
214+
)}
215+
</CardContentContainer>
216+
</InsightCard>
217+
);
218+
})}
219+
</InsightGrid>
220+
</Content>
221+
</div>
222+
);
223+
}
224+
225+
function GroupSummaryFull({
226+
group,
227+
project,
228+
data,
229+
isPending,
230+
isError,
231+
setForceEvent,
232+
preview,
233+
event,
234+
}: {
235+
data: GroupSummaryData | undefined;
236+
event: Event | null | undefined;
237+
group: Group;
238+
isError: boolean;
239+
isPending: boolean;
240+
preview: boolean;
241+
project: Project;
242+
setForceEvent: (v: boolean) => void;
243+
}) {
244+
const config = getConfigForIssueType(group, project);
159245
const shouldShowResources = config.resources && !preview;
160246

161247
const insightCards = [
162248
{
163249
id: 'whats_wrong',
164-
title: t("What's Wrong"),
250+
title: t('What Happened'),
165251
insight: data?.whatsWrong,
166252
icon: <IconFatal size="sm" />,
167253
showWhenLoading: true,
@@ -173,23 +259,19 @@ export function GroupSummary({
173259
icon: <IconSpan size="sm" />,
174260
showWhenLoading: false,
175261
},
176-
...(shouldShowPossibleCause
177-
? [
178-
{
179-
id: 'possible_cause',
180-
title: t('Possible Cause'),
181-
insight: data?.possibleCause,
182-
icon: <IconFocus size="sm" />,
183-
showWhenLoading: true,
184-
},
185-
]
186-
: []),
262+
{
263+
id: 'possible_cause',
264+
title: t('Initial Guess'),
265+
insight: data?.possibleCause,
266+
icon: <IconFocus size="sm" />,
267+
showWhenLoading: true,
268+
},
269+
187270
...(shouldShowResources
188271
? [
189272
{
190273
id: 'resources',
191274
title: t('Resources'),
192-
193275
// eslint-disable-next-line @typescript-eslint/no-base-to-string
194276
insight: `${isValidElement(config.resources?.description) ? '' : (config.resources?.description ?? '')}\n\n${config.resources?.links?.map(link => `[${link.text}](${link.link})`).join(' • ') ?? ''}`,
195277
insightElement: isValidElement(config.resources?.description)
@@ -211,13 +293,10 @@ export function GroupSummary({
211293
if ((!isPending && !card.insight) || (isPending && !card.showWhenLoading)) {
212294
return null;
213295
}
214-
215296
return (
216297
<InsightCard key={card.id}>
217-
<CardTitle preview={preview} cardId={card.id}>
218-
<CardTitleIcon cardId={card.id} preview={preview}>
219-
{card.icon}
220-
</CardTitleIcon>
298+
<CardTitle>
299+
<CardTitleIcon>{card.icon}</CardTitleIcon>
221300
<CardTitleText>{card.title}</CardTitleText>
222301
</CardTitle>
223302
<CardContentContainer>
@@ -241,7 +320,7 @@ export function GroupSummary({
241320
);
242321
})}
243322
</InsightGrid>
244-
{data?.eventId && !isPending && !preview && event?.id !== data?.eventId && (
323+
{data?.eventId && !isPending && event && event.id !== data?.eventId && (
245324
<ResummarizeWrapper>
246325
<Button
247326
onClick={() => setForceEvent(true)}
@@ -279,14 +358,11 @@ const InsightCard = styled('div')`
279358
min-height: 0;
280359
`;
281360

282-
const CardTitle = styled('div')<{cardId?: string; preview?: boolean}>`
361+
const CardTitle = styled('div')`
283362
display: flex;
284363
align-items: center;
285364
gap: ${space(1)};
286-
color: ${p =>
287-
p.preview === false && p.cardId === 'whats_wrong'
288-
? p.theme.textColor
289-
: p.theme.subText};
365+
color: ${p => p.theme.subText};
290366
padding-bottom: ${space(0.5)};
291367
`;
292368

@@ -296,13 +372,10 @@ const CardTitleText = styled('p')`
296372
font-weight: ${p => p.theme.fontWeightBold};
297373
`;
298374

299-
const CardTitleIcon = styled('div')<{cardId?: string; preview?: boolean}>`
375+
const CardTitleIcon = styled('div')`
300376
display: flex;
301377
align-items: center;
302-
color: ${p =>
303-
p.preview === false && p.cardId === 'whats_wrong'
304-
? p.theme.pink400
305-
: p.theme.subText};
378+
color: ${p => p.theme.subText};
306379
`;
307380

308381
const CardContentContainer = styled('div')`

static/app/components/group/issueSeerBadge.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ function IssueSeerBadge({group}: IssueSeerBadgeProps) {
3535
} else if (autofixRunExists) {
3636
seerTitle = t('Seer has insight into this issue');
3737
} else if (seerFixable) {
38-
seerTitle = t('This issue might be quick to fix');
38+
seerTitle = t('Seer thinks this issue might be quick to fix');
3939
}
4040

4141
if (!showSeer) {

static/app/views/issueDetails/streamline/header/seerBadge.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function SeerBadge({group}: {group: Group}) {
2222
}
2323

2424
return (
25-
<Tooltip title={t('This issue might be quick to fix')} skipWrapper>
25+
<Tooltip title={t('Seer thinks this issue might be quick to fix')} skipWrapper>
2626
<Wrapper>
2727
<Divider />
2828
<SeerIcon size="sm" />

static/app/views/issueDetails/streamline/sidebar/seerSection.spec.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,20 +53,24 @@ describe('SeerSection', () => {
5353
});
5454

5555
it('renders summary when AI features are enabled and data is available', async () => {
56-
const mockSummary = 'This is a test summary';
56+
const mockWhatHappened = 'This is a test what happened';
57+
const mockTrace = 'This is a test trace';
58+
const mockCause = 'This is a test cause';
5759
MockApiClient.addMockResponse({
5860
url: `/organizations/${mockProject.organization.slug}/issues/${mockGroup.id}/summarize/`,
5961
method: 'POST',
60-
body: {whatsWrong: mockSummary},
62+
body: {possibleCause: mockCause, whatsWrong: mockWhatHappened, trace: mockTrace},
6163
});
6264

6365
render(<SeerSection event={mockEvent} group={mockGroup} project={mockProject} />, {
6466
organization,
6567
});
6668

6769
await waitFor(() => {
68-
expect(screen.getByText(mockSummary)).toBeInTheDocument();
70+
expect(screen.getByText(mockCause)).toBeInTheDocument();
6971
});
72+
expect(screen.queryByText(mockWhatHappened)).not.toBeInTheDocument();
73+
expect(screen.queryByText(mockTrace)).not.toBeInTheDocument();
7074
});
7175

7276
it('renders resources section when AI features are disabled', () => {

0 commit comments

Comments
 (0)