@automattic/launchpad 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/.storybook/main.ts +16 -0
  2. package/.storybook/preview.ts +6 -0
  3. package/README.md +11 -2
  4. package/dist/cjs/action-components/index.js +6 -0
  5. package/dist/cjs/action-components/index.js.map +1 -0
  6. package/dist/cjs/action-components/share-site-modal/index.js +44 -0
  7. package/dist/cjs/action-components/share-site-modal/index.js.map +1 -0
  8. package/dist/cjs/action-components/share-site-modal/style.scss +159 -0
  9. package/dist/cjs/badge/index.js +2 -2
  10. package/dist/cjs/badge/index.js.map +1 -1
  11. package/dist/cjs/checklist/index.js +16 -8
  12. package/dist/cjs/checklist/index.js.map +1 -1
  13. package/dist/cjs/checklist/index.stories.js +29 -0
  14. package/dist/cjs/checklist/index.stories.js.map +1 -0
  15. package/dist/cjs/checklist-item/index.js +30 -13
  16. package/dist/cjs/checklist-item/index.js.map +1 -1
  17. package/dist/cjs/checklist-item/index.stories.js +79 -0
  18. package/dist/cjs/checklist-item/index.stories.js.map +1 -0
  19. package/dist/cjs/checklist-item/style.scss +142 -22
  20. package/dist/cjs/index.js +6 -1
  21. package/dist/cjs/index.js.map +1 -1
  22. package/dist/cjs/launchpad-container/index.js +11 -0
  23. package/dist/cjs/launchpad-container/index.js.map +1 -0
  24. package/dist/cjs/launchpad-container/style.scss +59 -0
  25. package/dist/cjs/launchpad-internal.js +40 -0
  26. package/dist/cjs/launchpad-internal.js.map +1 -0
  27. package/dist/cjs/launchpad-internal.stories.js +45 -0
  28. package/dist/cjs/launchpad-internal.stories.js.map +1 -0
  29. package/dist/cjs/launchpad.js +39 -10
  30. package/dist/cjs/launchpad.js.map +1 -1
  31. package/dist/cjs/msw/link-in-bio.js +68 -0
  32. package/dist/cjs/msw/link-in-bio.js.map +1 -0
  33. package/dist/cjs/msw/resolver.js +19 -0
  34. package/dist/cjs/msw/resolver.js.map +1 -0
  35. package/dist/cjs/msw/setup-free.js +88 -0
  36. package/dist/cjs/msw/setup-free.js.map +1 -0
  37. package/dist/cjs/setup-actions.js +51 -54
  38. package/dist/cjs/setup-actions.js.map +1 -1
  39. package/dist/cjs/use-tracking/index.js +72 -0
  40. package/dist/cjs/use-tracking/index.js.map +1 -0
  41. package/dist/esm/action-components/index.js +2 -0
  42. package/dist/esm/action-components/index.js.map +1 -0
  43. package/dist/esm/action-components/share-site-modal/index.js +42 -0
  44. package/dist/esm/action-components/share-site-modal/index.js.map +1 -0
  45. package/dist/esm/action-components/share-site-modal/style.scss +159 -0
  46. package/dist/esm/badge/index.js +2 -2
  47. package/dist/esm/badge/index.js.map +1 -1
  48. package/dist/esm/checklist/index.js +14 -8
  49. package/dist/esm/checklist/index.js.map +1 -1
  50. package/dist/esm/checklist/index.stories.js +25 -0
  51. package/dist/esm/checklist/index.stories.js.map +1 -0
  52. package/dist/esm/checklist-item/index.js +29 -14
  53. package/dist/esm/checklist-item/index.js.map +1 -1
  54. package/dist/esm/checklist-item/index.stories.js +75 -0
  55. package/dist/esm/checklist-item/index.stories.js.map +1 -0
  56. package/dist/esm/checklist-item/style.scss +142 -22
  57. package/dist/esm/index.js +3 -0
  58. package/dist/esm/index.js.map +1 -1
  59. package/dist/esm/launchpad-container/index.js +8 -0
  60. package/dist/esm/launchpad-container/index.js.map +1 -0
  61. package/dist/esm/launchpad-container/style.scss +59 -0
  62. package/dist/esm/launchpad-internal.js +37 -0
  63. package/dist/esm/launchpad-internal.js.map +1 -0
  64. package/dist/esm/launchpad-internal.stories.js +41 -0
  65. package/dist/esm/launchpad-internal.stories.js.map +1 -0
  66. package/dist/esm/launchpad.js +41 -13
  67. package/dist/esm/launchpad.js.map +1 -1
  68. package/dist/esm/msw/link-in-bio.js +66 -0
  69. package/dist/esm/msw/link-in-bio.js.map +1 -0
  70. package/dist/esm/msw/resolver.js +14 -0
  71. package/dist/esm/msw/resolver.js.map +1 -0
  72. package/dist/esm/msw/setup-free.js +86 -0
  73. package/dist/esm/msw/setup-free.js.map +1 -0
  74. package/dist/esm/setup-actions.js +51 -54
  75. package/dist/esm/setup-actions.js.map +1 -1
  76. package/dist/esm/use-tracking/index.js +68 -0
  77. package/dist/esm/use-tracking/index.js.map +1 -0
  78. package/dist/tsconfig-cjs.tsbuildinfo +1 -1
  79. package/dist/tsconfig.tsbuildinfo +1 -1
  80. package/dist/types/action-components/index.d.ts +2 -0
  81. package/dist/types/action-components/index.d.ts.map +1 -0
  82. package/dist/types/action-components/share-site-modal/index.d.ts +9 -0
  83. package/dist/types/action-components/share-site-modal/index.d.ts.map +1 -0
  84. package/dist/types/badge/index.d.ts.map +1 -1
  85. package/dist/types/checklist/index.d.ts +6 -7
  86. package/dist/types/checklist/index.d.ts.map +1 -1
  87. package/dist/types/checklist/index.stories.d.ts +8 -0
  88. package/dist/types/checklist/index.stories.d.ts.map +1 -0
  89. package/dist/types/checklist-item/index.d.ts +11 -8
  90. package/dist/types/checklist-item/index.d.ts.map +1 -1
  91. package/dist/types/checklist-item/index.stories.d.ts +14 -0
  92. package/dist/types/checklist-item/index.stories.d.ts.map +1 -0
  93. package/dist/types/index.d.ts +3 -0
  94. package/dist/types/index.d.ts.map +1 -1
  95. package/dist/types/launchpad-container/index.d.ts +15 -0
  96. package/dist/types/launchpad-container/index.d.ts.map +1 -0
  97. package/dist/types/launchpad-internal.d.ts +20 -0
  98. package/dist/types/launchpad-internal.d.ts.map +1 -0
  99. package/dist/types/launchpad-internal.stories.d.ts +8 -0
  100. package/dist/types/launchpad-internal.stories.d.ts.map +1 -0
  101. package/dist/types/launchpad.d.ts +10 -9
  102. package/dist/types/launchpad.d.ts.map +1 -1
  103. package/dist/types/msw/link-in-bio.d.ts +35 -0
  104. package/dist/types/msw/link-in-bio.d.ts.map +1 -0
  105. package/dist/types/msw/resolver.d.ts +3 -0
  106. package/dist/types/msw/resolver.d.ts.map +1 -0
  107. package/dist/types/msw/setup-free.d.ts +35 -0
  108. package/dist/types/msw/setup-free.d.ts.map +1 -0
  109. package/dist/types/setup-actions.d.ts +1 -1
  110. package/dist/types/setup-actions.d.ts.map +1 -1
  111. package/dist/types/types.d.ts +19 -9
  112. package/dist/types/types.d.ts.map +1 -1
  113. package/dist/types/use-tracking/index.d.ts +14 -0
  114. package/dist/types/use-tracking/index.d.ts.map +1 -0
  115. package/package.json +24 -16
  116. package/src/action-components/index.ts +1 -0
  117. package/src/action-components/share-site-modal/index.tsx +100 -0
  118. package/src/action-components/share-site-modal/style.scss +159 -0
  119. package/src/badge/index.tsx +2 -4
  120. package/src/checklist/index.stories.tsx +45 -0
  121. package/src/checklist/index.tsx +22 -21
  122. package/src/checklist/test/index.tsx +26 -0
  123. package/src/checklist-item/index.stories.tsx +92 -0
  124. package/src/checklist-item/index.tsx +62 -22
  125. package/src/checklist-item/style.scss +142 -22
  126. package/src/checklist-item/test/index.tsx +232 -0
  127. package/src/index.ts +3 -0
  128. package/src/launchpad-container/index.tsx +45 -0
  129. package/src/launchpad-container/style.scss +59 -0
  130. package/src/launchpad-container/test/index.tsx +72 -0
  131. package/src/launchpad-internal.stories.tsx +49 -0
  132. package/src/launchpad-internal.tsx +85 -0
  133. package/src/launchpad.tsx +80 -30
  134. package/src/msw/link-in-bio.ts +66 -0
  135. package/src/msw/resolver.ts +18 -0
  136. package/src/msw/setup-free.ts +85 -0
  137. package/src/setup-actions.ts +67 -54
  138. package/src/test/launchpad.tsx +51 -24
  139. package/src/test/lib/fixtures.ts +7 -2
  140. package/src/types.ts +24 -9
  141. package/src/use-tracking/index.tsx +87 -0
  142. package/src/use-tracking/test/index.tsx +116 -0
  143. package/static/mockServiceWorker.js +287 -0
  144. package/src/test/checklist-item.tsx +0 -96
  145. package/src/test/checklist.tsx +0 -25
