Files
2024-02-15 17:01:50 +00:00

89 lines
2.8 KiB
TypeScript

import {cloneElement, Fragment, isValidElement, useEffect, useState} from 'react';
import type {RouteComponentProps} from 'react-router';
import {fetchOrgMembers} from 'sentry/actionCreators/members';
import {navigateTo} from 'sentry/actionCreators/navigation';
import {Alert} from 'sentry/components/alert';
import LoadingIndicator from 'sentry/components/loadingIndicator';
import {t} from 'sentry/locale';
import type {Member, Organization} from 'sentry/types';
import useApi from 'sentry/utils/useApi';
import {useIsMountedRef} from 'sentry/utils/useIsMountedRef';
import useProjects from 'sentry/utils/useProjects';
import useScrollToTop from 'sentry/utils/useScrollToTop';
type Props = RouteComponentProps<RouteParams, {}> & {
hasMetricAlerts: boolean;
organization: Organization;
children?: React.ReactNode;
};
type RouteParams = {
projectId?: string;
};
function AlertBuilderProjectProvider(props: Props) {
const api = useApi();
const isMountedRef = useIsMountedRef();
const [members, setMembers] = useState<Member[] | undefined>(undefined);
useScrollToTop({location: props.location});
const {children, params, organization, ...other} = props;
const projectId = params.projectId || props.location.query.project;
const useFirstProject = projectId === undefined;
const {projects, initiallyLoaded, fetching, fetchError} = useProjects();
const project = useFirstProject
? projects.find(p => p.isMember) ?? (projects.length && projects[0])
: projects.find(({slug}) => slug === projectId);
useEffect(() => {
if (!project) {
return;
}
// fetch members list for mail action fields
fetchOrgMembers(api, organization.slug, [project.id]).then(mem => {
if (isMountedRef.current) {
setMembers(mem);
}
});
}, [api, organization, isMountedRef, project]);
if (!initiallyLoaded || fetching) {
return <LoadingIndicator />;
}
// If there's no project show the project selector modal
if (!project && !fetchError) {
navigateTo(
`/organizations/${organization.slug}/alerts/wizard/?referrer=${props.location.query.referrer}&project=:projectId`,
props.router
);
}
// if loaded, but project fetching states incomplete or project can't be found, project doesn't exist
if (!project || fetchError) {
return (
<Alert type="warning">{t('The project you were looking for was not found.')}</Alert>
);
}
return (
<Fragment>
{children && isValidElement(children)
? cloneElement(children, {
...other,
...children.props,
project,
projectId: useFirstProject ? project.slug : projectId,
organization,
members,
})
: children}
</Fragment>
);
}
export default AlertBuilderProjectProvider;