Browse Source

fix(alerts): Convert alert wizard to functional component (#50889)

Scott Cooper 1 year ago
parent
commit
ed42437632

+ 0 - 2
static/app/utils/analytics/workflowAnalyticsEvents.tsx

@@ -57,7 +57,6 @@ export type TeamInsightsEventParameters = {
   'alert_rules.viewed': {sort: string};
   'alert_stream.viewed': {};
   'alert_wizard.option_selected': {alert_type: string};
-  'alert_wizard.option_viewed': {alert_type: string};
   'edit_alert_rule.add_row': {
     name: string;
     project_id: string;
@@ -137,7 +136,6 @@ export const workflowEventMap: Record<TeamInsightsEventKey, string | null> = {
   'alert_rules.viewed': 'Alert Rules: Viewed',
   'alert_stream.viewed': 'Alert Stream: Viewed',
   'alert_wizard.option_selected': 'Alert Wizard: Option Selected',
-  'alert_wizard.option_viewed': 'Alert Wizard: Option Viewed',
   'edit_alert_rule.add_row': 'Edit Alert Rule: Add Row',
   'edit_alert_rule.viewed': 'Edit Alert Rule: Viewed',
   'edit_alert_rule.incompatible_rule': 'Edit Alert Rule: Incompatible Rule',

+ 87 - 116
static/app/views/alerts/wizard/index.tsx

@@ -1,4 +1,4 @@
-import {Component} from 'react';
+import {useState} from 'react';
 import {RouteComponentProps} from 'react-router';
 import styled from '@emotion/styled';
 
@@ -34,47 +34,26 @@ type RouteParams = {
   projectId?: string;
 };
 
-type Props = RouteComponentProps<RouteParams, {}> & {
+type AlertWizardProps = RouteComponentProps<RouteParams, {}> & {
   organization: Organization;
   projectId: string;
 };
 
-type State = {
-  alertOption: AlertType;
-};
-
 const DEFAULT_ALERT_OPTION = 'issues';
 
-class AlertWizard extends Component<Props, State> {
-  state: State = {
-    alertOption:
-      this.props.location.query.alert_option in AlertWizardAlertNames
-        ? this.props.location.query.alert_option
-        : DEFAULT_ALERT_OPTION,
-  };
-
-  componentDidMount() {
-    // capture landing on the alert wizard page and viewing the issue alert by default
-    this.trackView();
-  }
-
-  trackView(alertType: AlertType = DEFAULT_ALERT_OPTION) {
-    const {organization} = this.props;
-    trackAnalytics('alert_wizard.option_viewed', {
-      organization,
-      alert_type: alertType,
-    });
-  }
+function AlertWizard({organization, params, location, projectId}: AlertWizardProps) {
+  const [alertOption, setAlertOption] = useState<AlertType>(
+    location.query.alert_option in AlertWizardAlertNames
+      ? location.query.alert_option
+      : DEFAULT_ALERT_OPTION
+  );
+  const projectSlug = params.projectId ?? projectId;
 
-  handleChangeAlertOption = (alertOption: AlertType) => {
-    this.setState({alertOption});
-    this.trackView(alertOption);
+  const handleChangeAlertOption = (option: AlertType) => {
+    setAlertOption(option);
   };
 
-  renderCreateAlertButton() {
-    const {organization, location, params, projectId: _projectId} = this.props;
-    const {alertOption} = this.state;
-    const projectId = params.projectId ?? _projectId;
+  function renderCreateAlertButton() {
     let metricRuleTemplate: Readonly<WizardRuleTemplate> | undefined =
       AlertWizardRuleTemplates[alertOption];
     const isMetricAlert = !!metricRuleTemplate;
@@ -87,17 +66,6 @@ class AlertWizard extends Component<Props, State> {
       metricRuleTemplate = {...metricRuleTemplate, dataset: Dataset.METRICS};
     }
 
-    const to = {
-      pathname: `/organizations/${organization.slug}/alerts/new/${
-        isMetricAlert ? AlertRuleType.METRIC : AlertRuleType.ISSUE
-      }/`,
-      query: {
-        ...(metricRuleTemplate ? metricRuleTemplate : {}),
-        project: projectId,
-        referrer: location?.query?.referrer,
-      },
-    };
-
     const renderNoAccess = p => (
       <Hovercard
         body={
@@ -137,10 +105,19 @@ class AlertWizard extends Component<Props, State> {
           >
             <CreateAlertButton
               organization={organization}
-              projectSlug={projectId}
+              projectSlug={projectSlug}
               disabled={!hasFeature}
               priority="primary"
-              to={to}
+              to={{
+                pathname: `/organizations/${organization.slug}/alerts/new/${
+                  isMetricAlert ? AlertRuleType.METRIC : AlertRuleType.ISSUE
+                }/`,
+                query: {
+                  ...(metricRuleTemplate ? metricRuleTemplate : {}),
+                  project: projectSlug,
+                  referrer: location?.query?.referrer,
+                },
+              }}
               hideIcon
             >
               {t('Set Conditions')}
@@ -151,77 +128,71 @@ class AlertWizard extends Component<Props, State> {
     );
   }
 
-  render() {
-    const {organization, params, projectId: _projectId} = this.props;
-    const {alertOption} = this.state;
-    const projectId = params.projectId ?? _projectId;
-    const title = t('Alert Creation Wizard');
-    const panelContent = AlertWizardPanelContent[alertOption];
-    return (
-      <Layout.Page>
-        <SentryDocumentTitle title={title} projectSlug={projectId} />
-
-        <Layout.Header>
-          <StyledHeaderContent>
-            <BuilderBreadCrumbs
-              organization={organization}
-              projectSlug={projectId}
-              title={t('Select Alert')}
-            />
-            <Layout.Title>{t('Select Alert')}</Layout.Title>
-          </StyledHeaderContent>
-        </Layout.Header>
-        <Layout.Body>
-          <Layout.Main fullWidth>
-            <WizardBody>
-              <WizardOptions>
-                {getAlertWizardCategories(organization).map(
-                  ({categoryHeading, options}) => (
-                    <div key={categoryHeading}>
-                      <CategoryTitle>{categoryHeading} </CategoryTitle>
-                      <RadioPanelGroup
-                        choices={options.map(alertType => {
-                          return [alertType, AlertWizardAlertNames[alertType]];
-                        })}
-                        onChange={this.handleChangeAlertOption}
-                        value={alertOption}
-                        label="alert-option"
-                      />
-                    </div>
-                  )
-                )}
-              </WizardOptions>
-              <WizardPanel visible={!!panelContent && !!alertOption}>
-                <WizardPanelBody>
-                  <div>
-                    <PanelHeader>{AlertWizardAlertNames[alertOption]}</PanelHeader>
-                    <PanelBody withPadding>
-                      <PanelDescription>
-                        {panelContent.description}{' '}
-                        {panelContent.docsLink && (
-                          <ExternalLink href={panelContent.docsLink}>
-                            {t('Learn more')}
-                          </ExternalLink>
-                        )}
-                      </PanelDescription>
-                      <WizardImage src={panelContent.illustration} />
-                      <ExampleHeader>{t('Examples')}</ExampleHeader>
-                      <ExampleList symbol="bullet">
-                        {panelContent.examples.map((example, i) => (
-                          <ExampleItem key={i}>{example}</ExampleItem>
-                        ))}
-                      </ExampleList>
-                    </PanelBody>
+  const panelContent = AlertWizardPanelContent[alertOption];
+  return (
+    <Layout.Page>
+      <SentryDocumentTitle title={t('Alert Creation Wizard')} projectSlug={projectSlug} />
+
+      <Layout.Header>
+        <StyledHeaderContent>
+          <BuilderBreadCrumbs
+            organization={organization}
+            projectSlug={projectSlug}
+            title={t('Select Alert')}
+          />
+          <Layout.Title>{t('Select Alert')}</Layout.Title>
+        </StyledHeaderContent>
+      </Layout.Header>
+      <Layout.Body>
+        <Layout.Main fullWidth>
+          <WizardBody>
+            <WizardOptions>
+              {getAlertWizardCategories(organization).map(
+                ({categoryHeading, options}) => (
+                  <div key={categoryHeading}>
+                    <CategoryTitle>{categoryHeading} </CategoryTitle>
+                    <RadioPanelGroup
+                      choices={options.map(alertType => {
+                        return [alertType, AlertWizardAlertNames[alertType]];
+                      })}
+                      onChange={handleChangeAlertOption}
+                      value={alertOption}
+                      label="alert-option"
+                    />
                   </div>
-                  <WizardFooter>{this.renderCreateAlertButton()}</WizardFooter>
-                </WizardPanelBody>
-              </WizardPanel>
-            </WizardBody>
-          </Layout.Main>
-        </Layout.Body>
-      </Layout.Page>
-    );
-  }
+                )
+              )}
+            </WizardOptions>
+            <WizardPanel visible={!!panelContent && !!alertOption}>
+              <WizardPanelBody>
+                <div>
+                  <PanelHeader>{AlertWizardAlertNames[alertOption]}</PanelHeader>
+                  <PanelBody withPadding>
+                    <PanelDescription>
+                      {panelContent.description}{' '}
+                      {panelContent.docsLink && (
+                        <ExternalLink href={panelContent.docsLink}>
+                          {t('Learn more')}
+                        </ExternalLink>
+                      )}
+                    </PanelDescription>
+                    <WizardImage src={panelContent.illustration} />
+                    <ExampleHeader>{t('Examples')}</ExampleHeader>
+                    <ExampleList symbol="bullet">
+                      {panelContent.examples.map((example, i) => (
+                        <ExampleItem key={i}>{example}</ExampleItem>
+                      ))}
+                    </ExampleList>
+                  </PanelBody>
+                </div>
+                <WizardFooter>{renderCreateAlertButton()}</WizardFooter>
+              </WizardPanelBody>
+            </WizardPanel>
+          </WizardBody>
+        </Layout.Main>
+      </Layout.Body>
+    </Layout.Page>
+  );
 }
 
 const StyledHeaderContent = styled(Layout.HeaderContent)`