Skip to content

Commit 9b3b1c0

Browse files
priscilawebdevcmanallen
authored andcommitted
feat(quick-start): Add logic to skeleton - Part 2 (#79179)
1 parent 80d0b27 commit 9b3b1c0

File tree

2 files changed

+128
-48
lines changed

2 files changed

+128
-48
lines changed

static/app/components/onboardingWizard/newSidebar.tsx

Lines changed: 66 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,27 @@ import partition from 'lodash/partition';
1313

1414
import {navigateTo} from 'sentry/actionCreators/navigation';
1515
import {updateOnboardingTask} from 'sentry/actionCreators/onboardingTasks';
16+
import {Button} from 'sentry/components/button';
1617
import {Chevron} from 'sentry/components/chevron';
1718
import InteractionStateLayer from 'sentry/components/interactionStateLayer';
1819
import {
1920
OnboardingContext,
2021
type OnboardingContextProps,
2122
} from 'sentry/components/onboarding/onboardingContext';
23+
import SkipConfirm from 'sentry/components/onboardingWizard/skipConfirm';
2224
import {findCompleteTasks, taskIsDone} from 'sentry/components/onboardingWizard/utils';
2325
import ProgressRing from 'sentry/components/progressRing';
2426
import SidebarPanel from 'sentry/components/sidebar/sidebarPanel';
2527
import type {CommonSidebarProps} from 'sentry/components/sidebar/types';
26-
import {Tooltip} from 'sentry/components/tooltip';
27-
import {IconCheckmark} from 'sentry/icons';
28+
import {IconCheckmark, IconClose} from 'sentry/icons';
2829
import {t, tct} from 'sentry/locale';
2930
import DemoWalkthroughStore from 'sentry/stores/demoWalkthroughStore';
30-
import pulsingIndicatorStyles from 'sentry/styles/pulsingIndicator';
3131
import {space} from 'sentry/styles/space';
32-
import {type OnboardingTask, OnboardingTaskGroup} from 'sentry/types/onboarding';
32+
import {
33+
type OnboardingTask,
34+
OnboardingTaskGroup,
35+
type OnboardingTaskKey,
36+
} from 'sentry/types/onboarding';
3337
import type {Organization} from 'sentry/types/organization';
3438
import type {Project} from 'sentry/types/project';
3539
import {trackAnalytics} from 'sentry/utils/analytics';
@@ -85,10 +89,11 @@ function getPanelDescription(walkthrough: boolean) {
8589
interface TaskProps {
8690
hidePanel: () => void;
8791
task: OnboardingTask;
88-
status?: 'waiting' | 'completed';
92+
completed?: boolean;
8993
}
9094

91-
function Task({task, status, hidePanel}: TaskProps) {
95+
function Task({task, completed, hidePanel}: TaskProps) {
96+
const api = useApi();
9297
const organization = useOrganization();
9398
const router = useRouter();
9499

@@ -129,7 +134,35 @@ function Task({task, status, hidePanel}: TaskProps) {
129134
[task, organization, router, hidePanel]
130135
);
131136

132-
if (status === 'completed') {
137+
const handleMarkComplete = useCallback(
138+
(taskKey: OnboardingTaskKey) => {
139+
updateOnboardingTask(api, organization, {
140+
task: taskKey,
141+
status: 'complete',
142+
completionSeen: true,
143+
});
144+
},
145+
[api, organization]
146+
);
147+
148+
const handleMarkSkipped = useCallback(
149+
(taskKey: OnboardingTaskKey) => {
150+
trackAnalytics('quick_start.task_card_clicked', {
151+
organization,
152+
todo_id: task.task,
153+
todo_title: task.title,
154+
action: 'skipped',
155+
});
156+
updateOnboardingTask(api, organization, {
157+
task: taskKey,
158+
status: 'skipped',
159+
completionSeen: true,
160+
});
161+
},
162+
[task, organization, api]
163+
);
164+
165+
if (completed) {
133166
return (
134167
<TaskWrapper completed>
135168
<strong>{task.title}</strong>
@@ -138,28 +171,36 @@ function Task({task, status, hidePanel}: TaskProps) {
138171
);
139172
}
140173

141-
if (status === 'waiting') {
142-
return (
143-
<TaskWrapper onClick={handleClick}>
144-
<InteractionStateLayer />
145-
<div>
146-
<strong>{task.title}</strong>
147-
<p>{task.description}</p>
148-
</div>
149-
<Tooltip title={t('Waiting for event')}>
150-
<PulsingIndicator />
151-
</Tooltip>
152-
</TaskWrapper>
153-
);
154-
}
155-
156174
return (
157175
<TaskWrapper onClick={handleClick}>
158176
<InteractionStateLayer />
159177
<div>
160178
<strong>{task.title}</strong>
161179
<p>{task.description}</p>
162180
</div>
181+
{task.requisiteTasks.length === 0 && (
182+
<Fragment>
183+
{task.skippable && (
184+
<SkipConfirm onSkip={() => handleMarkSkipped(task.task)}>
185+
{({skip}) => (
186+
<Button
187+
borderless
188+
size="zero"
189+
aria-label={t('Close')}
190+
icon={<IconClose size="xs" color="gray300" />}
191+
onClick={skip}
192+
/>
193+
)}
194+
</SkipConfirm>
195+
)}
196+
{task.SupplementComponent && (
197+
<task.SupplementComponent
198+
task={task}
199+
onCompleteTask={() => handleMarkComplete(task.task)}
200+
/>
201+
)}
202+
</Fragment>
203+
)}
163204
</TaskWrapper>
164205
);
165206
}
@@ -215,12 +256,7 @@ function TaskGroup({title, description, tasks, expanded, hidePanel}: TaskGroupPr
215256
<Fragment>
216257
<TaskGroupProgress completed>{t('Completed')}</TaskGroupProgress>
217258
{completedTasks.map(task => (
218-
<Task
219-
key={task.task}
220-
task={task}
221-
hidePanel={hidePanel}
222-
status="completed"
223-
/>
259+
<Task key={task.task} task={task} hidePanel={hidePanel} completed />
224260
))}
225261
</Fragment>
226262
)}
@@ -398,7 +434,6 @@ const TaskWrapper = styled('div')<{completed?: boolean}>`
398434
border-radius: ${p => p.theme.borderRadius};
399435
display: grid;
400436
grid-template-columns: 1fr max-content;
401-
align-items: center;
402437
gap: ${space(1)};
403438
404439
p {
@@ -413,14 +448,11 @@ const TaskWrapper = styled('div')<{completed?: boolean}>`
413448
strong {
414449
opacity: 0.5;
415450
}
451+
align-items: center;
416452
`
417453
: css`
418454
position: relative;
419455
cursor: pointer;
456+
align-items: flex-start;
420457
`}
421458
`;
422-
423-
const PulsingIndicator = styled('div')`
424-
${pulsingIndicatorStyles};
425-
margin: 0 ${space(0.5)};
426-
`;

static/app/components/onboardingWizard/taskConfig.tsx

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {css} from '@emotion/react';
12
import styled from '@emotion/styled';
23

34
import {openInviteMembersModal} from 'sentry/actionCreators/modal';
@@ -11,6 +12,7 @@ import {
1112
} from 'sentry/components/onboardingWizard/utils';
1213
import {filterProjects} from 'sentry/components/performanceOnboarding/utils';
1314
import {SidebarPanelKey} from 'sentry/components/sidebar/types';
15+
import {Tooltip} from 'sentry/components/tooltip';
1416
import {sourceMaps} from 'sentry/data/platformCategories';
1517
import {t} from 'sentry/locale';
1618
import SidebarPanelStore from 'sentry/stores/sidebarPanelStore';
@@ -208,7 +210,12 @@ export function getOnboardingTasks({
208210
eventType="error"
209211
onIssueReceived={() => !taskIsDone(task) && onCompleteTask()}
210212
>
211-
{() => <EventWaitingIndicator text={t('Waiting for error')} />}
213+
{() => (
214+
<EventWaitingIndicator
215+
text={t('Waiting for error')}
216+
hasQuickStartUpdatesFeature={hasQuickStartUpdatesFeature(organization)}
217+
/>
218+
)}
212219
</EventWaiter>
213220
) : null
214221
),
@@ -338,7 +345,11 @@ export function getOnboardingTasks({
338345
eventType="transaction"
339346
onIssueReceived={() => !taskIsDone(task) && onCompleteTask()}
340347
>
341-
{() => <EventWaitingIndicator />}
348+
{() => (
349+
<EventWaitingIndicator
350+
hasQuickStartUpdatesFeature={hasQuickStartUpdatesFeature(organization)}
351+
/>
352+
)}
342353
</EventWaiter>
343354
) : null
344355
),
@@ -391,7 +402,12 @@ export function getOnboardingTasks({
391402
eventType="replay"
392403
onIssueReceived={() => !taskIsDone(task) && onCompleteTask()}
393404
>
394-
{() => <EventWaitingIndicator text={t('Waiting for user session')} />}
405+
{() => (
406+
<EventWaitingIndicator
407+
hasQuickStartUpdatesFeature={hasQuickStartUpdatesFeature(organization)}
408+
text={t('Waiting for user session')}
409+
/>
410+
)}
395411
</EventWaiter>
396412
) : null
397413
),
@@ -516,22 +532,54 @@ export function getMergedTasks({organization, projects, onboardingContext}: Opti
516532
}));
517533
}
518534

519-
const PulsingIndicator = styled('div')`
535+
const PulsingIndicator = styled('div')<{hasQuickStartUpdatesFeature?: boolean}>`
520536
${pulsingIndicatorStyles};
521-
margin-right: ${space(1)};
537+
${p =>
538+
p.hasQuickStartUpdatesFeature
539+
? css`
540+
margin: 0 ${space(0.5)};
541+
`
542+
: css`
543+
margin-right: ${space(1)};
544+
`}
522545
`;
523546

524547
const EventWaitingIndicator = styled(
525-
(p: React.HTMLAttributes<HTMLDivElement> & {text?: string}) => (
526-
<div {...p}>
527-
<PulsingIndicator />
528-
{p.text || t('Waiting for event')}
529-
</div>
530-
)
548+
({
549+
hasQuickStartUpdatesFeature: quickStartUpdatesFeature,
550+
text,
551+
...p
552+
}: React.HTMLAttributes<HTMLDivElement> & {
553+
hasQuickStartUpdatesFeature: boolean;
554+
text?: string;
555+
}) => {
556+
if (quickStartUpdatesFeature) {
557+
return (
558+
<div {...p}>
559+
<Tooltip title={text || t('Waiting for event')}>
560+
<PulsingIndicator hasQuickStartUpdatesFeature />
561+
</Tooltip>
562+
</div>
563+
);
564+
}
565+
return (
566+
<div {...p}>
567+
<PulsingIndicator />
568+
{text || t('Waiting for event')}
569+
</div>
570+
);
571+
}
531572
)`
532573
display: flex;
533574
align-items: center;
534-
flex-grow: 1;
535-
font-size: ${p => p.theme.fontSizeMedium};
536-
color: ${p => p.theme.pink400};
575+
${p =>
576+
p.hasQuickStartUpdatesFeature
577+
? css`
578+
height: 16px;
579+
`
580+
: css`
581+
flex-grow: 1;
582+
font-size: ${p.theme.fontSizeMedium};
583+
color: ${p.theme.pink400};
584+
`}
537585
`;

0 commit comments

Comments
 (0)