Skip to content

Commit 2664225

Browse files
authored
feat(tempest): DevKit instructions (#93008)
This is one big PR that refactors and adds new onboarding instructions for DevKit. In this PR: - PlayStation settings have been refactored - DevKit onbaording instructions have been added - Warning about the support for PS5 only has been added Both PlayStation and DevKit now have dedicated tabs now. Video available in the Linear ticket since it contains sensitive information (DSN). Closes [TET-586: DevKit onbaording in Playstation settings](https://linear.app/getsentry/issue/TET-586/devkit-onbaording-in-playstation-settings)
1 parent 3b20149 commit 2664225

File tree

7 files changed

+608
-180
lines changed

7 files changed

+608
-180
lines changed
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
import {Fragment, useMemo} from 'react';
2+
import styled from '@emotion/styled';
3+
4+
import waitingForEventImg from 'sentry-images/spot/waiting-for-event.svg';
5+
import devkitCrashesStep1 from 'sentry-images/tempest/devkit-crashes-step1.png';
6+
import devkitCrashesStep2 from 'sentry-images/tempest/devkit-crashes-step2.png';
7+
import devkitCrashesStep3 from 'sentry-images/tempest/devkit-crashes-step3.png';
8+
import windowToolImg from 'sentry-images/tempest/windows-tool-devkit.png';
9+
10+
import {Button} from 'sentry/components/core/button';
11+
import {ButtonBar} from 'sentry/components/core/button/buttonBar';
12+
import FeedbackWidgetButton from 'sentry/components/feedback/widget/feedbackWidgetButton';
13+
import {GuidedSteps} from 'sentry/components/guidedSteps/guidedSteps';
14+
import LoadingIndicator from 'sentry/components/loadingIndicator';
15+
import {OnboardingCodeSnippet} from 'sentry/components/onboarding/gettingStartedDoc/onboardingCodeSnippet';
16+
import Panel from 'sentry/components/panels/panel';
17+
import PanelBody from 'sentry/components/panels/panelBody';
18+
import {t} from 'sentry/locale';
19+
import {space} from 'sentry/styles/space';
20+
import type {Organization} from 'sentry/types/organization';
21+
import type {Project} from 'sentry/types/project';
22+
import {decodeInteger} from 'sentry/utils/queryString';
23+
import {useLocation} from 'sentry/utils/useLocation';
24+
import {useNavigate} from 'sentry/utils/useNavigate';
25+
import {useProjectKeys} from 'sentry/utils/useProjectKeys';
26+
27+
interface Props {
28+
organization: Organization;
29+
project: Project;
30+
}
31+
32+
export default function DevKitSettings({organization, project}: Props) {
33+
const navigate = useNavigate();
34+
const location = useLocation();
35+
36+
const {data: projectKeys, isPending: isLoadingKeys} = useProjectKeys({
37+
orgSlug: organization.slug,
38+
projSlug: project.slug,
39+
});
40+
41+
const playstationURL = useMemo(() => {
42+
if (!projectKeys) {
43+
return null;
44+
}
45+
46+
// xxx (vgrozdanic): this is a temporary hack since the playstation URL is almost the same as for the minidump
47+
const primaryKey = projectKeys[0];
48+
return primaryKey?.dsn?.minidump.replace('minidump', 'playstation');
49+
}, [projectKeys]);
50+
51+
if (isLoadingKeys) {
52+
return <LoadingIndicator />;
53+
}
54+
55+
return (
56+
<Fragment>
57+
<Panel>
58+
<PanelBody>
59+
<div>
60+
<HeaderWrapper>
61+
<Title>{t('Get Started with DevKit Crash Monitoring')}</Title>
62+
<Description>
63+
{t(
64+
'Set up your PlayStation development kit to send crash reports to Sentry.'
65+
)}
66+
</Description>
67+
<Image src={waitingForEventImg} />
68+
</HeaderWrapper>
69+
<Divider />
70+
<Body>
71+
<Setup>
72+
<BodyTitle>{t('Setup Instructions')}</BodyTitle>
73+
<GuidedSteps
74+
initialStep={decodeInteger(location.query.guidedStep)}
75+
onStepChange={step => {
76+
navigate({
77+
pathname: location.pathname,
78+
query: {
79+
...location.query,
80+
guidedStep: step,
81+
},
82+
});
83+
}}
84+
>
85+
<GuidedSteps.Step
86+
stepKey="step-1"
87+
title={t('Copy Playstation Ingestion URL')}
88+
>
89+
<DescriptionWrapper>
90+
<p>
91+
{t('This is the URL where your crash reports will be sent. ')}
92+
</p>
93+
<CodeSnippetWrapper>
94+
<OnboardingCodeSnippet>
95+
{playstationURL || ''}
96+
</OnboardingCodeSnippet>
97+
</CodeSnippetWrapper>
98+
</DescriptionWrapper>
99+
<GuidedSteps.StepButtons />
100+
</GuidedSteps.Step>
101+
102+
<GuidedSteps.Step
103+
stepKey="step-2"
104+
title={t('Using Windows tool set up Upload URL')}
105+
>
106+
<DescriptionWrapper>
107+
<StepContentColumn>
108+
<StepTextSection>
109+
<p>
110+
{t(
111+
'Using Windows tool enter that link into the DevKit as the URL to the Recap Server.'
112+
)}
113+
</p>
114+
</StepTextSection>
115+
<StepImageSection>
116+
<CardIllustration
117+
src={windowToolImg}
118+
alt="Setup Configuration"
119+
/>
120+
</StepImageSection>
121+
</StepContentColumn>
122+
</DescriptionWrapper>
123+
<GuidedSteps.StepButtons />
124+
</GuidedSteps.Step>
125+
126+
<GuidedSteps.Step
127+
stepKey="step-3"
128+
title={t('Using DevKit Directly set up Upload URL')}
129+
>
130+
<DescriptionWrapper>
131+
<StepContentColumn>
132+
<StepTextSection>
133+
<p>
134+
{t(
135+
`If you haven't done it via Windows tool, you can set up the Upload URL directly in the DevKit. It is under 'Debug Settings' > 'Core Dump' > 'Upload' > 'Upload URL'.`
136+
)}
137+
</p>
138+
</StepTextSection>
139+
<StepImageSection>
140+
<CardIllustration
141+
src={devkitCrashesStep1}
142+
alt="Setup Configuration"
143+
/>
144+
</StepImageSection>
145+
<StepImageSection>
146+
<CardIllustration
147+
src={devkitCrashesStep2}
148+
alt="Setup Configuration"
149+
/>
150+
</StepImageSection>
151+
<StepImageSection>
152+
<CardIllustration
153+
src={devkitCrashesStep3}
154+
alt="Setup Configuration"
155+
/>
156+
</StepImageSection>
157+
</StepContentColumn>
158+
</DescriptionWrapper>
159+
<GuidedSteps.StepButtons />
160+
</GuidedSteps.Step>
161+
162+
<GuidedSteps.Step stepKey="step-4" title={t('Important Notes')}>
163+
<DescriptionWrapper>
164+
<p>
165+
{t(
166+
'If you are trying to re-attempt the upload of a failed crash that occurred before entering the URL it might be that the DevKit still tries to send the crash to the previously specified URL.'
167+
)}
168+
</p>
169+
170+
<p>
171+
{t(
172+
'There is currently a limit on the size of files we support, as such, uploading large dumps or long videos may fail. Short videos should be supposed so configuring the DevKit to keep them short is a temporary solution.'
173+
)}
174+
</p>
175+
</DescriptionWrapper>
176+
<GuidedSteps.StepButtons>
177+
<Button
178+
size="sm"
179+
priority="primary"
180+
onClick={() => {
181+
navigate({
182+
pathname: '/issues/',
183+
query: {
184+
query: 'os.name:PlayStation',
185+
},
186+
});
187+
}}
188+
>
189+
{t('View DevKit Issues')}
190+
</Button>
191+
</GuidedSteps.StepButtons>
192+
</GuidedSteps.Step>
193+
</GuidedSteps>
194+
</Setup>
195+
</Body>
196+
</div>
197+
</PanelBody>
198+
</Panel>
199+
</Fragment>
200+
);
201+
}
202+
203+
export const getDevKitHeaderAction = () => {
204+
return (
205+
<ButtonBar gap={1.5}>
206+
<FeedbackWidgetButton />
207+
</ButtonBar>
208+
);
209+
};
210+
211+
const Title = styled('div')`
212+
font-size: 26px;
213+
font-weight: ${p => p.theme.fontWeightBold};
214+
`;
215+
216+
const Description = styled('div')``;
217+
218+
const HeaderWrapper = styled('div')`
219+
border-radius: ${p => p.theme.borderRadius};
220+
padding: ${space(4)};
221+
`;
222+
223+
const BodyTitle = styled('div')`
224+
font-size: ${p => p.theme.fontSizeExtraLarge};
225+
font-weight: ${p => p.theme.fontWeightBold};
226+
margin-bottom: ${space(1)};
227+
`;
228+
229+
const Setup = styled('div')`
230+
padding: ${space(4)};
231+
`;
232+
233+
const Body = styled('div')``;
234+
235+
const Image = styled('img')`
236+
position: absolute;
237+
display: block;
238+
top: 0px;
239+
right: 20px;
240+
pointer-events: none;
241+
height: 120px;
242+
overflow: hidden;
243+
244+
@media (max-width: ${p => p.theme.breakpoints.small}) {
245+
display: none;
246+
}
247+
`;
248+
249+
const Divider = styled('hr')`
250+
height: 1px;
251+
width: 95%;
252+
background: ${p => p.theme.border};
253+
border: none;
254+
margin-top: 0;
255+
margin-bottom: 0;
256+
`;
257+
258+
const CodeSnippetWrapper = styled('div')`
259+
margin-bottom: ${space(2)};
260+
margin-top: ${space(2)};
261+
`;
262+
263+
const DescriptionWrapper = styled('div')`
264+
margin-bottom: ${space(1)};
265+
`;
266+
267+
const StepContentColumn = styled('div')`
268+
display: flex;
269+
flex-direction: column;
270+
width: 100%;
271+
gap: ${space(3)};
272+
`;
273+
274+
const StepTextSection = styled('div')`
275+
display: flex;
276+
flex-direction: column;
277+
gap: ${space(1)};
278+
`;
279+
280+
const StepImageSection = styled('div')`
281+
display: flex;
282+
justify-content: center;
283+
align-items: center;
284+
width: 100%;
285+
`;
286+
287+
const CardIllustration = styled('img')`
288+
width: 100%;
289+
max-width: 600px;
290+
height: auto;
291+
object-fit: contain;
292+
border: 1px solid ${p => p.theme.border};
293+
border-radius: ${p => p.theme.borderRadius};
294+
box-shadow: ${p => p.theme.dropShadowLight};
295+
`;

0 commit comments

Comments
 (0)