@@ -0,0 +1,49 @@
1
+ import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
2
+ import { http } from 'msw';
3
+ import LaunchpadInternal from './launchpad-internal';
4
+ import { launchpadResolver } from './msw/resolver';
5
+ import type { Meta, StoryObj } from '@storybook/react';
6
+
7
+ const queryClient = new QueryClient();
8
+
9
+ const meta: Meta< typeof LaunchpadInternal > = {
10
+ title: 'Launchpad/LaunchpadInternal',
11
+ component: LaunchpadInternal,
12
+ decorators: [
13
+ ( Story ) => (
14
+ <QueryClientProvider client={ queryClient }>
15
+ <Story />
16
+ </QueryClientProvider>
17
+ ),
18
+ ],
19
+ parameters: {
20
+ msw: {
21
+ handlers: [ http.get( '/wpcom/v2/sites/*/launchpad', launchpadResolver ) ],
22
+ },
23
+ },
24
+ args: {
25
+ site: null,
26
+ siteSlug: 'example.wordpress.com',
27
+ launchpadContext: 'fullscreen',
28
+ checklistSlug: 'free',
29
+ },
30
+ argTypes: {
31
+ checklistSlug: {
32
+ defaultValue: 'free',
33
+ options: [ 'free', 'link-in-bio' ],
34
+ control: { type: 'select' },
35
+ },
36
+ },
37
+ };
38
+
39
+ type Story = StoryObj< typeof meta >;
40
+ export const Default: Story = {};
41
+ export const Loading: Story = {
42
+ parameters: {
43
+ msw: {
44
+ delay: 1000,
45
+ },
46
+ },
47
+ };
48
+
49
+ export default meta;
@@ -0,0 +1,85 @@
1
+ import { useLaunchpad } from '@automattic/data-stores';
2
+ import { type FC, useMemo } from 'react';
3
+ import Checklist, { Placeholder as ChecklistPlaceHolder } from './checklist';
4
+ import ChecklistItem from './checklist-item';
5
+ import { useTracking } from './use-tracking';
6
+ import type { Task } from './types';
7
+ import type { SiteDetails, UseLaunchpadOptions } from '@automattic/data-stores';
8
+
9
+ interface Props {
10
+ site?: SiteDetails | null;
11
+ siteSlug: string | null;
12
+ checklistSlug: string | null;
13
+ makeLastTaskPrimaryAction?: boolean;
14
+ taskFilter?: ( tasks: Task[] ) => Task[];
15
+ useLaunchpadOptions?: UseLaunchpadOptions;
16
+ launchpadContext: string;
17
+ flow?: string;
18
+ }
19
+
20
+ /**
21
+ * Low-level launchpad component that should only be used in exceptional cases.
22
+ * Please use the main Launchpad component whenever possible.
23
+ */
24
+ const LaunchpadInternal: FC< Props > = ( {
25
+ flow,
26
+ site,
27
+ siteSlug,
28
+ checklistSlug,
29
+ taskFilter,
30
+ makeLastTaskPrimaryAction,
31
+ useLaunchpadOptions = {},
32
+ launchpadContext,
33
+ } ) => {
34
+ const launchpadData = useLaunchpad(
35
+ siteSlug || '',
36
+ checklistSlug,
37
+ useLaunchpadOptions,
38
+ launchpadContext
39
+ );
40
+
41
+ const { isFetchedAfterMount, data } = launchpadData;
42
+ const { checklist } = data;
43
+
44
+ const tasks = useMemo( () => {
45
+ if ( ! checklist ) {
46
+ return [];
47
+ }
48
+ return taskFilter ? taskFilter( checklist ) : checklist;
49
+ // Array of tasks requires deep comparison
50
+ // eslint-disable-next-line react-hooks/exhaustive-deps
51
+ }, [ JSON.stringify( checklist ), taskFilter ] );
52
+
53
+ const { trackTaskClick } = useTracking( {
54
+ tasks,
55
+ checklistSlug,
56
+ site,
57
+ context: launchpadContext,
58
+ flow,
59
+ } );
60
+
61
+ const itemClickHandler = ( task: Task ) => {
62
+ trackTaskClick( task );
63
+ task?.actionDispatch?.();
64
+ };
65
+
66
+ return (
67
+ <div className="launchpad__checklist-wrapper">
68
+ { isFetchedAfterMount ? (
69
+ <Checklist makeLastTaskPrimaryAction={ makeLastTaskPrimaryAction }>
70
+ { tasks.map( ( task ) => (
71
+ <ChecklistItem
72
+ task={ task }
73
+ key={ task.id }
74
+ onClick={ () => itemClickHandler( task ) }
75
+ />
76
+ ) ) }
77
+ </Checklist>
78
+ ) : (
79
+ <ChecklistPlaceHolder />
80
+ ) }
81
+ </div>
82
+ );
83
+ };
84
+
85
+ export default LaunchpadInternal;
package/src/launchpad.tsx CHANGED
@@ -1,44 +1,94 @@
1
- import { useLaunchpad } from '@automattic/data-stores';
2
- import { useRef, useMemo } from 'react';
3
- import Checklist from './checklist';
4
- import type { Task } from './types';
5
- import type { UseLaunchpadOptions } from '@automattic/data-stores';
1
+ import { recordTracksEvent } from '@automattic/calypso-analytics';
2
+ import {
3
+ LaunchpadNavigator,
4
+ Site,
5
+ type SiteSelect,
6
+ sortLaunchpadTasksByCompletionStatus,
7
+ useSortedLaunchpadTasks,
8
+ } from '@automattic/data-stores';
9
+ import { useDispatch, useSelect } from '@wordpress/data';
10
+ import { useState } from 'react';
11
+ import { ShareSiteModal } from './action-components';
12
+ import LaunchpadInternal from './launchpad-internal';
13
+ import { setUpActionsForTasks } from './setup-actions';
14
+ import type { EventHandlers, Task } from './types';
6
15
 
