Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 31 additions & 14 deletions static/app/views/alerts/create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import {browserHistory, RouteComponentProps} from 'react-router';
import styled from '@emotion/styled';

import * as Layout from 'app/components/layouts/thirds';
import LoadingIndicator from 'app/components/loadingIndicator';
import SentryDocumentTitle from 'app/components/sentryDocumentTitle';
import {t} from 'app/locale';
import space from 'app/styles/space';
import {Organization, Project} from 'app/types';
import {trackAnalyticsEvent} from 'app/utils/analytics';
import EventView from 'app/utils/discover/eventView';
import {uniqueId} from 'app/utils/guid';
import Teams from 'app/utils/teams';
import BuilderBreadCrumbs from 'app/views/alerts/builder/builderBreadCrumbs';
import IncidentRulesCreate from 'app/views/alerts/incidentRules/create';
import IssueRuleEditor from 'app/views/alerts/issueRuleEditor';
Expand Down Expand Up @@ -128,20 +130,35 @@ class Create extends Component<Props, State> {
</Layout.Header>
<AlertConditionsBody>
<StyledLayoutMain fullWidth>
{(!hasMetricAlerts || alertType === 'issue') && (
<IssueRuleEditor {...this.props} project={project} />
)}

{hasMetricAlerts && alertType === 'metric' && (
<IncidentRulesCreate
{...this.props}
eventView={eventView}
wizardTemplate={wizardTemplate}
sessionId={this.sessionId}
project={project}
isCustomMetric={wizardAlertType === 'custom'}
/>
)}
<Teams provideUserTeams>
{({teams, initiallyLoaded}) =>
initiallyLoaded ? (
<Fragment>
{(!hasMetricAlerts || alertType === 'issue') && (
<IssueRuleEditor
{...this.props}
project={project}
userTeamIds={teams.map(({id}) => id)}
/>
)}

{hasMetricAlerts && alertType === 'metric' && (
<IncidentRulesCreate
{...this.props}
eventView={eventView}
wizardTemplate={wizardTemplate}
sessionId={this.sessionId}
project={project}
isCustomMetric={wizardAlertType === 'custom'}
userTeamIds={teams.map(({id}) => id)}
/>
)}
</Fragment>
) : (
<LoadingIndicator />
)
}
</Teams>
</StyledLayoutMain>
</AlertConditionsBody>
</Fragment>
Expand Down
42 changes: 28 additions & 14 deletions static/app/views/alerts/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import {RouteComponentProps} from 'react-router';
import styled from '@emotion/styled';

import * as Layout from 'app/components/layouts/thirds';
import LoadingIndicator from 'app/components/loadingIndicator';
import SentryDocumentTitle from 'app/components/sentryDocumentTitle';
import {t} from 'app/locale';
import space from 'app/styles/space';
import {Organization, Project} from 'app/types';
import {trackAnalyticsEvent} from 'app/utils/analytics';
import Teams from 'app/utils/teams';
import BuilderBreadCrumbs from 'app/views/alerts/builder/builderBreadCrumbs';
import IncidentRulesDetails from 'app/views/alerts/incidentRules/details';
import IssueEditor from 'app/views/alerts/issueRuleEditor';
Expand Down Expand Up @@ -83,20 +85,32 @@ class ProjectAlertsEditor extends Component<Props, State> {
</Layout.Header>
<EditConditionsBody>
<Layout.Main fullWidth>
{(!hasMetricAlerts || alertType === 'issue') && (
<IssueEditor
{...this.props}
project={project}
onChangeTitle={this.handleChangeTitle}
/>
)}
{hasMetricAlerts && alertType === 'metric' && (
<IncidentRulesDetails
{...this.props}
project={project}
onChangeTitle={this.handleChangeTitle}
/>
)}
<Teams provideUserTeams>
{({teams, initiallyLoaded}) =>
initiallyLoaded ? (
<Fragment>
{(!hasMetricAlerts || alertType === 'issue') && (
<IssueEditor
{...this.props}
project={project}
onChangeTitle={this.handleChangeTitle}
userTeamIds={teams.map(({id}) => id)}
/>
)}
{hasMetricAlerts && alertType === 'metric' && (
<IncidentRulesDetails
{...this.props}
project={project}
onChangeTitle={this.handleChangeTitle}
userTeamIds={teams.map(({id}) => id)}
/>
)}
</Fragment>
) : (
<LoadingIndicator />
)
}
</Teams>
</Layout.Main>
</EditConditionsBody>
</Fragment>
Expand Down
12 changes: 5 additions & 7 deletions static/app/views/alerts/incidentRules/create.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import {RouteComponentProps} from 'react-router';

import {Organization, Project, Team} from 'app/types';
import {Organization, Project} from 'app/types';
import {metric} from 'app/utils/analytics';
import EventView from 'app/utils/discover/eventView';
import withTeams from 'app/utils/withTeams';
import {
createDefaultRule,
createRuleFromEventView,
Expand All @@ -23,7 +22,7 @@ type Props = {
organization: Organization;
project: Project;
eventView: EventView | undefined;
teams: Team[];
userTeamIds: string[];
wizardTemplate?: WizardRuleTemplate;
sessionId?: string;
isCustomMetric?: boolean;
Expand All @@ -41,15 +40,14 @@ function IncidentRulesCreate(props: Props) {
router.push(`/organizations/${orgId}/alerts/rules/`);
}

const {project, eventView, wizardTemplate, sessionId, teams, ...otherProps} = props;
const {project, eventView, wizardTemplate, sessionId, userTeamIds, ...otherProps} =
props;
const defaultRule = eventView
? createRuleFromEventView(eventView)
: wizardTemplate
? createRuleFromWizardTemplate(wizardTemplate)
: createDefaultRule();

const userTeamIds = teams.filter(({isMember}) => isMember).map(({id}) => id);

const projectTeamIds = new Set(project.teams.map(({id}) => id));
const defaultOwnerId = userTeamIds.find(id => projectTeamIds.has(id)) ?? null;
defaultRule.owner = defaultOwnerId && `team:${defaultOwnerId}`;
Expand All @@ -66,4 +64,4 @@ function IncidentRulesCreate(props: Props) {
);
}

export default withTeams(IncidentRulesCreate);
export default IncidentRulesCreate;
11 changes: 3 additions & 8 deletions static/app/views/alerts/incidentRules/details.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {RouteComponentProps} from 'react-router';

import {Organization, Project, Team} from 'app/types';
import {Organization, Project} from 'app/types';
import {metric} from 'app/utils/analytics';
import withTeams from 'app/utils/withTeams';
import RuleForm from 'app/views/alerts/incidentRules/ruleForm';
import {IncidentRule} from 'app/views/alerts/incidentRules/types';
import AsyncView from 'app/views/asyncView';
Expand All @@ -17,7 +16,7 @@ type Props = {
organization: Organization;
onChangeTitle: (data: string) => void;
project: Project;
teams: Team[];
userTeamIds: string[];
} & RouteComponentProps<RouteParams, {}>;

type State = {
Expand Down Expand Up @@ -54,22 +53,18 @@ class IncidentRulesDetails extends AsyncView<Props, State> {
};

renderBody() {
const {teams} = this.props;
const {ruleId} = this.props.params;
const {rule} = this.state;

const userTeamIds = teams.filter(({isMember}) => isMember).map(({id}) => id);

return (
<RuleForm
{...this.props}
ruleId={ruleId}
rule={rule}
onSubmitSuccess={this.handleSubmitSuccess}
userTeamIds={userTeamIds}
/>
);
}
}

export default withTeams(IncidentRulesDetails);
export default IncidentRulesDetails;
18 changes: 8 additions & 10 deletions static/app/views/alerts/issueRuleEditor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import {isActiveSuperuser} from 'app/utils/isActiveSuperuser';
import recreateRoute from 'app/utils/recreateRoute';
import routeTitleGen from 'app/utils/routeTitle';
import withOrganization from 'app/utils/withOrganization';
import withTeams from 'app/utils/withTeams';
import {
CHANGE_ALERT_CONDITION_IDS,
CHANGE_ALERT_PLACEHOLDERS_LABELS,
Expand Down Expand Up @@ -101,7 +100,7 @@ type RuleTaskResponse = {
type Props = {
project: Project;
organization: Organization;
teams: Team[];
userTeamIds: string[];
onChangeTitle?: (data: string) => void;
} & RouteComponentProps<{orgId: string; projectId: string; ruleId?: string}, {}>;

Expand Down Expand Up @@ -138,7 +137,7 @@ class IssueRuleEditor extends AsyncView<Props, State> {
}

getDefaultState() {
const {teams, project} = this.props;
const {userTeamIds, project} = this.props;
const defaultState = {
...super.getDefaultState(),
configs: null,
Expand All @@ -149,9 +148,8 @@ class IssueRuleEditor extends AsyncView<Props, State> {
};

const projectTeamIds = new Set(project.teams.map(({id}) => id));
const userTeam =
teams.find(({isMember, id}) => !!isMember && projectTeamIds.has(id)) ?? null;
defaultState.rule.owner = userTeam && `team:${userTeam.id}`;
const userTeamId = userTeamIds.find(id => projectTeamIds.has(id)) ?? null;
defaultState.rule.owner = userTeamId && `team:${userTeamId}`;

return defaultState;
}
Expand Down Expand Up @@ -546,7 +544,7 @@ class IssueRuleEditor extends AsyncView<Props, State> {
}

renderBody() {
const {project, organization, teams} = this.props;
const {project, organization, userTeamIds} = this.props;
const {environments} = this.state;
const environmentOptions = [
{
Expand All @@ -563,10 +561,10 @@ class IssueRuleEditor extends AsyncView<Props, State> {
const environment =
!rule || !rule.environment ? ALL_ENVIRONMENTS_KEY : rule.environment;

const userTeams = teams.filter(({isMember}) => isMember).map(({id}) => id);
const ownerId = rule?.owner?.split(':')[1];
// check if superuser or if user is on the alert's team
const canEdit = isActiveSuperuser() || (ownerId ? userTeams.includes(ownerId) : true);
const canEdit =
isActiveSuperuser() || (ownerId ? userTeamIds.includes(ownerId) : true);

// Note `key` on `<Form>` below is so that on initial load, we show
// the form with a loading mask on top of it, but force a re-render by using
Expand Down Expand Up @@ -895,7 +893,7 @@ class IssueRuleEditor extends AsyncView<Props, State> {
}
}

export default withOrganization(withTeams(IssueRuleEditor));
export default withOrganization(IssueRuleEditor);

// TODO(ts): Understand why styled is not correctly inheriting props here
const StyledForm = styled(Form)<Form['props']>`
Expand Down
2 changes: 2 additions & 0 deletions tests/js/spec/views/alerts/create.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {

import * as memberActionCreators from 'app/actionCreators/members';
import ProjectsStore from 'app/stores/projectsStore';
import TeamStore from 'app/stores/teamStore';
import {metric, trackAnalyticsEvent} from 'app/utils/analytics';
import AlertsContainer from 'app/views/alerts';
import AlertBuilderProjectProvider from 'app/views/alerts/builder/projectProvider';
Expand All @@ -33,6 +34,7 @@ jest.mock('app/utils/analytics', () => ({
}));

describe('ProjectAlertsCreate', function () {
TeamStore.loadInitialData([]);
const projectAlertRuleDetailsRoutes = [
{
path: '/organizations/:orgId/alerts/',
Expand Down
1 change: 1 addition & 0 deletions tests/js/spec/views/alerts/incidentRules/create.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ describe('Incident Rules Create', function () {
params={{orgId: organization.slug, projectId: project.slug}}
organization={organization}
project={project}
userTeamIds={[]}
/>,
routerContext
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ describe('ProjectAlerts -> IssueRuleEditor', function () {
routes={projectAlertRuleDetailsRoutes}
onChangeTitle={onChangeTitleMock}
project={project}
userTeamIds={[]}
/>
</ProjectAlerts>,
routerContext
Expand Down