usePerformanceOnboardingDocs.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import {useEffect, useState} from 'react';
  2. import * as Sentry from '@sentry/react';
  3. import {loadDocs} from 'sentry/actionCreators/projects';
  4. import {
  5. PlatformKey,
  6. withoutPerformanceSupport,
  7. withPerformanceOnboarding,
  8. } from 'sentry/data/platformCategories';
  9. import platforms from 'sentry/data/platforms';
  10. import {Project} from 'sentry/types';
  11. import useApi from 'sentry/utils/useApi';
  12. import useOrganization from 'sentry/utils/useOrganization';
  13. export function generateOnboardingDocKeys(platform: PlatformKey): string[] {
  14. return ['1-install', '2-configure', '3-verify'].map(
  15. key => `${platform}-performance-onboarding-${key}`
  16. );
  17. }
  18. const INITIAL_LOADING_DOCS = {};
  19. const INITIAL_DOC_CONTENTS = {};
  20. function usePerformanceOnboardingDocs(project: Project) {
  21. const organization = useOrganization();
  22. const api = useApi();
  23. const [loadingDocs, setLoadingDocs] =
  24. useState<Record<string, boolean>>(INITIAL_LOADING_DOCS);
  25. const [docContents, setDocContents] =
  26. useState<Record<string, string>>(INITIAL_DOC_CONTENTS);
  27. const currentPlatform = project.platform
  28. ? platforms.find(p => p.id === project.platform)
  29. : undefined;
  30. const hasPerformanceOnboarding = currentPlatform
  31. ? withPerformanceOnboarding.has(currentPlatform.id)
  32. : false;
  33. const doesNotSupportPerformance = currentPlatform
  34. ? withoutPerformanceSupport.has(currentPlatform.id)
  35. : false;
  36. useEffect(() => {
  37. if (!currentPlatform || !hasPerformanceOnboarding || doesNotSupportPerformance) {
  38. if (loadingDocs !== INITIAL_LOADING_DOCS) {
  39. setLoadingDocs(INITIAL_LOADING_DOCS);
  40. }
  41. if (docContents !== INITIAL_DOC_CONTENTS) {
  42. setDocContents(INITIAL_DOC_CONTENTS);
  43. }
  44. return;
  45. }
  46. const docKeys = generateOnboardingDocKeys(currentPlatform.id);
  47. docKeys.forEach(docKey => {
  48. if (docKey in loadingDocs) {
  49. // If a documentation content is loading, we should not attempt to fetch it again.
  50. // otherwise, if it's not loading, we should only fetch at most once.
  51. // Any errors that occurred will be captured via Sentry.
  52. return;
  53. }
  54. const setLoadingDoc = (loadingState: boolean) =>
  55. setLoadingDocs(prevState => {
  56. return {
  57. ...prevState,
  58. [docKey]: loadingState,
  59. };
  60. });
  61. const setDocContent = (docContent: string | undefined) =>
  62. setDocContents(prevState => {
  63. if (docContent === undefined) {
  64. const newState = {
  65. ...prevState,
  66. };
  67. delete newState[docKey];
  68. return newState;
  69. }
  70. return {
  71. ...prevState,
  72. [docKey]: docContent,
  73. };
  74. });
  75. setLoadingDoc(true);
  76. loadDocs(api, organization.slug, project.slug, docKey as any)
  77. .then(({html}) => {
  78. setDocContent(html as string);
  79. setLoadingDoc(false);
  80. })
  81. .catch(error => {
  82. Sentry.captureException(error);
  83. setDocContent(undefined);
  84. setLoadingDoc(false);
  85. });
  86. });
  87. }, [
  88. currentPlatform,
  89. hasPerformanceOnboarding,
  90. doesNotSupportPerformance,
  91. api,
  92. loadingDocs,
  93. organization.slug,
  94. project.slug,
  95. docContents,
  96. ]);
  97. if (!currentPlatform || !hasPerformanceOnboarding || doesNotSupportPerformance) {
  98. return {
  99. isLoading: false,
  100. hasOnboardingContents: false,
  101. docContents: {},
  102. };
  103. }
  104. const docKeys = generateOnboardingDocKeys(currentPlatform.id);
  105. const isLoading = docKeys.some(key => {
  106. if (key in loadingDocs) {
  107. return !!loadingDocs[key];
  108. }
  109. return true;
  110. });
  111. const hasOnboardingContents = docKeys.every(
  112. key => typeof docContents[key] === 'string'
  113. );
  114. return {
  115. isLoading,
  116. hasOnboardingContents,
  117. docContents,
  118. };
  119. }
  120. export default usePerformanceOnboardingDocs;