Files
sentinel/static/app/views/projectInstall/platformIntegrationSetup.tsx
2024-02-15 17:01:50 +00:00

211 lines
6.3 KiB
TypeScript

import {Fragment} from 'react';
import type {RouteComponentProps} from 'react-router';
import {browserHistory} from 'react-router';
import styled from '@emotion/styled';
import {Button} from 'sentry/components/button';
import ButtonBar from 'sentry/components/buttonBar';
import DeprecatedAsyncComponent from 'sentry/components/deprecatedAsyncComponent';
import platforms from 'sentry/data/platforms';
import {t} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import type {IntegrationProvider, Organization, Project} from 'sentry/types';
import {trackAnalytics} from 'sentry/utils/analytics';
import {trackIntegrationAnalytics} from 'sentry/utils/integrationUtil';
import {normalizeUrl} from 'sentry/utils/withDomainRequired';
import withOrganization from 'sentry/utils/withOrganization';
import AddInstallationInstructions from 'sentry/views/onboarding/components/integrations/addInstallationInstructions';
import PostInstallCodeSnippet from 'sentry/views/onboarding/components/integrations/postInstallCodeSnippet';
import {AddIntegrationButton} from 'sentry/views/settings/organizationIntegrations/addIntegrationButton';
import FirstEventFooter from './components/firstEventFooter';
import PlatformHeaderButtonBar from './components/platformHeaderButtonBar';
type Props = {
integrationSlug: string;
organization: Organization;
} & RouteComponentProps<{platform: string; projectId: string}, {}> &
DeprecatedAsyncComponent['props'];
type State = {
installed: boolean;
integrations: {providers: IntegrationProvider[]};
project: Project | null;
} & DeprecatedAsyncComponent['state'];
class PlatformIntegrationSetup extends DeprecatedAsyncComponent<Props, State> {
getDefaultState() {
return {
...super.getDefaultState(),
installed: false,
integrations: {providers: []},
project: null,
};
}
componentDidMount() {
super.componentDidMount();
window.scrollTo(0, 0);
const {platform} = this.props.params;
// redirect if platform is not known.
if (!platform || platform === 'other') {
this.redirectToNeutralDocs();
}
}
get provider() {
const {providers} = this.state.integrations;
return providers.length ? providers[0] : null;
}
getEndpoints(): ReturnType<DeprecatedAsyncComponent['getEndpoints']> {
const {organization, integrationSlug, params} = this.props;
if (!integrationSlug) {
return [];
}
return [
[
'integrations',
`/organizations/${organization.slug}/config/integrations/?provider_key=${integrationSlug}`,
],
['project', `/projects/${organization.slug}/${params.projectId}/`],
];
}
handleFullDocsClick = () => {
const {organization} = this.props;
trackAnalytics('growth.onboarding_view_full_docs', {organization});
};
redirectToNeutralDocs() {
const {organization} = this.props;
const {projectId} = this.props.params;
const url = `/organizations/${organization.slug}/projects/${projectId}/getting-started/`;
browserHistory.push(normalizeUrl(url));
}
handleAddIntegration = () => {
this.setState({installed: true});
};
trackSwitchToManual = () => {
const {organization, integrationSlug} = this.props;
trackIntegrationAnalytics('integrations.switch_manual_sdk_setup', {
integration_type: 'first_party',
integration: integrationSlug,
view: 'project_creation',
organization,
});
};
render() {
const {organization, params} = this.props;
const {installed, project} = this.state;
const {projectId, platform} = params;
const provider = this.provider;
const platformIntegration = platforms.find(p => p.id === platform);
if (!provider || !platformIntegration || !project) {
return null;
}
const gettingStartedLink = `/organizations/${organization.slug}/projects/${projectId}/getting-started/`;
// TODO: make dynamic when adding more integrations
const docsLink =
'https://docs.sentry.io/product/integrations/cloud-monitoring/aws-lambda/';
return (
<OuterWrapper>
<InnerWrapper>
<StyledTitle>
{t('Automatically instrument %s', platformIntegration.name)}
</StyledTitle>
<HeaderButtons>
<PlatformHeaderButtonBar
gettingStartedLink={gettingStartedLink}
docsLink={docsLink}
/>
</HeaderButtons>
{!installed ? (
<Fragment>
<AddInstallationInstructions />
<StyledButtonBar gap={1}>
<AddIntegrationButton
provider={provider}
onAddIntegration={this.handleAddIntegration}
organization={organization}
priority="primary"
size="sm"
analyticsParams={{view: 'project_creation', already_installed: false}}
modalParams={{projectId: project.id}}
aria-label={t('Add integration')}
/>
<Button
size="sm"
to={{
pathname: window.location.pathname,
query: {manual: '1'},
}}
onClick={this.trackSwitchToManual}
>
{t('Manual Setup')}
</Button>
</StyledButtonBar>
</Fragment>
) : (
<Fragment>
<PostInstallCodeSnippet provider={provider} />
<FirstEventFooter
project={project}
organization={organization}
docsLink={docsLink}
docsOnClick={this.handleFullDocsClick}
/>
</Fragment>
)}
</InnerWrapper>
</OuterWrapper>
);
}
}
const StyledButtonBar = styled(ButtonBar)`
margin-top: ${space(3)};
width: max-content;
@media (max-width: ${p => p.theme.breakpoints.small}) {
width: auto;
grid-row-gap: ${space(1)};
grid-auto-flow: row;
}
`;
const InnerWrapper = styled('div')`
max-width: 850px;
`;
const OuterWrapper = styled('div')`
display: flex;
flex-direction: column;
align-items: center;
margin-top: 50px;
`;
const HeaderButtons = styled('div')`
width: min-content;
margin-bottom: ${space(3)};
`;
const StyledTitle = styled('h2')`
margin: 0;
margin-bottom: ${space(2)};
`;
export default withOrganization(PlatformIntegrationSetup);