import {Fragment, useCallback, useState} from 'react'; import {css} from '@emotion/react'; import styled from '@emotion/styled'; import omit from 'lodash/omit'; import {PlatformIcon} from 'platformicons'; import { addErrorMessage, addLoadingMessage, addSuccessMessage, clearIndicators, } from 'sentry/actionCreators/indicator'; import type {ModalRenderProps} from 'sentry/actionCreators/modal'; import {Button} from 'sentry/components/button'; import Input from 'sentry/components/input'; import type {SupportedLanguages} from 'sentry/components/onboarding/frameworkSuggestionModal'; import PlatformPicker, { type Category, type Platform, } from 'sentry/components/platformPicker'; import TeamSelector from 'sentry/components/teamSelector'; import {t} from 'sentry/locale'; import ProjectsStore from 'sentry/stores/projectsStore'; import {space} from 'sentry/styles/space'; import type {OnboardingSelectedSDK, Team} from 'sentry/types'; import {trackAnalytics} from 'sentry/utils/analytics'; import slugify from 'sentry/utils/slugify'; import useApi from 'sentry/utils/useApi'; import useOrganization from 'sentry/utils/useOrganization'; import type {IssueAlertFragment} from 'sentry/views/projectInstall/createProject'; import IssueAlertOptions from 'sentry/views/projectInstall/issueAlertOptions'; type Props = ModalRenderProps & { defaultCategory?: Category; }; export default function ProjectCreationModal({ Header, closeModal, defaultCategory, }: Props) { const [platform, setPlatform] = useState(undefined); const [step, setStep] = useState(0); const [alertRuleConfig, setAlertRuleConfig] = useState( undefined ); const [projectName, setProjectName] = useState(''); const [team, setTeam] = useState(undefined); const [creating, setCreating] = useState(false); const api = useApi(); const organization = useOrganization(); function handlePlatformChange(selectedPlatform: Platform | null) { if (selectedPlatform) { setPlatform({ ...omit(selectedPlatform, 'id'), key: selectedPlatform.id, }); } } const createProject = useCallback(async () => { const {slug} = organization; const { shouldCreateCustomRule, name, conditions, actions, actionMatch, frequency, defaultRules, } = alertRuleConfig || {}; if (platform === undefined) { return; } addLoadingMessage(t('Creating project...'), { duration: 15000, }); try { const url = `/teams/${slug}/${team}/projects/`; const projectData = await api.requestPromise(url, { method: 'POST', data: { name: projectName, platform: platform.key, default_rules: defaultRules ?? true, }, }); let ruleId: string | undefined; if (shouldCreateCustomRule) { const ruleData = await api.requestPromise( `/projects/${organization.slug}/${projectData.slug}/rules/`, { method: 'POST', data: { name, conditions, actions, actionMatch, frequency, }, } ); ruleId = ruleData.id; } ProjectsStore.onCreateSuccess(projectData, organization.slug); clearIndicators(); trackAnalytics('project_modal.created', { organization, issue_alert: defaultRules ? 'Default' : shouldCreateCustomRule ? 'Custom' : 'No Rule', project_id: projectData.id, rule_id: ruleId || '', }); addSuccessMessage(`Created project ${projectData.slug}`); closeModal(); } catch (err) { setCreating(false); addErrorMessage(`Failed to create project ${projectName}`); } }, [api, alertRuleConfig, organization, platform, projectName, team, closeModal]); return (

{t('Create a Project')}

{step === 0 && ( Choose a Platform )} {step === 1 && ( {t('Set your alert frequency')} setAlertRuleConfig(updatedData)} /> {t('Name your project and assign it a team')}
setProjectName(slugify(e.target.value))} />
setTeam(choice.value)} teamFilter={(tm: Team) => tm.access.includes('team:admin')} />
)}
); } const Footer = styled('div')` display: flex; flex-direction: row; justify-content: right; gap: ${space(1)}; margin-top: ${space(2)}; `; const StyledPlatformIcon = styled(PlatformIcon)` position: absolute; top: 50%; left: ${p => p.theme.formPadding.md.paddingLeft}px; transform: translateY(-50%); `; const ProjectNameInputWrap = styled('div')` position: relative; `; const ProjectNameInput = styled(Input)` padding-left: calc(${p => p.theme.formPadding.md.paddingLeft}px * 1.5 + 20px); `; export const modalCss = css` width: 100%; max-width: 1000px; `; const ProjectNameTeamSection = styled('div')` display: flex; flex-direction: row; gap: ${space(1)}; `; const Label = styled('div')` font-size: ${p => p.theme.fontSizeExtraLarge}; margin-bottom: ${space(1)}; `; const TeamInput = styled(TeamSelector)` min-width: 250px; `; const Subtitle = styled('p')` margin: ${space(2)} 0 ${space(1)} 0; font-size: ${p => p.theme.fontSizeExtraLarge}; font-weight: bold; `;