pageLayout.tsx 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import {useState} from 'react';
  2. import {browserHistory} from 'react-router';
  3. import styled from '@emotion/styled';
  4. import {Location} from 'history';
  5. import Feature from 'sentry/components/acl/feature';
  6. import {Alert} from 'sentry/components/alert';
  7. import * as Layout from 'sentry/components/layouts/thirds';
  8. import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
  9. import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
  10. import {Tabs} from 'sentry/components/tabs';
  11. import {t} from 'sentry/locale';
  12. import {Organization, Project} from 'sentry/types';
  13. import {defined} from 'sentry/utils';
  14. import EventView from 'sentry/utils/discover/eventView';
  15. import {useMetricsCardinalityContext} from 'sentry/utils/performance/contexts/metricsCardinality';
  16. import {PerformanceEventViewProvider} from 'sentry/utils/performance/contexts/performanceEventViewContext';
  17. import {decodeScalar} from 'sentry/utils/queryString';
  18. import {normalizeUrl} from 'sentry/utils/withDomainRequired';
  19. import {getTransactionName} from '../../utils';
  20. import TransactionHeader from '../header';
  21. import usePageTabs from '../pageLayout/usePageTabs';
  22. import {TransactionThresholdMetric} from '../transactionThresholdModal';
  23. import Tab from './tabs';
  24. type Props = {
  25. children: React.ReactNode;
  26. organization: Organization;
  27. project: undefined | Project;
  28. tab: Tab;
  29. title: string;
  30. };
  31. function PageLayout({children, tab, title, organization, project}: Props) {
  32. return (
  33. <SentryDocumentTitle
  34. title={title}
  35. orgSlug={organization.slug}
  36. projectSlug={project?.slug}
  37. >
  38. <Feature
  39. features={['performance-view', ...features]}
  40. organization={organization}
  41. renderDisabled={NoAccess}
  42. >
  43. <PerformanceEventViewProvider value={{eventView}}>
  44. <PageFiltersContainer
  45. shouldForceProject={defined(project)}
  46. forceProject={project}
  47. specificProjectSlugs={defined(project) ? [project.slug] : []}
  48. >
  49. <Tabs value={tab} onChange={onTabChange}>
  50. <Layout.Page>
  51. <TransactionHeader
  52. eventView={eventView}
  53. location={location}
  54. organization={organization}
  55. projects={projects}
  56. projectId={projectId}
  57. transactionName={transactionName}
  58. currentTab={tab}
  59. hasWebVitals={tab === Tab.WebVitals ? 'yes' : 'maybe'}
  60. onChangeThreshold={(threshold, metric) => {
  61. setTransactionThreshold(threshold);
  62. setTransactionThresholdMetric(metric);
  63. }}
  64. metricsCardinality={metricsCardinality}
  65. />
  66. <Layout.Body>
  67. {defined(error) && (
  68. <StyledAlert type="error" showIcon>
  69. {error}
  70. </StyledAlert>
  71. )}
  72. {children}
  73. </Layout.Body>
  74. </Layout.Page>
  75. </Tabs>
  76. </PageFiltersContainer>
  77. </PerformanceEventViewProvider>
  78. </Feature>
  79. </SentryDocumentTitle>
  80. );
  81. }
  82. function NoAccess() {
  83. return <Alert type="warning">{t("You don't have access to this feature")}</Alert>;
  84. }
  85. const StyledAlert = styled(Alert)`
  86. grid-column: 1/3;
  87. margin: 0;
  88. `;
  89. export default PageLayout;