= {
installationId: install.uuid,
code: install.code,
orgSlug: organization.slug,
};
const state = props.location.query.state;
if (state) {
queryParams.state = state;
}
const redirectUrl = addQueryParamsToExistingUrl(sentryApp.redirectUrl, queryParams);
return window.location.assign(redirectUrl);
}
return onClose();
}, [api, organization, sentryApp, onClose, props.location.query.state]);
if (sentryAppLoading || orgsLoading || !sentryApp) {
return ;
}
return (
{isSingleOrg(organizations) ? (
) : (
)}
{organization && (
)}
);
}
type CheckAndRenderProps = {
isInstalled: boolean | undefined;
organization: Organization | undefined;
selectedOrgSlug: string | undefined;
sentryApp: SentryApp;
};
function CheckAndRenderError({
organization,
selectedOrgSlug,
isInstalled,
sentryApp,
}: CheckAndRenderProps) {
if (selectedOrgSlug && organization && !hasAccess(organization)) {
return (
{tct(
`You do not have permission to install integrations in
[organization]. Ask an organization owner or manager to
visit this page to finish installing this integration.`,
{organization: {organization.slug}}
)}
{generateOrgSlugUrl(selectedOrgSlug)}
);
}
if (isInstalled && organization && sentryApp) {
return (
{tct('Integration [sentryAppName] already installed for [organization]', {
organization: {organization.name},
sentryAppName: {sentryApp.name},
})}
);
}
if (isSentryAppUnavailableForOrg(sentryApp, selectedOrgSlug)) {
// use the slug of the owner if we have it, otherwise use 'another organization'
const ownerSlug = sentryApp?.owner?.slug ?? 'another organization';
return (
{tct(
'Integration [sentryAppName] is an unpublished integration for [otherOrg]. An unpublished integration can only be installed on the organization which created it.',
{
sentryAppName: {sentryApp.name},
otherOrg: {ownerSlug},
}
)}
);
}
return null;
}
type SingleOrgProps = {
organizations: OrganizationSummary[];
sentryApp: SentryApp;
};
function SingleOrgView({organizations, sentryApp}: SingleOrgProps) {
const organizationName = organizations[0]!.name;
return (
{tct('You are installing [sentryAppName] for organization [organization]', {
organization: {organizationName},
sentryAppName: {sentryApp.name},
})}
);
}
type SelectOrgCallback = (slug: string) => void;
type MultiOrgProps = {
onSelectOrg: SelectOrgCallback;
organizations: OrganizationSummary[];
selectedOrgSlug: string | undefined;
sentryApp: SentryApp;
};
function MultiOrgView({
onSelectOrg,
organizations,
selectedOrgSlug,
sentryApp,
}: MultiOrgProps) {
return (
{tct(
'Please pick a specific [organization:organization] to install [sentryAppName]',
{
organization: ,
sentryAppName: {sentryApp.name},
}
)}
onSelectOrg(value)}
value={selectedOrgSlug}
placeholder={t('Select an organization')}
options={getOrganizationOptions(organizations)}
data-test-id="org-select"
/>
);
}
const hasAccess = (org: Organization) => org.access.includes('org:integrations');
function isSingleOrg(organizations: OrganizationSummary[]): boolean {
return organizations.length === 1;
}
function getOrganizationOptions(organizations: OrganizationSummary[]) {
return organizations.map(org => ({
value: org.slug,
label: (
{org.slug}
),
}));
}
function isSentryAppUnavailableForOrg(
sentryApp: SentryApp,
selectedOrgSlug: string | undefined
): boolean {
if (!selectedOrgSlug) {
return false;
}
// if the app is unpublished for a different org
return sentryApp?.owner?.slug !== selectedOrgSlug && sentryApp.status === 'unpublished';
}
const InstallLink = styled('pre')`
margin-bottom: 0;
background: #fbe3e1;
`;
const OrgNameHolder = styled('span')`
margin-left: 5px;
`;
const Content = styled('div')`
margin-bottom: 40px;
`;
const OrgViewHolder = styled('div')`
margin-bottom: 20px;
`;