orgStatsBanner.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import styled from '@emotion/styled';
  2. import {Button} from 'sentry/components/button';
  3. import Panel from 'sentry/components/panels/panel';
  4. import {t, tct} from 'sentry/locale';
  5. import {space} from 'sentry/styles/space';
  6. import type {Organization} from 'sentry/types/organization';
  7. import TextBlock from 'sentry/views/settings/components/text/textBlock';
  8. import {openUpsellModal} from 'getsentry/actionCreators/modal';
  9. import AddEventsCTA from 'getsentry/components/addEventsCTA';
  10. import withSubscription from 'getsentry/components/withSubscription';
  11. import type {Subscription} from 'getsentry/types';
  12. import {
  13. getBestActionToIncreaseEventLimits,
  14. hasPerformance,
  15. } from 'getsentry/utils/billing';
  16. import {ButtonWrapper, SubscriptionBody} from 'getsentry/views/subscriptionPage/styles';
  17. import TrialBadge from 'getsentry/views/subscriptionPage/trial/badge';
  18. type Props = {
  19. organization: Organization;
  20. subscription: Subscription;
  21. referrer?: string;
  22. };
  23. function OrgStatsBanner({organization, subscription, referrer}: Props) {
  24. if (!subscription.canSelfServe || !hasPerformance(subscription.planDetails)) {
  25. return null;
  26. }
  27. referrer = referrer || 'org-stats';
  28. const props = {
  29. organization,
  30. subscription,
  31. referrer,
  32. source: referrer,
  33. buttonProps: {
  34. size: 'sm' as const,
  35. },
  36. };
  37. const isPaidPlan = subscription.planDetails.price > 0;
  38. // only show start trial if on a free plan and trial available
  39. const showStartTrial = !isPaidPlan && subscription.canTrial;
  40. const getTextContent = (): [string | JSX.Element, string | JSX.Element] => {
  41. const action = getBestActionToIncreaseEventLimits(organization, subscription);
  42. switch (action) {
  43. case 'start_trial':
  44. return [
  45. t('Try Sentry Business for Free'),
  46. t("Activate your trial to take advantage of Sentry's Business plan features."),
  47. ];
  48. case 'add_events':
  49. return [
  50. t('Increase your Reserved Quotas'),
  51. t('Increase your reserved limits, because no one likes dropped data.'),
  52. ];
  53. case 'request_add_events':
  54. return [
  55. t('Request an Increase to Reserved Limits'),
  56. t('Bump your Organization’s owner to bump your limits.'),
  57. ];
  58. case 'request_upgrade':
  59. return [
  60. t('Request an Upgrade to Business'),
  61. tct(
  62. '[italicized] your Organization’s owner to upgrade Sentry (See what I did there?).',
  63. {
  64. italicized: <i>{t('Bug')}</i>,
  65. }
  66. ),
  67. ];
  68. case 'send_to_checkout':
  69. default:
  70. return [
  71. t('Upgrade to Business'),
  72. t(
  73. 'Advanced integrations, deep insights, custom dashboards, and more. Upgrade to Sentry’s Business plan today.'
  74. ),
  75. ];
  76. }
  77. };
  78. const [headerText, subText] = getTextContent();
  79. return (
  80. <Panel>
  81. <SubscriptionBody withPadding>
  82. <TextWrapper>
  83. <HeaderWrapper>
  84. <Heading>{headerText}</Heading>
  85. {showStartTrial && (
  86. <TrialBadge subscription={subscription} organization={organization} />
  87. )}
  88. </HeaderWrapper>
  89. <SubText>{subText}</SubText>
  90. </TextWrapper>
  91. <ButtonWrapper gap={1}>
  92. {!isPaidPlan && (
  93. <Button
  94. size="sm"
  95. onClick={() =>
  96. openUpsellModal({organization, source: `${referrer}.banner`})
  97. }
  98. >
  99. {t('Learn More')}
  100. </Button>
  101. )}
  102. <AddEventsCTA {...props} />
  103. </ButtonWrapper>
  104. </SubscriptionBody>
  105. </Panel>
  106. );
  107. }
  108. const Heading = styled('span')`
  109. font-weight: 400;
  110. font-size: ${p => p.theme.fontSizeExtraLarge};
  111. margin-right: ${space(1)};
  112. `;
  113. const SubText = styled(TextBlock)`
  114. color: ${p => p.theme.subText};
  115. margin: 0;
  116. `;
  117. const TextWrapper = styled('div')`
  118. display: grid;
  119. grid-auto-rows: auto;
  120. gap: ${space(1)};
  121. `;
  122. const HeaderWrapper = styled('div')`
  123. display: flex;
  124. `;
  125. export default withSubscription(OrgStatsBanner, {noLoader: true});