setupDocs.tsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import {Fragment, useCallback, useEffect, useMemo, useState} from 'react';
  2. import styled from '@emotion/styled';
  3. import {motion} from 'framer-motion';
  4. import {SdkDocumentation} from 'sentry/components/onboarding/gettingStartedDoc/sdkDocumentation';
  5. import type {ProductSolution} from 'sentry/components/onboarding/productSelection';
  6. import platforms, {otherPlatform} from 'sentry/data/platforms';
  7. import {t} from 'sentry/locale';
  8. import {space} from 'sentry/styles/space';
  9. import {trackAnalytics} from 'sentry/utils/analytics';
  10. import {browserHistory} from 'sentry/utils/browserHistory';
  11. import {platformToIntegrationMap} from 'sentry/utils/integrationUtil';
  12. import {decodeList} from 'sentry/utils/queryString';
  13. import useOrganization from 'sentry/utils/useOrganization';
  14. import SetupIntroduction from 'sentry/views/onboarding/components/setupIntroduction';
  15. import {SetupDocsLoader} from 'sentry/views/onboarding/setupDocsLoader';
  16. import {OtherPlatformsInfo} from 'sentry/views/projectInstall/otherPlatformsInfo';
  17. import FirstEventFooter from './components/firstEventFooter';
  18. import IntegrationSetup from './integrationSetup';
  19. import type {StepProps} from './types';
  20. function SetupDocs({location, recentCreatedProject: project}: StepProps) {
  21. const organization = useOrganization();
  22. const [integrationUseManualSetup, setIntegrationUseManualSetup] = useState(false);
  23. const products = useMemo<ProductSolution[]>(
  24. () => decodeList(location.query.product ?? []) as ProductSolution[],
  25. [location.query.product]
  26. );
  27. const currentPlatformKey = project?.platform ?? 'other';
  28. const currentPlatform =
  29. platforms.find(p => p.id === currentPlatformKey) ?? otherPlatform;
  30. const [showLoaderOnboarding, setShowLoaderOnboarding] = useState(
  31. currentPlatformKey === 'javascript'
  32. );
  33. useEffect(() => {
  34. setShowLoaderOnboarding(currentPlatformKey === 'javascript');
  35. }, [currentPlatformKey]);
  36. const hideLoaderOnboarding = useCallback(() => {
  37. setShowLoaderOnboarding(false);
  38. if (!project?.id) {
  39. return;
  40. }
  41. trackAnalytics('onboarding.js_loader_npm_docs_shown', {
  42. organization,
  43. platform: currentPlatformKey,
  44. project_id: project?.id,
  45. });
  46. }, [organization, currentPlatformKey, project?.id]);
  47. if (!project || !currentPlatform) {
  48. return null;
  49. }
  50. const platformName = currentPlatform?.name ?? '';
  51. const integrationSlug = project?.platform && platformToIntegrationMap[project.platform];
  52. const showIntegrationOnboarding = integrationSlug && !integrationUseManualSetup;
  53. return (
  54. <Fragment>
  55. <Wrapper>
  56. <MainContent>
  57. {showIntegrationOnboarding ? (
  58. <IntegrationSetup
  59. integrationSlug={integrationSlug}
  60. project={project}
  61. onClickManualSetup={() => {
  62. setIntegrationUseManualSetup(true);
  63. }}
  64. />
  65. ) : (
  66. <Fragment>
  67. <SetupIntroduction
  68. stepHeaderText={t('Configure %s SDK', platformName)}
  69. platform={currentPlatformKey}
  70. />
  71. {currentPlatformKey === 'other' ? (
  72. <OtherPlatformsInfo
  73. projectSlug={project.slug}
  74. platform={currentPlatform.name}
  75. />
  76. ) : showLoaderOnboarding ? (
  77. <SetupDocsLoader
  78. organization={organization}
  79. project={project}
  80. location={location}
  81. platform={currentPlatform.id}
  82. close={hideLoaderOnboarding}
  83. />
  84. ) : (
  85. <SdkDocumentation
  86. platform={currentPlatform}
  87. organization={organization}
  88. projectSlug={project.slug}
  89. projectId={project.id}
  90. activeProductSelection={products}
  91. newOrg
  92. />
  93. )}
  94. </Fragment>
  95. )}
  96. </MainContent>
  97. </Wrapper>
  98. <FirstEventFooter
  99. project={project}
  100. organization={organization}
  101. isLast
  102. onClickSetupLater={() => {
  103. const orgIssuesURL = `/organizations/${organization.slug}/issues/?project=${project.id}&referrer=onboarding-setup-docs`;
  104. trackAnalytics('growth.onboarding_clicked_setup_platform_later', {
  105. organization,
  106. platform: currentPlatformKey,
  107. project_id: project.id,
  108. });
  109. browserHistory.push(orgIssuesURL);
  110. }}
  111. />
  112. </Fragment>
  113. );
  114. }
  115. export default SetupDocs;
  116. const AnimatedContentWrapper = styled(motion.div)`
  117. overflow: hidden;
  118. `;
  119. AnimatedContentWrapper.defaultProps = {
  120. initial: {
  121. height: 0,
  122. },
  123. animate: {
  124. height: 'auto',
  125. },
  126. exit: {
  127. height: 0,
  128. },
  129. };
  130. const DocsWrapper = styled(motion.div)``;
  131. DocsWrapper.defaultProps = {
  132. initial: {opacity: 0, y: 40},
  133. animate: {opacity: 1, y: 0},
  134. exit: {opacity: 0},
  135. };
  136. const Wrapper = styled('div')`
  137. display: flex;
  138. flex-direction: row;
  139. margin: ${space(2)};
  140. justify-content: center;
  141. `;
  142. const MainContent = styled('div')`
  143. max-width: 850px;
  144. min-width: 0;
  145. flex-grow: 1;
  146. `;