disabledPerformancePage.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import DemoSandboxButton from 'sentry/components/demoSandboxButton';
  4. import List from 'sentry/components/list';
  5. import ListItem from 'sentry/components/list/listItem';
  6. import {IconBusiness} from 'sentry/icons';
  7. import {t, tct} from 'sentry/locale';
  8. import type {Organization} from 'sentry/types/organization';
  9. import PerformanceBackground from './illustrations/performanceBackground';
  10. import PageUpsellOverlay from './pageUpsellOverlay';
  11. type Props = React.PropsWithChildren<{
  12. features: string[];
  13. organization: Organization;
  14. }>;
  15. const TextWrapper = styled('div')`
  16. width: 550px;
  17. `;
  18. function DisabledPerformancePage({
  19. organization,
  20. children: _children,
  21. features,
  22. ...props
  23. }: Props) {
  24. const requiredPlan = tct(
  25. `You'll need to migrate to a new plan with [strong:Transactions] to access Performance.`,
  26. {
  27. strong: <strong />,
  28. }
  29. );
  30. const description = (
  31. <Fragment>
  32. <p>
  33. {t(
  34. 'Load times getting longer? Visitors losing patience? Customers grabbing pitchforks? We’ll help. '
  35. )}
  36. </p>
  37. <FeatureList
  38. symbol={<IconBusiness size="sm" />}
  39. data-test-id="performance-feature-list"
  40. >
  41. <ListItem>{t('Visualize latency percentiles')}</ListItem>
  42. <ListItem>{t('Sort by apdex & throughput')}</ListItem>
  43. <ListItem>{t('Monitor user misery')}</ListItem>
  44. <ListItem>{t('See related issues')}</ListItem>
  45. </FeatureList>
  46. </Fragment>
  47. );
  48. const SandboxButton = organization.features.includes('sandbox-kill-switch') ? null : (
  49. <DemoSandboxButton
  50. scenario="oneTransaction"
  51. projectSlug="react"
  52. size="sm"
  53. clientData={{
  54. skipEmail: true,
  55. cta: {
  56. id: 'disabled-performance-page',
  57. title: t('Upgrade Now'),
  58. shortTitle: t('Upgrade'),
  59. url: new URL(
  60. `/settings/${organization.slug}/billing/checkout/`,
  61. window.location.origin
  62. ).toString(),
  63. },
  64. }}
  65. >
  66. {t('See a Sample Transaction')}
  67. </DemoSandboxButton>
  68. );
  69. return (
  70. <PageUpsellOverlay
  71. name={t('Spot slowdowns')}
  72. source="performance-view"
  73. description={description}
  74. data-test-id="mock-performance-page"
  75. organization={organization}
  76. requiredPlan={requiredPlan}
  77. features={features}
  78. background={PerformanceBackground}
  79. customWrapper={TextWrapper}
  80. customSecondaryCTA={SandboxButton}
  81. positioningStrategy={({mainRect, anchorRect, wrapperRect}) => {
  82. let y = anchorRect.y - mainRect.y - wrapperRect.height;
  83. // Center within the anchor on the x axis, until the wrapper is larger
  84. // than the anchor, then align the wrapper to the right within anchor.
  85. let x =
  86. (anchorRect.width - wrapperRect.width) /
  87. (anchorRect.width > wrapperRect.width ? 2 : 1) +
  88. anchorRect.x -
  89. mainRect.x;
  90. // Avoid overflowing onto the left of the page
  91. x = Math.max(30, x);
  92. // Avoid cutting off the top on smaller screens
  93. y = Math.max(30, y);
  94. return {x, y};
  95. }}
  96. {...props}
  97. />
  98. );
  99. }
  100. const FeatureList = styled(List)`
  101. display: grid;
  102. grid-template-columns: 1fr 1fr;
  103. `;
  104. export default DisabledPerformancePage;