diff --git a/static/app/views/performance/transactionSummary/transactionTags/content.tsx b/static/app/views/performance/transactionSummary/transactionTags/content.tsx index f84a67b92c375a..653e7c659effc7 100644 --- a/static/app/views/performance/transactionSummary/transactionTags/content.tsx +++ b/static/app/views/performance/transactionSummary/transactionTags/content.tsx @@ -1,10 +1,11 @@ -import {Fragment, useEffect, useState} from 'react'; +import {useEffect, useState} from 'react'; import {browserHistory} from 'react-router'; import styled from '@emotion/styled'; import {Location} from 'history'; import {SectionHeading} from 'app/components/charts/styles'; import SearchBar from 'app/components/events/searchBar'; +import * as Layout from 'app/components/layouts/thirds'; import LoadingIndicator from 'app/components/loadingIndicator'; import {getParams} from 'app/components/organizations/globalSelectionHeader/getParams'; import QuestionTooltip from 'app/components/questionTooltip'; @@ -20,8 +21,6 @@ import {decodeScalar} from 'app/utils/queryString'; import {SidebarSpacer} from 'app/views/performance/transactionSummary/utils'; import {SpanOperationBreakdownFilter} from '../filter'; -import TransactionHeader from '../header'; -import Tab from '../tabs'; import {getTransactionField} from '../transactionOverview/tagExplorer'; import TagsDisplay from './tagsDisplay'; @@ -38,9 +37,7 @@ type Props = { type TagOption = string; const TagsPageContent = (props: Props) => { - const {eventView, location, organization, projects, transactionName} = props; - - const handleIncompatibleQuery = () => {}; + const {eventView, location, organization, projects} = props; const aggregateColumn = getTransactionField( SpanOperationBreakdownFilter.None, @@ -49,18 +46,7 @@ const TagsPageContent = (props: Props) => { ); return ( - - - + { return ; }} - + ); }; @@ -276,15 +262,10 @@ const StyledSectionHeading = styled(SectionHeading)` // TODO(k-fish): Adjust thirds layout to allow for this instead. const ReversedLayoutBody = styled('div')` - padding: ${space(2)}; margin: 0; background-color: ${p => p.theme.background}; flex-grow: 1; - @media (min-width: ${p => p.theme.breakpoints[0]}) { - padding: ${space(3)} ${space(4)}; - } - @media (min-width: ${p => p.theme.breakpoints[1]}) { display: grid; grid-template-columns: auto 66%; diff --git a/static/app/views/performance/transactionSummary/transactionTags/index.tsx b/static/app/views/performance/transactionSummary/transactionTags/index.tsx index 6ad6840ec2869c..61e7c3f482d561 100644 --- a/static/app/views/performance/transactionSummary/transactionTags/index.tsx +++ b/static/app/views/performance/transactionSummary/transactionTags/index.tsx @@ -1,24 +1,27 @@ -import {Component} from 'react'; +import {ReactNode, useState} from 'react'; import {browserHistory} from 'react-router'; import styled from '@emotion/styled'; import {Location} from 'history'; import Feature from 'app/components/acl/feature'; import Alert from 'app/components/alert'; +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 {Organization, Project} from 'app/types'; +import {defined} from 'app/utils'; import EventView from 'app/utils/discover/eventView'; import {decodeScalar} from 'app/utils/queryString'; import {MutableSearch} from 'app/utils/tokenizeSearch'; -import withGlobalSelection from 'app/utils/withGlobalSelection'; import withOrganization from 'app/utils/withOrganization'; import withProjects from 'app/utils/withProjects'; import {getTransactionName} from '../../utils'; +import TransactionHeader from '../header'; +import Tab from '../tabs'; import TagsPageContent from './content'; @@ -26,92 +29,69 @@ type Props = { location: Location; organization: Organization; projects: Project[]; - selection: GlobalSelection; }; -type State = { - eventView: EventView | undefined; -}; - -class TransactionTags extends Component { - state: State = { - eventView: generateTagsEventView( - this.props.location, - getTransactionName(this.props.location) - ), - }; - - static getDerivedStateFromProps(nextProps: Readonly, prevState: State): State { - return { - ...prevState, - eventView: generateTagsEventView( - nextProps.location, - getTransactionName(nextProps.location) - ), - }; +function TransactionTags(props: Props) { + const {location, 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; } - getDocumentTitle(): string { - const name = getTransactionName(this.props.location); - - const hasTransactionName = typeof name === 'string' && String(name).trim().length > 0; - - if (hasTransactionName) { - return [String(name).trim(), t('Tags')].join(' \u2014 '); - } - - return [t('Summary'), t('Tags')].join(' \u2014 '); - } + const project = projects.find(p => p.id === projectId); - renderNoAccess = () => { - return {t("You don't have access to this feature")}; + const [incompatibleAlertNotice, setIncompatibleAlertNotice] = useState(null); + const handleIncompatibleQuery = (incompatibleAlertNoticeFn, _errors) => { + const notice = incompatibleAlertNoticeFn(() => setIncompatibleAlertNotice(null)); + setIncompatibleAlertNotice(notice); }; - render() { - const {organization, projects, location} = this.props; - const {eventView} = this.state; - const transactionName = getTransactionName(location); - if (!eventView || transactionName === undefined) { - // 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 shouldForceProject = eventView.project.length === 1; - const forceProject = shouldForceProject - ? projects.find(p => parseInt(p.id, 10) === eventView.project[0]) - : undefined; - const projectSlugs = eventView.project - .map(projectId => projects.find(p => parseInt(p.id, 10) === projectId)) - .filter((p: Project | undefined): p is Project => p !== undefined) - .map(p => p.slug); - - return ( - + - - - - + + + + + {incompatibleAlertNotice && ( + {incompatibleAlertNotice} + )} { organization={organization} projects={projects} /> - - - - - - ); + + + + + + + ); +} + +function getDocumentTitle(transactionName: string): string { + const hasTransactionName = + typeof transactionName === 'string' && String(transactionName).trim().length > 0; + + if (hasTransactionName) { + return [String(transactionName).trim(), t('Tags')].join(' \u2014 '); } + + return [t('Summary'), t('Tags')].join(' \u2014 '); +} + +function NoAccess() { + return {t("You don't have access to this feature")}; } const StyledPageContent = styled(PageContent)` padding: 0; `; -function generateTagsEventView( - location: Location, - transactionName: string | undefined -): EventView | undefined { - if (transactionName === undefined) { - return undefined; - } +function generateEventView(location: Location, transactionName: string): EventView { const query = decodeScalar(location.query.query, ''); const conditions = new MutableSearch(query); const eventView = EventView.fromNewQueryWithLocation( @@ -158,4 +147,4 @@ function generateTagsEventView( return eventView; } -export default withGlobalSelection(withProjects(withOrganization(TransactionTags))); +export default withProjects(withOrganization(TransactionTags)); diff --git a/tests/js/spec/views/performance/transactionTags/index.spec.jsx b/tests/js/spec/views/performance/transactionTags/index.spec.jsx index 3f321d87f384e3..8d231aac17c013 100644 --- a/tests/js/spec/views/performance/transactionTags/index.spec.jsx +++ b/tests/js/spec/views/performance/transactionTags/index.spec.jsx @@ -18,7 +18,7 @@ function initializeData({query} = {query: {}}) { location: { query: { transaction: 'Test Transaction', - project: 1, + project: '1', ...query, }, }, @@ -141,7 +141,7 @@ describe('Performance > Transaction Tags', function () { expect(browserHistory.replace).toHaveBeenCalledWith({ query: { - project: 1, + project: '1', statsPeriod: '14d', tagKey: 'hardwareConcurrency', transaction: 'Test Transaction', @@ -174,7 +174,7 @@ describe('Performance > Transaction Tags', function () { expect(browserHistory.replace).toHaveBeenCalledWith({ query: { - project: 1, + project: '1', statsPeriod: '14d', tagKey: 'hardwareConcurrency', transaction: 'Test Transaction', @@ -214,7 +214,7 @@ describe('Performance > Transaction Tags', function () { expect(browserHistory.replace).toHaveBeenCalledWith({ query: { - project: 1, + project: '1', statsPeriod: '14d', tagKey: 'effectiveConnectionType', transaction: 'Test Transaction',