7
- export interface LaunchpadProps {
16
+ export const SITE_STORE = Site.register( { client_id: '', client_secret: '' } );
17
+
18
+ type LaunchpadProps = {
8
19
  siteSlug: string | null;
9
- checklistSlug?: string | 0 | null | undefined;
10
- makeLastTaskPrimaryAction?: boolean;
11
- taskFilter?: ( tasks: Task[] ) => Task[];
12
- useLaunchpadOptions?: UseLaunchpadOptions;
13
- }
20
+ checklistSlug: string;
21
+ launchpadContext: string;
22
+ onSiteLaunched?: () => void;
23
+ onTaskClick?: EventHandlers[ 'onTaskClick' ];
24
+ onPostFilterTasks?: ( tasks: Task[] ) => Task[];
25
+ };
14
26
 
15
27
  const Launchpad = ( {
16
28
  siteSlug,
17
29
  checklistSlug,
18
- taskFilter,
19
- makeLastTaskPrimaryAction,
20
- useLaunchpadOptions = {},
30
+ launchpadContext,
31
+ onSiteLaunched,
32
+ onTaskClick,
33
+ onPostFilterTasks,
21
34
  }: LaunchpadProps ) => {
22
- const launchpadData = useLaunchpad( siteSlug || '', checklistSlug, useLaunchpadOptions );
23
- const { isFetchedAfterMount, data } = launchpadData;
24
- const tasks = useRef< Task[] >( [] );
35
+ const {
36
+ data: { checklist },
37
+ } = useSortedLaunchpadTasks( siteSlug, checklistSlug, launchpadContext );
38
+ const { setActiveChecklist } = useDispatch( LaunchpadNavigator.store );
39
+
40
+ const tasklistCompleted = checklist?.every( ( task: Task ) => task.completed ) || false;
41
+
42
+ const tracksData = { recordTracksEvent, checklistSlug, tasklistCompleted, launchpadContext };
43
+
44
+ const site = useSelect(
45
+ ( select ) => {
46
+ return siteSlug ? ( select( SITE_STORE ) as SiteSelect ).getSite( siteSlug ) : null;
47
+ },
48
+ [ siteSlug ]
49
+ );
50
+ const [ shareSiteModalIsOpen, setShareSiteModalIsOpen ] = useState( false );
51
+
52
+ const taskFilter = ( tasks: Task[] ) => {
53
+ const baseTasks = setUpActionsForTasks( {
54
+ tasks,
55
+ siteSlug,
56
+ tracksData,
57
+ extraActions: {
58
+ setActiveChecklist,
59
+ setShareSiteModalIsOpen,
60
+ },
61
+ eventHandlers: {
62
+ onSiteLaunched,
63
+ onTaskClick,
64
+ },
65
+ } );
66
+
67
+ if ( onPostFilterTasks ) {
68
+ return onPostFilterTasks( baseTasks );
69
+ }
70
+
71
+ return baseTasks;
72
+ };
25
73
 
26
- useMemo( () => {
27
- const originalTasks = data.checklist || [];
28
- tasks.current = taskFilter ? taskFilter( originalTasks ) : originalTasks;
29
- }, [ data, taskFilter ] );
74
+ const launchpadOptions = {
75
+ onSuccess: sortLaunchpadTasksByCompletionStatus,
76
+ };
30
77
 
31
78
  return (
32
- <div className="launchpad__checklist-wrapper">
33
- { isFetchedAfterMount ? (
34
- <Checklist
35
- tasks={ tasks.current }
36
- makeLastTaskPrimaryAction={ makeLastTaskPrimaryAction }
37
- />
38
- ) : (
39
- <Checklist.Placeholder />
79
+ <>
80
+ { shareSiteModalIsOpen && site && (
81
+ <ShareSiteModal setModalIsOpen={ setShareSiteModalIsOpen } site={ site } />
40
82
  ) }
41
- </div>
83
+ <LaunchpadInternal
84
+ site={ site }
85
+ siteSlug={ siteSlug }
86
+ checklistSlug={ checklistSlug }
87
+ taskFilter={ taskFilter }
88
+ useLaunchpadOptions={ launchpadOptions }
89
+ launchpadContext={ launchpadContext }
90
+ />
91
+ </>
42
92
  );
43
93
  };
44
94
 
@@ -0,0 +1,66 @@
1
+ export default {
2
+ site_intent: 'free',
3
+ launchpad_screen: 'full',
4
+ checklist_statuses: {
5
+ setup_free: true,
6
+ setup_general: true,
7
+ design_completed: true,
8
+ site_theme_selected: true,
9
+ },
10
+ checklist: [
11
+ {
12
+ id: 'design_selected',
13
+ title: 'Select a design',
14
+ completed: true,
15
+ disabled: false,
16
+ subtitle: '',
17
+ badge_text: '',
18
+ isLaunchTask: false,
19
+ calypso_path: '/setup/update-design/designSetup?siteSlug=site62798.wordpress.com',
20
+ },
21
+ {
22
+ id: 'setup_link_in_bio',
23
+ title: 'Personalize Link in Bio',
24
+ completed: true,
25
+ disabled: false,
26
+ subtitle: '',
27
+ badge_text: '',
28
+ isLaunchTask: false,
29
+ calypso_path:
30
+ '/setup/link-in-bio-post-setup/linkInBioPostSetup?siteSlug=site62798.wordpress.com',
31
+ },
32
+ {
33
+ id: 'plan_selected',
34
+ title: 'Choose a plan',
35
+ completed: true,
36
+ disabled: false,
37
+ subtitle: '',
38
+ badge_text: '',
39
+ isLaunchTask: false,
40
+ calypso_path: '/plans/site62798.wordpress.com',
41
+ },
42
+ {
43
+ id: 'links_added',
44
+ title: 'Add links',
45
+ completed: false,
46
+ disabled: false,
47
+ subtitle: '',
48
+ badge_text: '',
49
+ isLaunchTask: false,
50
+ calypso_path: '/site-editor/site62798.wordpress.com',
51
+ },
52
+ {
53
+ id: 'link_in_bio_launched',
54
+ title: 'Launch your site',
55
+ completed: false,
56
+ disabled: true,
57
+ subtitle: '',
58
+ badge_text: '',
59
+ isLaunchTask: false,
60
+ },
61
+ ],
62
+ is_enabled: true,
63
+ is_dismissed: false,
64
+ is_dismissible: false,
65
+ title: 'Next steps for your site',
66
+ };
@@ -0,0 +1,18 @@
1
+ import { HttpResponse, HttpResponseResolver, delay } from 'msw';
2
+ import linkInBio from './link-in-bio';
3
+ import free from './setup-free';
4
+
5
+ export const launchpadResolver: HttpResponseResolver = async ( { request } ) => {
6
+ const searchParams = new URL( request.url ).searchParams;
7
+ const checklistSlug = searchParams.get( 'checklist_slug' );
8
+
9
+ // Random delay to make the UI feel more realistic
10
+
11
+ await delay();
12
+
13
+ if ( checklistSlug === 'link-in-bio' ) {
14
+ return HttpResponse.json( linkInBio );
15
+ }
16
+
17
+ return HttpResponse.json( free );
18
+ };
@@ -0,0 +1,85 @@
1
+ export default {
2
+ site_intent: 'free',
3
+ launchpad_screen: 'full',
4
+ checklist_statuses: {
5
+ setup_free: true,
6
+ setup_general: true,
7
+ design_completed: true,
8
+ site_theme_selected: true,
9
+ },
10
+ checklist: [
11
+ {
12
+ id: 'plan_selected',
13
+ title: 'Choose a plan',
14
+ completed: true,
15
+ disabled: false,
16
+ subtitle: '',
17
+ badge_text: '',
18
+ isLaunchTask: false,
19
+ calypso_path: '/plans/site62798.wordpress.com',
20
+ },
21
+ {
22
+ id: 'setup_free',
23
+ title: 'Personalize your site',
24
+ completed: true,
25
+ disabled: false,
26
+ subtitle: '',
27
+ badge_text: '',
28
+ isLaunchTask: false,
29
+ calypso_path: '/settings/general/site62798.wordpress.com',
30
+ },
31
+ {
32
+ id: 'design_selected',
33
+ title: 'Select a design',
34
+ completed: true,
35
+ disabled: false,
36
+ subtitle: '',
37
+ badge_text: '',
38
+ isLaunchTask: false,
39
+ calypso_path: '/setup/update-design/designSetup?siteSlug=site62798.wordpress.com',
40
+ },
41
+ {
42
+ id: 'domain_upsell',
43
+ title: 'Choose a domain',
44
+ completed: false,
45
+ disabled: false,
46
+ subtitle: '',
47
+ badge_text: 'Upgrade plan',
48
+ isLaunchTask: false,
49
+ calypso_path: '/setup/domain-upsell/domains?siteSlug=site62798.wordpress.com',
50
+ },
51
+ {
52
+ id: 'first_post_published',
53
+ title: 'Write your first post',
54
+ completed: false,
55
+ disabled: false,
56
+ subtitle: '',
57
+ badge_text: '',
58
+ isLaunchTask: false,
59
+ calypso_path: '/post/site62798.wordpress.com',
60
+ },
61
+ {
62
+ id: 'design_edited',
63
+ title: 'Edit site design',
64
+ completed: false,
65
+ disabled: false,
66
+ subtitle: '',
67
+ badge_text: '',
68
+ isLaunchTask: false,
69
+ calypso_path: '/site-editor/site62798.wordpress.com',
70
+ },
71
+ {
72
+ id: 'site_launched',
73
+ title: 'Launch your site',
74
+ completed: false,
75
+ disabled: false,
76
+ subtitle: '',
77
+ badge_text: '',
78
+ isLaunchTask: true,
79
+ },
80
+ ],
81
+ is_enabled: true,
82
+ is_dismissed: false,
83
+ is_dismissible: false,
84
+ title: 'Next steps for your site',
85
+ };
@@ -1,5 +1,6 @@
1
1
  import config from '@automattic/calypso-config';
2
2
  import { updateLaunchpadSettings } from '@automattic/data-stores';
3
+ import { localizeUrl } from '@automattic/i18n-utils';
3
4
  import { isMobile } from '@automattic/viewport';
4
5
  import { addQueryArgs } from '@wordpress/url';
5
6
  import wpcomRequest from 'wpcom-proxy-request';
@@ -12,6 +13,10 @@ const TASKS_TO_COMPLETE_ON_CLICK = [
12
13
  'manage_subscribers',
13
14
  'connect_social_media',
14
15
  'drive_traffic',
16
+ 'site_monitoring_page',
17
+ 'front_page_updated',
18
+ 'post_sharing_enabled',
19
+ 'mobile_app_installed',
15
20
  ];
16
21
 
17
22
  export const setUpActionsForTasks = ( {
@@ -19,33 +24,23 @@ export const setUpActionsForTasks = ( {
19
24
  tasks,
20
25
  tracksData,
21
26
  extraActions,
27
+ eventHandlers,
22
28
  uiContext = 'calypso',
23
29
  }: LaunchpadTaskActionsProps ): Task[] => {
24
- const { recordTracksEvent, checklistSlug, tasklistCompleted, launchpadContext } = tracksData;
25
- const { setShareSiteModalIsOpen, siteLaunched, setActiveChecklist } = extraActions;
26
-
27
- //Record click events for tasks
28
- const recordTaskClickTracksEvent = ( task: Task ) => {
29
- recordTracksEvent( 'calypso_launchpad_task_clicked', {
30
- checklist_slug: checklistSlug,
31
- checklist_completed: tasklistCompleted,
32
- task_id: task.id,
33
- is_completed: task.completed,
34
- context: launchpadContext,
35
- order: task.order,
36
- } );
37
- };
30
+ const { recordTracksEvent, checklistSlug, launchpadContext } = tracksData;
31
+ const { setShareSiteModalIsOpen, setActiveChecklist } = extraActions;
32
+ const { onSiteLaunched, onTaskClick } = eventHandlers || {};
38
33
 
39
34
  // Add actions to the tasks.
40
35
  return tasks.map( ( task: Task ) => {
41
36
  let action: () => void;
42
37
  let logMissingCalypsoPath = false;
38
+ let useCalypsoPath = true;
39
+ const hasCalypsoPath = task.calypso_path !== undefined;
43
40
 
44
- if ( uiContext === 'calypso' && task.calypso_path !== undefined ) {
45
- let targetPath = task.calypso_path;
46
-
47
- if ( task.id === 'drive_traffic' && ! isMobile() ) {
48
- targetPath = addQueryArgs( targetPath, { tour: 'marketingConnectionsTour' } );
41
+ if ( uiContext === 'calypso' && hasCalypsoPath ) {
42
+ if ( task.id === 'drive_traffic' && ! isMobile() && hasCalypsoPath ) {
43
+ task.calypso_path = addQueryArgs( task.calypso_path, { tour: 'marketingConnectionsTour' } );
49
44
  }
50
45
 
51
46
  // Enable task in 'calypso' context
@@ -59,7 +54,6 @@ export const setUpActionsForTasks = ( {
59
54
  checklist_statuses: { [ task.id ]: true },
60
55
  } );
61
56
  }
62
- window.location.assign( targetPath );
63
57
  };
64
58
  } else {
65
59
  switch ( task.id ) {
@@ -67,66 +61,55 @@ export const setUpActionsForTasks = ( {
67
61
  action = () => {
68
62
  setShareSiteModalIsOpen?.( true );
69
63
  };
64
+ useCalypsoPath = false;
70
65
  break;
71
66
 
72
67
  case 'site_title':
73
68
  logMissingCalypsoPath = true;
74
- action = () => {
75
- window.location.assign( `/settings/general/${ siteSlug }` );
76
- };
69
+ task.calypso_path = `/settings/general/${ siteSlug }`;
77
70
  break;
78
71
 
79
72
  case 'domain_claim':
80
73
  case 'domain_upsell':
81
74
  case 'domain_customize':
82
75
  logMissingCalypsoPath = true;
83
- action = () => {
84
- window.location.assign( `/domains/add/${ siteSlug }` );
85
- };
76
+ task.calypso_path = `/domains/add/${ siteSlug }`;
86
77
  break;
78
+
87
79
  case 'drive_traffic':
88
80
  logMissingCalypsoPath = true;
89
- action = () => {
90
- const url = isMobile()
91
- ? `/marketing/connections/${ siteSlug }`
92
- : `/marketing/connections/${ siteSlug }?tour=marketingConnectionsTour`;
93
- window.location.assign( url );
94
- };
81
+ task.calypso_path = isMobile()
82
+ ? `/marketing/connections/${ siteSlug }`
83
+ : `/marketing/connections/${ siteSlug }?tour=marketingConnectionsTour`;
95
84
  break;
85
+
96
86
  case 'add_new_page':
97
87
  logMissingCalypsoPath = true;
98
- action = () => {
99
- window.location.assign( `/page/${ siteSlug }` );
100
- };
88
+ task.calypso_path = `/page/${ siteSlug }`;
101
89
  break;
90
+
102
91
  case 'edit_page':
103
92
  logMissingCalypsoPath = true;
104
- action = () => {
105
- window.location.assign( `/pages/${ siteSlug }` );
106
- };
93
+ task.calypso_path = `/pages/${ siteSlug }`;
107
94
  break;
95
+
108
96
  case 'update_about_page':
109
97
  logMissingCalypsoPath = true;
110
- action = () => {
111
- window.location.assign( `/page/${ siteSlug }/${ task?.extra_data?.about_page_id }` );
112
- };
98
+ task.calypso_path = `/page/${ siteSlug }/${ task?.extra_data?.about_page_id }`;
113
99
  break;
100
+
114
101
  case 'customize_welcome_message':
115
102
  logMissingCalypsoPath = true;
116
- action = () => {
117
- if ( config.isEnabled( 'settings/newsletter-settings-page' ) ) {
118
- window.location.assign( `/settings/newsletter/${ siteSlug }` );
119
- } else {
120
- window.location.assign( `/settings/reading/${ siteSlug }#newsletter-settings` );
121
- }
122
- };
103
+ task.calypso_path = config.isEnabled( 'settings/newsletter-settings-page' )
104
+ ? `/settings/newsletter/${ siteSlug }`
105
+ : `/settings/reading/${ siteSlug }#newsletter-settings`;
123
106
  break;
107
+
124
108
  case 'manage_subscribers':
125
109
  logMissingCalypsoPath = true;
126
- action = () => {
127
- window.location.assign( `/subscribers/${ siteSlug }` );
128
- };
110
+ task.calypso_path = `/subscribers/${ siteSlug }`;
129
111
  break;
112
+
130
113
  case 'site_launched':
131
114
  case 'blog_launched':
132
115
  case 'videopress_launched':
@@ -137,11 +120,37 @@ export const setUpActionsForTasks = ( {
137
120
  apiVersion: '1.1',
138
121
  method: 'post',
139
122
  } );
140
- siteLaunched?.();
123
+ onSiteLaunched?.();
141
124
  };
125
+ useCalypsoPath = false;
142
126
  break;
127
+
128
+ case 'review_site':
129
+ action = () => {
130
+ // redirects to the site slug home page in a new tab
131
+ window.open( `https://${ siteSlug }`, '_blank' );
132
+ updateLaunchpadSettings( siteSlug, {
133
+ checklist_statuses: { [ task.id ]: true },
134
+ } );
135
+ };
136
+ useCalypsoPath = false;
137
+ break;
138
+
139
+ case 'domain_dns_mapped':
140
+ action = () => {
141
+ window.open(
142
+ localizeUrl(
143
+ `https://wordpress.com/support/domains/connect-existing-domain/#step-2-connect-your-domain`
144
+ ),
145
+ '_blank'
146
+ );
147
+ };
148
+ useCalypsoPath = false;
149
+ break;
150
+
143
151
  default:
144
152
  logMissingCalypsoPath = true;
153
+ useCalypsoPath = false;
145
154
  break;
146
155
  }
147
156
  }
@@ -156,13 +165,17 @@ export const setUpActionsForTasks = ( {
156
165
  }
157
166
 
158
167
  const actionDispatch = () => {
159
- recordTaskClickTracksEvent( task );
160
- if ( siteSlug && setActiveChecklist ) {
168
+ if ( siteSlug && setActiveChecklist && config.isEnabled( 'launchpad/navigator' ) ) {
161
169
  setActiveChecklist( siteSlug, checklistSlug );
162
170
  }
171
+ onTaskClick?.( task );
163
172
  action?.();
164
173
  };
165
174
 
175
+ // Note that we double-check for both the flag and a valid calypso_path as a safety check.
176
+ // We intentionally avoid `hasCalypsoPath`, as it may be out of date.
177
+ task.useCalypsoPath = useCalypsoPath && task.calypso_path !== undefined;
178
+
166
179
  return { ...task, actionDispatch };
167
180
  } );
168
181
  };