|
@@ -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)`
|