|
@@ -1,19 +1,11 @@
|
|
|
-import {ReactNode, useEffect, useState} from 'react';
|
|
|
-import {browserHistory, RouteComponentProps} from 'react-router';
|
|
|
-import styled from '@emotion/styled';
|
|
|
+import {useEffect} from 'react';
|
|
|
+import {browserHistory} from 'react-router';
|
|
|
import {Location} from 'history';
|
|
|
|
|
|
import {loadOrganizationTags} from 'app/actionCreators/tags';
|
|
|
import {Client} from 'app/api';
|
|
|
-import GlobalSdkUpdateAlert from 'app/components/globalSdkUpdateAlert';
|
|
|
-import * as Layout from 'app/components/layouts/thirds';
|
|
|
-import LightWeightNoProjectMessage from 'app/components/lightWeightNoProjectMessage';
|
|
|
-import GlobalSelectionHeader from 'app/components/organizations/globalSelectionHeader';
|
|
|
-import SentryDocumentTitle from 'app/components/sentryDocumentTitle';
|
|
|
import {t} from 'app/locale';
|
|
|
-import {PageContent} from 'app/styles/organization';
|
|
|
import {GlobalSelection, Organization, Project} from 'app/types';
|
|
|
-import {defined} from 'app/utils';
|
|
|
import {trackAnalyticsEvent} from 'app/utils/analytics';
|
|
|
import DiscoverQuery from 'app/utils/discover/discoverQuery';
|
|
|
import EventView from 'app/utils/discover/eventView';
|
|
@@ -31,15 +23,14 @@ import withGlobalSelection from 'app/utils/withGlobalSelection';
|
|
|
import withOrganization from 'app/utils/withOrganization';
|
|
|
import withProjects from 'app/utils/withProjects';
|
|
|
|
|
|
-import {addRoutePerformanceContext, getTransactionName} from '../../utils';
|
|
|
+import {addRoutePerformanceContext} from '../../utils';
|
|
|
import {
|
|
|
decodeFilterFromLocation,
|
|
|
filterToLocationQuery,
|
|
|
SpanOperationBreakdownFilter,
|
|
|
} from '../filter';
|
|
|
-import TransactionHeader from '../header';
|
|
|
+import PageLayout, {ChildProps} from '../pageLayout';
|
|
|
import Tab from '../tabs';
|
|
|
-import {TransactionThresholdMetric} from '../transactionThresholdModal';
|
|
|
import {
|
|
|
PERCENTILE as VITAL_PERCENTILE,
|
|
|
VITAL_GROUPS,
|
|
@@ -52,8 +43,9 @@ import {ZOOM_END, ZOOM_START} from './latencyChart';
|
|
|
// as React.ReactText
|
|
|
type TotalValues = Record<string, number>;
|
|
|
|
|
|
-type Props = RouteComponentProps<{}, {}> & {
|
|
|
+type Props = {
|
|
|
api: Client;
|
|
|
+ location: Location;
|
|
|
selection: GlobalSelection;
|
|
|
organization: Organization;
|
|
|
projects: Project[];
|
|
@@ -61,41 +53,37 @@ type Props = RouteComponentProps<{}, {}> & {
|
|
|
|
|
|
function TransactionOverview(props: Props) {
|
|
|
const {api, location, selection, organization, projects} = props;
|
|
|
- const projectId = decodeScalar(location.query.project);
|
|
|
- const transactionName = getTransactionName(location);
|
|
|
-
|
|
|
- if (!defined(projectId) || !defined(transactionName)) {
|
|
|
- // If there is no transaction name, redirect to the Performance landing page
|
|
|
- browserHistory.replace({
|
|
|
- pathname: `/organizations/${organization.slug}/performance/`,
|
|
|
- query: {
|
|
|
- ...location.query,
|
|
|
- },
|
|
|
- });
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- const project = projects.find(p => p.id === projectId);
|
|
|
|
|
|
useEffect(() => {
|
|
|
loadOrganizationTags(api, organization.slug, selection);
|
|
|
addRoutePerformanceContext(selection);
|
|
|
}, [selection]);
|
|
|
|
|
|
- const [incompatibleAlertNotice, setIncompatibleAlertNotice] = useState<ReactNode>(null);
|
|
|
- const handleIncompatibleQuery = (incompatibleAlertNoticeFn, _errors) => {
|
|
|
- const notice = incompatibleAlertNoticeFn(() => setIncompatibleAlertNotice(null));
|
|
|
- setIncompatibleAlertNotice(notice);
|
|
|
- };
|
|
|
+ return (
|
|
|
+ <PageLayout
|
|
|
+ location={location}
|
|
|
+ organization={organization}
|
|
|
+ projects={projects}
|
|
|
+ tab={Tab.TransactionSummary}
|
|
|
+ getDocumentTitle={getDocumentTitle}
|
|
|
+ generateEventView={generateEventView}
|
|
|
+ childComponent={OverviewContentWrapper}
|
|
|
+ />
|
|
|
+ );
|
|
|
+}
|
|
|
|
|
|
- const [transactionThreshold, setTransactionThreshold] = useState<number | undefined>();
|
|
|
- const [transactionThresholdMetric, setTransactionThresholdMetric] = useState<
|
|
|
- TransactionThresholdMetric | undefined
|
|
|
- >();
|
|
|
+function OverviewContentWrapper(props: ChildProps) {
|
|
|
+ const {
|
|
|
+ location,
|
|
|
+ organization,
|
|
|
+ eventView,
|
|
|
+ transactionName,
|
|
|
+ transactionThreshold,
|
|
|
+ transactionThresholdMetric,
|
|
|
+ } = props;
|
|
|
|
|
|
const spanOperationBreakdownFilter = decodeFilterFromLocation(location);
|
|
|
|
|
|
- const eventView = generateEventView(location, transactionName);
|
|
|
const totalsView = getTotalsEventView(organization, eventView);
|
|
|
|
|
|
const onChangeFilter = (newFilter: SpanOperationBreakdownFilter) => {
|
|
@@ -121,71 +109,31 @@ function TransactionOverview(props: Props) {
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
- <SentryDocumentTitle
|
|
|
- title={getDocumentTitle(transactionName)}
|
|
|
+ <DiscoverQuery
|
|
|
+ eventView={totalsView}
|
|
|
orgSlug={organization.slug}
|
|
|
- projectSlug={project?.slug}
|
|
|
+ location={location}
|
|
|
+ transactionThreshold={transactionThreshold}
|
|
|
+ transactionThresholdMetric={transactionThresholdMetric}
|
|
|
+ referrer="api.performance.transaction-summary"
|
|
|
>
|
|
|
- <GlobalSelectionHeader
|
|
|
- lockedMessageSubject={t('transaction')}
|
|
|
- shouldForceProject={defined(project)}
|
|
|
- forceProject={project}
|
|
|
- specificProjectSlugs={defined(project) ? [project.slug] : []}
|
|
|
- disableMultipleProjectSelection
|
|
|
- showProjectSettingsLink
|
|
|
- >
|
|
|
- <StyledPageContent>
|
|
|
- <LightWeightNoProjectMessage organization={organization}>
|
|
|
- <TransactionHeader
|
|
|
- eventView={eventView}
|
|
|
- location={location}
|
|
|
- organization={organization}
|
|
|
- projects={projects}
|
|
|
- projectId={projectId}
|
|
|
- transactionName={transactionName}
|
|
|
- currentTab={Tab.TransactionSummary}
|
|
|
- hasWebVitals="maybe"
|
|
|
- handleIncompatibleQuery={handleIncompatibleQuery}
|
|
|
- onChangeThreshold={(threshold, metric) => {
|
|
|
- setTransactionThreshold(threshold);
|
|
|
- setTransactionThresholdMetric(metric);
|
|
|
- }}
|
|
|
- />
|
|
|
- <Layout.Body>
|
|
|
- <StyledSdkUpdatesAlert />
|
|
|
- {incompatibleAlertNotice && (
|
|
|
- <Layout.Main fullWidth>{incompatibleAlertNotice}</Layout.Main>
|
|
|
- )}
|
|
|
- <DiscoverQuery
|
|
|
- eventView={totalsView}
|
|
|
- orgSlug={organization.slug}
|
|
|
- location={location}
|
|
|
- transactionThreshold={transactionThreshold}
|
|
|
- transactionThresholdMetric={transactionThresholdMetric}
|
|
|
- referrer="api.performance.transaction-summary"
|
|
|
- >
|
|
|
- {({isLoading, error, tableData}) => {
|
|
|
- const totals: TotalValues | null = tableData?.data?.[0] ?? null;
|
|
|
- return (
|
|
|
- <SummaryContent
|
|
|
- location={location}
|
|
|
- organization={organization}
|
|
|
- eventView={eventView}
|
|
|
- transactionName={transactionName}
|
|
|
- isLoading={isLoading}
|
|
|
- error={error}
|
|
|
- totalValues={totals}
|
|
|
- onChangeFilter={onChangeFilter}
|
|
|
- spanOperationBreakdownFilter={spanOperationBreakdownFilter}
|
|
|
- />
|
|
|
- );
|
|
|
- }}
|
|
|
- </DiscoverQuery>
|
|
|
- </Layout.Body>
|
|
|
- </LightWeightNoProjectMessage>
|
|
|
- </StyledPageContent>
|
|
|
- </GlobalSelectionHeader>
|
|
|
- </SentryDocumentTitle>
|
|
|
+ {({isLoading, error, tableData}) => {
|
|
|
+ const totals: TotalValues | null = tableData?.data?.[0] ?? null;
|
|
|
+ return (
|
|
|
+ <SummaryContent
|
|
|
+ location={location}
|
|
|
+ organization={organization}
|
|
|
+ eventView={eventView}
|
|
|
+ transactionName={transactionName}
|
|
|
+ isLoading={isLoading}
|
|
|
+ error={error}
|
|
|
+ totalValues={totals}
|
|
|
+ onChangeFilter={onChangeFilter}
|
|
|
+ spanOperationBreakdownFilter={spanOperationBreakdownFilter}
|
|
|
+ />
|
|
|
+ );
|
|
|
+ }}
|
|
|
+ </DiscoverQuery>
|
|
|
);
|
|
|
}
|
|
|
|
|
@@ -200,10 +148,6 @@ function getDocumentTitle(transactionName: string): string {
|
|
|
return [t('Summary'), t('Performance')].join(' - ');
|
|
|
}
|
|
|
|
|
|
-const StyledPageContent = styled(PageContent)`
|
|
|
- padding: 0;
|
|
|
-`;
|
|
|
-
|
|
|
function generateEventView(location: Location, transactionName: string): EventView {
|
|
|
// Use the user supplied query but overwrite any transaction or event type
|
|
|
// conditions they applied.
|
|
@@ -288,16 +232,6 @@ function getTotalsEventView(
|
|
|
]);
|
|
|
}
|
|
|
|
|
|
-const StyledSdkUpdatesAlert = styled(GlobalSdkUpdateAlert)`
|
|
|
- @media (min-width: ${p => p.theme.breakpoints[1]}) {
|
|
|
- margin-bottom: 0;
|
|
|
- }
|
|
|
-`;
|
|
|
-
|
|
|
-StyledSdkUpdatesAlert.defaultProps = {
|
|
|
- Wrapper: p => <Layout.Main fullWidth {...p} />,
|
|
|
-};
|
|
|
-
|
|
|
export default withApi(
|
|
|
withGlobalSelection(withProjects(withOrganization(TransactionOverview)))
|
|
|
);
|