Browse Source

feat(related_groups): Move same title issues below similar stack traces (#81177)

Similar Issues changes:
* Show "issues with similar stack trace" before "issues with same root
cause"
* Rename "issues with same root cause" with "issues with similar titles"
* Added description to the section
* Removed events, users and assignee
* Reduce title font

Next steps:
* Bring further UI & style consistency between the two sections
* Refactor the code into the same directory

Before:
<img width="463" alt="image"
src="https://github.com/user-attachments/assets/6ff67422-e145-46d7-a3bd-2d79d227ee23">
After:
<img width="922" alt="image"
src="https://github.com/user-attachments/assets/0015bc20-37c9-4f19-b7d7-6b0bad22cb1a">


Narrow view:
<img width="463" alt="image"
src="https://github.com/user-attachments/assets/ce13c37f-199d-46f3-a855-afd3023bda94">

Wide view:
<img width="942" alt="image"
src="https://github.com/user-attachments/assets/c1faab56-c96c-42e0-91e2-f5715cefd0a6">
Armen Zambrano G. 3 months ago
parent
commit
9ec2d07c2a

+ 62 - 40
static/app/views/issueDetails/groupRelatedIssues/index.tsx

@@ -74,47 +74,28 @@ function RelatedIssuesSection({
   // This is important for traces since issues can be for any project in the org
   const baseUrl = `/organizations/${orgSlug}/issues/?project=-1`;
   let title: React.ReactNode = null;
-  let linkToTrace: React.ReactNode = null;
+  let extraInfo: React.ReactNode = null;
   let openIssuesButton: React.ReactNode = null;
   if (relationType === 'trace_connected' && traceMeta) {
-    title = t('Issues in the same trace');
-    linkToTrace = (
-      <small>
-        {t('These issues were all found within ')}
-        <Link
-          to={`/organizations/${orgSlug}/performance/trace/${traceMeta.trace_id}/?node=error-${traceMeta.event_id}`}
-        >
-          {t('this trace')}
-        </Link>
-        .
-      </small>
-    );
-    openIssuesButton = (
-      <LinkButton
-        to={`${baseUrl}&query=trace:${traceMeta.trace_id}`}
-        size="xs"
-        analyticsEventName="Clicked Open Issues from trace-connected related issues"
-        analyticsEventKey="similar_issues.trace_connected_issues_clicked_open_issues"
-      >
-        {t('Open in Issues')}
-      </LinkButton>
-    );
+    ({title, extraInfo, openIssuesButton} = getTraceConnectedContent(
+      traceMeta,
+      baseUrl,
+      orgSlug
+    ));
   } else {
-    title = t('Issues caused by the same root cause');
-    openIssuesButton = (
-      <LinkButton
-        to={`${baseUrl}&query=issue.id:[${groupId},${issues}]`}
-        size="xs"
-        analyticsEventName="Clicked Open Issues from same-root related issues"
-        analyticsEventKey="similar_issues.same_root_cause_clicked_open_issues"
-      >
-        {t('Open in Issues')}
-      </LinkButton>
+    title = t('Issues with similar titles');
+    extraInfo = t(
+      'These issues have the same title and may have been caused by the same root cause.'
+    );
+    openIssuesButton = getLinkButton(
+      `${baseUrl}&query=issue.id:[${groupId},${issues}]`,
+      'Clicked Open Issues from same-root related issues',
+      'similar_issues.same_root_cause_clicked_open_issues'
     );
   }
 
   return (
-    <HeaderWrapper>
+    <Fragment>
       {isPending ? (
         <LoadingIndicator />
       ) : isError ? (
@@ -124,28 +105,67 @@ function RelatedIssuesSection({
         />
       ) : issues.length > 0 ? (
         <Fragment>
-          <Title>{title}</Title>
-          <TextButtonWrapper>
-            {linkToTrace}
-            {openIssuesButton}
-          </TextButtonWrapper>
+          <HeaderWrapper>
+            <Title>{title}</Title>
+            <TextButtonWrapper>
+              <span>{extraInfo}</span>
+              {openIssuesButton}
+            </TextButtonWrapper>
+          </HeaderWrapper>
           <GroupList
             orgSlug={orgSlug}
             queryParams={{query: query}}
             source="similar-issues-tab"
             canSelectGroups={false}
             withChart={false}
+            withColumns={['event']}
           />
         </Fragment>
       ) : null}
-    </HeaderWrapper>
+    </Fragment>
   );
 }
 
+const getTraceConnectedContent = (
+  traceMeta: RelatedIssuesResponse['meta'],
+  baseUrl: string,
+  orgSlug: string
+) => {
+  const title = t('Issues in the same trace');
+  const url = `/organizations/${orgSlug}/performance/trace/${traceMeta.trace_id}/?node=error-${traceMeta.event_id}`;
+  const extraInfo = (
+    <small>
+      {t('These issues were all found within')}
+      <Link to={url}>{t('this trace')}</Link>.
+    </small>
+  );
+  const openIssuesButton = getLinkButton(
+    `${baseUrl}&query=trace:${traceMeta.trace_id}`,
+    'Clicked Open Issues from trace-connected related issues',
+    'similar_issues.trace_connected_issues_clicked_open_issues'
+  );
+
+  return {title, extraInfo, openIssuesButton};
+};
+
+const getLinkButton = (to: string, eventName: string, eventKey: string) => {
+  return (
+    <LinkButton
+      to={to}
+      size="xs"
+      analyticsEventName={eventName}
+      analyticsEventKey={eventKey}
+    >
+      {t('Open in Issues')}
+    </LinkButton>
+  );
+};
+
 // Export the component without feature flag controls
 export {GroupRelatedIssues};
 
 const Title = styled('h4')`
+  font-size: ${p => p.theme.fontSizeLarge};
   margin-bottom: ${space(0.75)};
 `;
 
@@ -158,7 +178,9 @@ const HeaderWrapper = styled('div')`
 `;
 
 const TextButtonWrapper = styled('div')`
+  align-items: center;
   display: flex;
   justify-content: space-between;
   margin-bottom: ${space(1)};
+  width: 100%;
 `;

+ 3 - 3
static/app/views/issueDetails/groupSimilarIssues/similarIssues.tsx

@@ -35,12 +35,12 @@ function GroupSimilarIssues() {
 
   return (
     <Fragment>
-      <Feature features="related-issues">
-        <GroupRelatedIssues />
-      </Feature>
       <Feature features="similarity-view" project={project}>
         <SimilarStackTrace project={project} />
       </Feature>
+      <Feature features="related-issues">
+        <GroupRelatedIssues />
+      </Feature>
     </Fragment>
   );
 }

+ 1 - 1
static/app/views/issueDetails/groupSimilarIssues/similarStackTrace/index.tsx

@@ -193,7 +193,7 @@ function SimilarStackTrace({project}: Props) {
       {status === 'ready' && !hasSimilarItems && !hasSimilarityEmbeddingsFeature && (
         <Panel>
           <EmptyStateWarning>
-            <p>{t("There don't seem to be any similar issues.")}</p>
+            <Title>{t("There don't seem to be any similar issues.")}</Title>
           </EmptyStateWarning>
         </Panel>
       )}