index.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import {css} from '@emotion/react';
  2. import styled from '@emotion/styled';
  3. import type {ModalRenderProps} from 'sentry/actionCreators/modal';
  4. import ErrorBoundary from 'sentry/components/errorBoundary';
  5. import HighlightModalContainer from 'sentry/components/highlightModalContainer';
  6. import ExternalLink from 'sentry/components/links/externalLink';
  7. import List from 'sentry/components/list';
  8. import ListItem from 'sentry/components/list/listItem';
  9. import {t} from 'sentry/locale';
  10. import {space} from 'sentry/styles/space';
  11. import type {Organization} from 'sentry/types/organization';
  12. import type {Plan, PreviewData, Subscription} from 'getsentry/types';
  13. import type {AM2UpdateSurfaces} from 'getsentry/utils/trackGetsentryAnalytics';
  14. import ActionButtons from './actionButtons';
  15. import PlanTable from './planTable';
  16. import type {Reservations} from './types';
  17. import useLogUpgradeNowViewed from './useLogUpgradeNowViewed';
  18. type Props = ModalRenderProps & {
  19. organization: Organization;
  20. plan: Plan;
  21. previewData: PreviewData;
  22. reservations: Reservations;
  23. subscription: Subscription;
  24. surface: AM2UpdateSurfaces;
  25. isActionDisabled?: boolean;
  26. onComplete?: () => void;
  27. };
  28. function UpgradeNowModal({
  29. isActionDisabled,
  30. onComplete,
  31. organization,
  32. plan,
  33. previewData,
  34. reservations,
  35. subscription,
  36. surface,
  37. }: Props) {
  38. useLogUpgradeNowViewed({
  39. hasPriceChange: previewData.billedAmount !== 0,
  40. organization,
  41. subscription,
  42. surface,
  43. });
  44. return (
  45. <HighlightModalContainer>
  46. <ModalLayout>
  47. <UpsellContent>
  48. <SubheaderPrimary>{t('Updates to Sentry')}</SubheaderPrimary>
  49. <Header>{t('Performance that scales & Session Replay')}</Header>
  50. <p>
  51. {t(
  52. 'Get full visibility into the performance and stability of your application'
  53. )}
  54. </p>
  55. <List symbol="bullet">
  56. <ListItem>
  57. <ExternalLink href="https://docs.sentry.io/product/performance/performance-at-scale/">
  58. {t('Dynamically sample performance events at scale*')}
  59. </ExternalLink>
  60. </ListItem>
  61. <ListItem>{t('Automatically discard health check transactions')}</ListItem>
  62. <ListItem>
  63. {t(
  64. 'Video-like reproduction of user sessions to get to the root cause faster.'
  65. )}
  66. </ListItem>
  67. </List>
  68. <ActionButtons
  69. isActionDisabled={isActionDisabled}
  70. onComplete={onComplete}
  71. organization={organization}
  72. plan={plan}
  73. previewData={previewData}
  74. reservations={reservations}
  75. subscription={subscription}
  76. surface={surface}
  77. />
  78. <Note>
  79. {t(
  80. '* Dynamic sampling kicks in for customers reserving 1M or more performance units a month'
  81. )}
  82. </Note>
  83. </UpsellContent>
  84. <div>
  85. <Subheader>{t('Plan Volume')}</Subheader>
  86. <ErrorBoundary mini>
  87. <PlanTable
  88. organization={organization}
  89. previewData={previewData}
  90. reservations={reservations}
  91. subscription={subscription}
  92. />
  93. </ErrorBoundary>
  94. </div>
  95. </ModalLayout>
  96. </HighlightModalContainer>
  97. );
  98. }
  99. const Subheader = styled('h2')`
  100. text-transform: uppercase;
  101. font-weight: bold;
  102. font-size: ${p => p.theme.fontSizeSmall};
  103. margin-bottom: ${space(1)};
  104. `;
  105. const SubheaderPrimary = styled(Subheader)`
  106. color: ${p => p.theme.purple300};
  107. `;
  108. const Header = styled('h1')`
  109. font-size: ${p => p.theme.headerFontSize};
  110. font-weight: bold;
  111. margin: ${space(1)} 0;
  112. `;
  113. const ModalLayout = styled('div')`
  114. display: grid;
  115. font-size: ${p => p.theme.fontSizeMedium};
  116. margin-bottom: ${space(2)};
  117. @media (min-width: ${p => p.theme.breakpoints.small}) {
  118. grid-template-columns: 1fr auto;
  119. gap: ${space(3)};
  120. }
  121. `;
  122. const UpsellContent = styled('div')`
  123. grid-column: 1;
  124. grid-row: 1;
  125. font-size: ${p => p.theme.fontSizeLarge};
  126. `;
  127. const Note = styled('p')`
  128. color: ${p => p.theme.gray300};
  129. font-size: ${p => p.theme.fontSizeExtraSmall};
  130. `;
  131. export const modalCss = css`
  132. width: 100%;
  133. max-width: 980px;
  134. [role='document'] {
  135. position: relative;
  136. padding: 80px;
  137. overflow: hidden;
  138. }
  139. `;
  140. export default UpgradeNowModal;