Browse Source

fix(perf): add link to transaction summary on performance change explorer (#52730)

Addressing the feedback that @udameli and @narsaynorath gave about
having a link to the transaction summary from the performance change
explorer. This adds a link at the bottom of the performance change
explorer which directs users to the transaction summary with the trends
graph displayed.

<img width="500" alt="Screenshot 2023-07-12 at 12 11 35 PM"
src="https://github.com/getsentry/sentry/assets/72356613/cda93aea-e651-4b3c-96b0-8528b8757ebc">


EDIT: linked to transaction summary through open icon in header instead
<img width="500" alt="image"
src="https://github.com/getsentry/sentry/assets/72356613/6e7d9d39-6ed7-4768-af33-0e3fc1f9832f">
nikkikapadia 1 year ago
parent
commit
49e1a433d1
1 changed files with 88 additions and 4 deletions
  1. 88 4
      static/app/views/performance/trends/changeExplorer.tsx

+ 88 - 4
static/app/views/performance/trends/changeExplorer.tsx

@@ -3,13 +3,19 @@ import styled from '@emotion/styled';
 import {Location} from 'history';
 import moment from 'moment';
 
+import {Button} from 'sentry/components/button';
 import {getArbitraryRelativePeriod} from 'sentry/components/organizations/timeRangeSelector/utils';
 import {DEFAULT_RELATIVE_PERIODS} from 'sentry/constants';
-import {IconFire} from 'sentry/icons';
+import {IconFire, IconOpen} from 'sentry/icons';
 import {t} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
 import {Organization, Project} from 'sentry/types';
 import theme from 'sentry/utils/theme';
+import {normalizeUrl} from 'sentry/utils/withDomainRequired';
+import {
+  DisplayModes,
+  transactionSummaryRouteWithQuery,
+} from 'sentry/views/performance/transactionSummary/utils';
 import {MetricsTable} from 'sentry/views/performance/trends/changeExplorerUtils/metricsTable';
 import {Chart} from 'sentry/views/performance/trends/chart';
 import {
@@ -19,6 +25,7 @@ import {
   TrendsStats,
   TrendView,
 } from 'sentry/views/performance/trends/types';
+import {getTrendProjectId} from 'sentry/views/performance/trends/utils';
 import DetailPanel from 'sentry/views/starfish/components/detailPanel';
 
 type PerformanceChangeExplorerProps = {
@@ -50,8 +57,13 @@ type ExplorerBodyProps = {
 };
 
 type HeaderProps = {
+  organization: Organization;
+  projects: Project[];
   transaction: NormalizedTrendsTransaction;
   trendChangeType: TrendChangeType;
+  trendFunction: string;
+  trendParameter: TrendParameter;
+  trendView: TrendView;
 };
 
 export function PerformanceChangeExplorer({
@@ -100,6 +112,7 @@ function ExplorerBody(props: ExplorerBodyProps) {
     isLoading,
     location,
     organization,
+    projects,
   } = props;
   const breakpointDate = transaction.breakpoint
     ? moment(transaction.breakpoint * 1000).format('ddd, DD MMM YYYY HH:mm:ss z')
@@ -109,7 +122,15 @@ function ExplorerBody(props: ExplorerBodyProps) {
   const end = moment(trendView.end).format('DD MMM YYYY HH:mm:ss z');
   return (
     <Fragment>
-      <Header transaction={transaction} trendChangeType={trendChangeType} />
+      <Header
+        transaction={transaction}
+        trendChangeType={trendChangeType}
+        trendView={trendView}
+        projects={projects}
+        organization={organization}
+        trendFunction={trendFunction}
+        trendParameter={trendParameter}
+      />
       <div style={{display: 'flex', gap: space(4)}}>
         <InfoItem
           label={
@@ -164,9 +185,25 @@ function InfoItem({label, value}: {label: string; value: string}) {
 }
 
 function Header(props: HeaderProps) {
-  const {transaction, trendChangeType} = props;
+  const {
+    transaction,
+    trendChangeType,
+    trendView,
+    projects,
+    organization,
+    trendFunction,
+    trendParameter,
+  } = props;
 
   const regression = trendChangeType === TrendChangeType.REGRESSION;
+  const transactionSummaryLink = getTransactionSummaryLink(
+    trendView,
+    transaction,
+    projects,
+    organization,
+    trendFunction,
+    trendParameter
+  );
 
   return (
     <HeaderWrapper data-test-id="pce-header">
@@ -177,12 +214,44 @@ function Header(props: HeaderProps) {
         <ChangeType regression={regression}>
           {regression ? t('Ongoing Regression') : t('Ongoing Improvement')}
         </ChangeType>
-        <TransactionName>{transaction.transaction}</TransactionName>
+        <TransactionNameWrapper>
+          <TransactionName>{transaction.transaction}</TransactionName>
+          <ViewTransactionButton
+            borderless
+            to={normalizeUrl(transactionSummaryLink)}
+            icon={<IconOpen />}
+            aria-label={t('View transaction summary')}
+          />
+        </TransactionNameWrapper>
       </HeaderTextWrapper>
     </HeaderWrapper>
   );
 }
 
+function getTransactionSummaryLink(
+  eventView: TrendView,
+  transaction: NormalizedTrendsTransaction,
+  projects: Project[],
+  organization: Organization,
+  currentTrendFunction: string,
+  trendParameter: TrendParameter
+) {
+  const summaryView = eventView.clone();
+  const projectID = getTrendProjectId(transaction, projects);
+  const target = transactionSummaryRouteWithQuery({
+    orgSlug: organization.slug,
+    transaction: String(transaction.transaction),
+    query: summaryView.generateQueryStringObject(),
+    projectID,
+    display: DisplayModes.TREND,
+    trendFunction: currentTrendFunction,
+    additionalQuery: {
+      trendParameter: trendParameter.column,
+    },
+  });
+  return target;
+}
+
 const PanelBodyWrapper = styled('div')`
   padding: 0 ${space(2)};
   margin-top: ${space(4)};
@@ -214,8 +283,23 @@ const FireIcon = styled('div')<ChangeTypeProps>`
 
 const TransactionName = styled('h4')`
   margin-right: ${space(1)};
+  margin-bottom: ${space(0)};
   ${p => p.theme.overflowEllipsis};
 `;
+
+const TransactionNameWrapper = styled('div')`
+  display: flex;
+  align-items: center;
+  margin-bottom: ${space(3)};
+  width: fit-content;
+`;
+
+const ViewTransactionButton = styled(Button)`
+  padding: ${space(0)};
+  height: min-content;
+  min-height: 0px;
+`;
+
 const InfoLabel = styled('strong')`
   color: ${p => p.theme.gray300};
 `;