Просмотр исходного кода

ref(project-creation): Convert overview from class to func (#49303)

Priscila Oliveira 1 год назад
Родитель
Сommit
9a048570c5
2 измененных файлов с 121 добавлено и 113 удалено
  1. 16 2
      static/app/routes.tsx
  2. 105 111
      static/app/views/projectInstall/overview.tsx

+ 16 - 2
static/app/routes.tsx

@@ -1024,7 +1024,14 @@ function buildRoutes() {
         component={make(() => import('sentry/views/projectInstall/gettingStarted'))}
       >
         <IndexRoute
-          component={make(() => import('sentry/views/projectInstall/overview'))}
+          component={make(async () => {
+            const {ProjectInstallOverview} = await import(
+              'sentry/views/projectInstall/overview'
+            );
+            return {
+              default: ProjectInstallOverview,
+            };
+          })}
         />
         <Route
           path=":platform/"
@@ -1991,7 +1998,14 @@ function buildRoutes() {
   const gettingStartedChildRoutes = (
     <Fragment>
       <IndexRoute
-        component={make(() => import('sentry/views/projectInstall/overview'))}
+        component={make(async () => {
+          const {ProjectInstallOverview} = await import(
+            'sentry/views/projectInstall/overview'
+          );
+          return {
+            default: ProjectInstallOverview,
+          };
+        })}
       />
       <Route
         path=":platform/"

+ 105 - 111
static/app/views/projectInstall/overview.tsx

@@ -1,139 +1,135 @@
+import {useCallback, useState} from 'react';
 import {browserHistory, RouteComponentProps} from 'react-router';
 import styled from '@emotion/styled';
 
-import AsyncComponent from 'sentry/components/asyncComponent';
 import AutoSelectText from 'sentry/components/autoSelectText';
 import {Button} from 'sentry/components/button';
 import ExternalLink from 'sentry/components/links/externalLink';
+import LoadingError from 'sentry/components/loadingError';
+import LoadingIndicator from 'sentry/components/loadingIndicator';
 import PlatformPicker, {PLATFORM_CATEGORIES} from 'sentry/components/platformPicker';
 import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
 import {PlatformKey} from 'sentry/data/platformCategories';
 import platforms from 'sentry/data/platforms';
 import {t, tct} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
-import {Organization, Project} from 'sentry/types';
+import {useApiQuery} from 'sentry/utils/queryClient';
 import recreateRoute from 'sentry/utils/recreateRoute';
+import useOrganization from 'sentry/utils/useOrganization';
+import useProjects from 'sentry/utils/useProjects';
 import {normalizeUrl} from 'sentry/utils/withDomainRequired';
-import withOrganization from 'sentry/utils/withOrganization';
-import withProjects from 'sentry/utils/withProjects';
 import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader';
 import TextBlock from 'sentry/views/settings/components/text/textBlock';
 import {ProjectKey} from 'sentry/views/settings/project/projectKeys/types';
 
-type Props = RouteComponentProps<{projectId: string}, {}> & {
-  organization: Organization;
-  projects: Project[];
-} & AsyncComponent['props'];
-
-type State = {
-  keyList: Array<ProjectKey> | null;
-} & AsyncComponent['state'];
-
-class ProjectInstallOverview extends AsyncComponent<Props, State> {
-  get isGettingStarted() {
-    return window.location.href.indexOf('getting-started') > 0;
+type Props = RouteComponentProps<{projectId: string}, {}>;
+
+export function ProjectInstallOverview({params, routes, location}: Props) {
+  const [showDsn, setShowDsn] = useState(false);
+  const {projectId: projectSlug} = params;
+  const organization = useOrganization();
+  const {projects} = useProjects();
+
+  const issueStreamLink = `/organizations/${organization.slug}/issues/#welcome`;
+  const isGettingStarted = window.location.href.indexOf('getting-started') > 0;
+
+  const project = projects.find(p => p.slug === projectSlug);
+  const platform = project ? platforms.find(p => p.id === project.platform) : undefined;
+  const category = PLATFORM_CATEGORIES.find(c =>
+    c.platforms?.some(p => p === platform?.id)
+  )?.id;
+
+  const {
+    data: keyList,
+    isLoading,
+    isError,
+    refetch,
+  } = useApiQuery<ProjectKey[]>([`/projects/${organization.slug}/${projectSlug}/keys/`], {
+    staleTime: Infinity,
+  });
+
+  const redirectToDocs = useCallback(
+    (platformKey: PlatformKey | null) => {
+      const installUrl = isGettingStarted
+        ? `/organizations/${organization.slug}/projects/${projectSlug}/getting-started/${platformKey}/`
+        : recreateRoute(`${platformKey}/`, {
+            routes,
+            location,
+            params,
+            stepBack: -1,
+          });
+
+      browserHistory.push(normalizeUrl(installUrl));
+    },
+    [projectSlug, isGettingStarted, organization.slug, routes, location, params]
+  );
+
+  if (isLoading) {
+    return <LoadingIndicator />;
   }
 
-  getEndpoints(): ReturnType<AsyncComponent['getEndpoints']> {
-    const {organization} = this.props;
-    const {projectId} = this.props.params;
-    return [['keyList', `/projects/${organization.slug}/${projectId}/keys/`]];
+  if (isError) {
+    return <LoadingError onRetry={refetch} />;
   }
 
-  redirectToDocs = (platform: PlatformKey | null) => {
-    const {organization} = this.props;
-    const {projectId} = this.props.params;
-
-    const installUrl = this.isGettingStarted
-      ? `/organizations/${organization.slug}/projects/${projectId}/getting-started/${platform}/`
-      : recreateRoute(`${platform}/`, {
-          ...this.props,
-          stepBack: -1,
-        });
-
-    browserHistory.push(normalizeUrl(installUrl));
-  };
-
-  toggleDsn = () => {
-    this.setState(state => ({showDsn: !state.showDsn}));
-  };
-
-  render() {
-    const {organization, projects} = this.props;
-    const {projectId} = this.props.params;
-    const {keyList, showDsn} = this.state;
-
-    const issueStreamLink = `/organizations/${organization.slug}/issues/#welcome`;
-
-    const project = projects.find(p => p.slug === projectId);
-    const platform = project ? platforms.find(p => p.id === project.platform) : undefined;
-    const category = PLATFORM_CATEGORIES.find(c =>
-      c.platforms?.some(p => p === platform?.id)
-    )?.id;
-
-    return (
-      <div>
-        <SentryDocumentTitle title={t('Instrumentation')} projectSlug={projectId} />
-        <SettingsPageHeader title={t('Configure your application')} />
-        <TextBlock>
-          {t(
-            'Get started by selecting the platform or language that powers your application.'
-          )}
-        </TextBlock>
-
-        {showDsn ? (
-          <DsnInfo>
-            <DsnContainer>
-              <strong>{t('DSN')}</strong>
-              <DsnValue>{keyList?.[0].dsn.public}</DsnValue>
-            </DsnContainer>
-
-            <Button priority="primary" to={issueStreamLink}>
-              {t('Got it! Take me to the Issue Stream.')}
-            </Button>
-          </DsnInfo>
-        ) : (
-          <p>
-            <small>
-              {tct('Already have things setup? [link:Get your DSN]', {
-                link: (
-                  <Button
-                    priority="link"
-                    onClick={this.toggleDsn}
-                    aria-label={t('Get your DSN')}
-                  />
-                ),
-              })}
-              .
-            </small>
-          </p>
+  return (
+    <div>
+      <SentryDocumentTitle title={t('Instrumentation')} projectSlug={projectSlug} />
+      <SettingsPageHeader title={t('Configure your application')} />
+      <TextBlock>
+        {t(
+          'Get started by selecting the platform or language that powers your application.'
         )}
-        <PlatformPicker
-          setPlatform={selectedPlatform =>
-            this.redirectToDocs(selectedPlatform?.id ?? null)
-          }
-          showOther={false}
-          organization={this.props.organization}
-          defaultCategory={category}
-          platform={platform?.id}
-        />
+      </TextBlock>
+
+      {showDsn ? (
+        <DsnInfo>
+          <DsnContainer>
+            <strong>{t('DSN')}</strong>
+            <DsnValue>
+              <AutoSelectText>{keyList?.[0].dsn.public}</AutoSelectText>
+            </DsnValue>
+          </DsnContainer>
+
+          <Button priority="primary" to={issueStreamLink}>
+            {t('Got it! Take me to the Issue Stream.')}
+          </Button>
+        </DsnInfo>
+      ) : (
         <p>
-          {tct(
-            `For a complete list of client integrations, please see
-             [docLink:our in-depth documentation].`,
-            {docLink: <ExternalLink href="https://docs.sentry.io" />}
-          )}
+          <small>
+            {tct('Already have things setup? [link:Get your DSN]', {
+              link: (
+                <Button
+                  priority="link"
+                  onClick={() => setShowDsn(!showDsn)}
+                  aria-label={t('Get your DSN')}
+                />
+              ),
+            })}
+            .
+          </small>
         </p>
-      </div>
-    );
-  }
+      )}
+      <PlatformPicker
+        setPlatform={selectedPlatform => redirectToDocs(selectedPlatform?.id ?? null)}
+        showOther={false}
+        organization={organization}
+        defaultCategory={category}
+        platform={platform?.id}
+      />
+      <p>
+        {tct(
+          `For a complete list of client integrations, please see
+             [docLink:our in-depth documentation].`,
+          {docLink: <ExternalLink href="https://docs.sentry.io" />}
+        )}
+      </p>
+    </div>
+  );
 }
 
-const DsnValue = styled(p => (
-  <code {...p}>
-    <AutoSelectText>{p.children}</AutoSelectText>
-  </code>
-))`
+const DsnValue = styled('code')`
   overflow: hidden;
 `;
 
@@ -148,5 +144,3 @@ const DsnContainer = styled('div')`
   align-items: center;
   margin-bottom: ${space(2)};
 `;
-
-export default withOrganization(withProjects(ProjectInstallOverview));