Browse Source

ref(settings-relay): Convert to functional component (#73104)

Priscila Oliveira 8 months ago
parent
commit
8c5fc4fe27

+ 1 - 1
static/app/views/settings/organizationRelay/emptyState.tsx

@@ -5,7 +5,7 @@ import {t} from 'sentry/locale';
 function EmptyState() {
   return (
     <Panel>
-      <EmptyMessage>{t('No Keys Registered.')}</EmptyMessage>
+      <EmptyMessage>{t('No Keys Registered')}</EmptyMessage>
     </Panel>
   );
 }

+ 3 - 3
static/app/views/settings/organizationRelay/index.tsx

@@ -5,9 +5,9 @@ import PanelBody from 'sentry/components/panels/panelBody';
 import {t} from 'sentry/locale';
 import useOrganization from 'sentry/utils/useOrganization';
 
-import RelayWrapper from './relayWrapper';
+import {RelayWrapper} from './relayWrapper';
 
-function OrganizationRelay(props: Omit<RelayWrapper['props'], 'organization'>) {
+function OrganizationRelay() {
   const organization = useOrganization();
   return (
     <Feature
@@ -26,7 +26,7 @@ function OrganizationRelay(props: Omit<RelayWrapper['props'], 'organization'>) {
         </Panel>
       )}
     >
-      <RelayWrapper organization={organization} {...props} />
+      <RelayWrapper />
     </Feature>
   );
 }

+ 141 - 156
static/app/views/settings/organizationRelay/relayWrapper.tsx

@@ -1,18 +1,20 @@
-import {Fragment} from 'react';
-import type {RouteComponentProps} from 'react-router';
-import isEqual from 'lodash/isEqual';
+import {useCallback, useState} from 'react';
 import omit from 'lodash/omit';
 
 import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator';
 import {openModal} from 'sentry/actionCreators/modal';
-import {updateOrganization} from 'sentry/actionCreators/organizations';
 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 SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
 import {IconAdd} from 'sentry/icons';
 import {t, tct} from 'sentry/locale';
 import type {Organization} from 'sentry/types/organization';
 import type {Relay, RelayActivity} from 'sentry/types/relay';
-import DeprecatedAsyncView from 'sentry/views/deprecatedAsyncView';
+import {useApiQuery} from 'sentry/utils/queryClient';
+import useApi from 'sentry/utils/useApi';
+import useOrganization from 'sentry/utils/useOrganization';
 import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader';
 import TextBlock from 'sentry/views/settings/components/text/textBlock';
 import PermissionAlert from 'sentry/views/settings/organization/permissionAlert';
@@ -24,169 +26,152 @@ import List from './list';
 
 const RELAY_DOCS_LINK = 'https://getsentry.github.io/relay/';
 
-type Props = {
-  organization: Organization;
-} & RouteComponentProps<{}, {}>;
-
-type State = {
-  relayActivities: Array<RelayActivity>;
-  relays: Array<Relay>;
-} & DeprecatedAsyncView['state'];
-
-class RelayWrapper extends DeprecatedAsyncView<Props, State> {
-  componentDidUpdate(prevProps: Props, prevState: State) {
-    if (!isEqual(prevState.relays, this.state.relays)) {
-      // Fetch fresh activities
-      this.fetchData();
-      updateOrganization({...prevProps.organization, trustedRelays: this.state.relays});
-    }
-
-    super.componentDidUpdate(prevProps, prevState);
-  }
-
-  getTitle() {
-    return t('Relay');
-  }
-
-  getDefaultState() {
-    return {
-      ...super.getDefaultState(),
-      relays: this.props.organization.trustedRelays,
-    };
-  }
-
-  getEndpoints(): ReturnType<DeprecatedAsyncView['getEndpoints']> {
-    const {organization} = this.props;
-    return [['relayActivities', `/organizations/${organization.slug}/relay_usage/`]];
-  }
-
-  setRelays(trustedRelays: Array<Relay>) {
-    this.setState({relays: trustedRelays});
-  }
-
-  handleDelete = (publicKey: Relay['publicKey']) => async () => {
-    const {relays} = this.state;
+export function RelayWrapper() {
+  const organization = useOrganization();
+  const api = useApi();
+  const [relays, setRelays] = useState<Relay[]>(organization.trustedRelays);
 
-    const trustedRelays = relays
-      .filter(relay => relay.publicKey !== publicKey)
-      .map(relay => omit(relay, ['created', 'lastModified']));
-
-    try {
-      const response = await this.api.requestPromise(
-        `/organizations/${this.props.organization.slug}/`,
-        {
-          method: 'PUT',
-          data: {trustedRelays},
-        }
-      );
-      addSuccessMessage(t('Successfully deleted Relay public key'));
-      this.setRelays(response.trustedRelays);
-    } catch {
-      addErrorMessage(t('An unknown error occurred while deleting Relay public key'));
-    }
-  };
-
-  successfullySaved(response: Organization, successMessage: string) {
-    addSuccessMessage(successMessage);
-    this.setRelays(response.trustedRelays);
-  }
-
-  handleOpenEditDialog = (publicKey: Relay['publicKey']) => () => {
-    const editRelay = this.state.relays.find(relay => relay.publicKey === publicKey);
-
-    if (!editRelay) {
-      return;
-    }
+  const disabled = !organization.access.includes('org:write');
 
-    openModal(modalProps => (
-      <Edit
-        {...modalProps}
-        savedRelays={this.state.relays}
-        api={this.api}
-        orgSlug={this.props.organization.slug}
-        relay={editRelay}
-        onSubmitSuccess={response => {
-          this.successfullySaved(response, t('Successfully updated Relay public key'));
-        }}
-      />
-    ));
-  };
-
-  handleOpenAddDialog = () => {
+  const handleOpenAddDialog = useCallback(() => {
     openModal(modalProps => (
       <Add
         {...modalProps}
-        savedRelays={this.state.relays}
-        api={this.api}
-        orgSlug={this.props.organization.slug}
+        savedRelays={relays}
+        api={api}
+        orgSlug={organization.slug}
         onSubmitSuccess={response => {
-          this.successfullySaved(response, t('Successfully added Relay public key'));
+          addSuccessMessage(t('Successfully added Relay public key'));
+          setRelays(response.trustedRelays);
         }}
       />
     ));
-  };
-
-  handleRefresh = () => {
-    // Fetch fresh activities
-    this.fetchData();
-  };
-
-  renderContent(disabled: boolean) {
-    const {relays, relayActivities, loading} = this.state;
-
-    if (loading) {
-      return this.renderLoading();
-    }
+  }, [relays, api, organization.slug]);
+
+  return (
+    <SentryDocumentTitle title={t('Relay')}>
+      <SettingsPageHeader
+        title={t('Relay')}
+        action={
+          <Button
+            title={
+              disabled ? t('You do not have permission to register keys') : undefined
+            }
+            priority="primary"
+            size="sm"
+            icon={<IconAdd isCircled />}
+            onClick={handleOpenAddDialog}
+            disabled={disabled}
+          >
+            {t('Register Key')}
+          </Button>
+        }
+      />
+      <PermissionAlert />
+      <TextBlock>
+        {tct(
+          'Sentry Relay offers enterprise-grade data security by providing a standalone service that acts as a middle layer between your application and sentry.io. Go to [link:Relay Documentation] for setup and details.',
+          {link: <ExternalLink href={RELAY_DOCS_LINK} />}
+        )}
+      </TextBlock>
+      {relays.length === 0 ? (
+        <EmptyState />
+      ) : (
+        <RelayUsageList
+          orgSlug={organization.slug}
+          disabled={disabled}
+          relays={relays}
+          api={api}
+          onRelaysChange={setRelays}
+        />
+      )}
+    </SentryDocumentTitle>
+  );
+}
 
-    if (!relays.length) {
-      return <EmptyState />;
+function RelayUsageList({
+  relays,
+  orgSlug,
+  disabled,
+  api,
+  onRelaysChange,
+}: {
+  api: ReturnType<typeof useApi>;
+  disabled: boolean;
+  onRelaysChange: (relays: Relay[]) => void;
+  orgSlug: Organization['slug'];
+  relays: Relay[];
+}) {
+  const {isLoading, isError, refetch, data} = useApiQuery<RelayActivity[]>(
+    [`/organizations/${orgSlug}/relay_usage/`],
+    {
+      staleTime: 0,
+      retry: false,
+      enabled: relays.length > 0,
     }
-
-    return (
-      <List
-        relays={relays}
-        relayActivities={relayActivities}
-        onEdit={this.handleOpenEditDialog}
-        onRefresh={this.handleRefresh}
-        onDelete={this.handleDelete}
-        disabled={disabled}
-      />
-    );
+  );
+
+  const handleOpenEditDialog = useCallback(
+    (publicKey: string) => {
+      const editRelay = relays.find(relay => relay.publicKey === publicKey);
+
+      if (!editRelay) {
+        return;
+      }
+
+      openModal(modalProps => (
+        <Edit
+          {...modalProps}
+          savedRelays={relays}
+          api={api}
+          orgSlug={orgSlug}
+          relay={editRelay}
+          onSubmitSuccess={response => {
+            addSuccessMessage(t('Successfully updated Relay public key'));
+            onRelaysChange(response.trustedRelays);
+          }}
+        />
+      ));
+    },
+    [orgSlug, relays, api, onRelaysChange]
+  );
+
+  const handleDeleteRelay = useCallback(
+    async (publicKey: string) => {
+      const trustedRelays = relays
+        .filter(relay => relay.publicKey !== publicKey)
+        .map(relay => omit(relay, ['created', 'lastModified']));
+
+      try {
+        const response = await api.requestPromise(`/organizations/${orgSlug}/`, {
+          method: 'PUT',
+          data: {trustedRelays},
+        });
+        addSuccessMessage(t('Successfully deleted Relay public key'));
+        onRelaysChange(response.trustedRelays);
+      } catch {
+        addErrorMessage(t('An unknown error occurred while deleting Relay public key'));
+      }
+    },
+    [relays, api, orgSlug, onRelaysChange]
+  );
+
+  if (isLoading) {
+    return <LoadingIndicator />;
   }
 
-  renderBody() {
-    const {organization} = this.props;
-    const disabled = !organization.access.includes('org:write');
-    return (
-      <Fragment>
-        <SettingsPageHeader
-          title={t('Relay')}
-          action={
-            <Button
-              title={
-                disabled ? t('You do not have permission to register keys') : undefined
-              }
-              priority="primary"
-              size="sm"
-              icon={<IconAdd isCircled />}
-              onClick={this.handleOpenAddDialog}
-              disabled={disabled}
-            >
-              {t('Register Key')}
-            </Button>
-          }
-        />
-        <PermissionAlert />
-        <TextBlock>
-          {tct(
-            'Sentry Relay offers enterprise-grade data security by providing a standalone service that acts as a middle layer between your application and sentry.io. Go to [link:Relay Documentation] for setup and details.',
-            {link: <ExternalLink href={RELAY_DOCS_LINK} />}
-          )}
-        </TextBlock>
-        {this.renderContent(disabled)}
-      </Fragment>
-    );
+  if (isError) {
+    return <LoadingError onRetry={refetch} />;
   }
-}
 
-export default RelayWrapper;
+  return (
+    <List
+      relays={relays}
+      relayActivities={data}
+      disabled={disabled}
+      onEdit={publicKey => () => handleOpenEditDialog(publicKey)}
+      onRefresh={() => refetch()}
+      onDelete={publicKey => () => handleDeleteRelay(publicKey)}
+    />
+  );
+}