diff --git a/packages/js/data/changelog/dev-migrate-onboarding-store-to-ts b/packages/js/data/changelog/dev-migrate-onboarding-store-to-ts
new file mode 100644
index 00000000000..7e955f6b2b1
--- /dev/null
+++ b/packages/js/data/changelog/dev-migrate-onboarding-store-to-ts
@@ -0,0 +1,4 @@
+Significance: minor
+Type: dev
+
+Migrate onboarding data store to TS
diff --git a/packages/js/data/src/onboarding/action-types.js b/packages/js/data/src/onboarding/action-types.ts
similarity index 99%
rename from packages/js/data/src/onboarding/action-types.js
rename to packages/js/data/src/onboarding/action-types.ts
index 4fb27c9950e..690016fbbb5 100644
--- a/packages/js/data/src/onboarding/action-types.js
+++ b/packages/js/data/src/onboarding/action-types.ts
@@ -36,6 +36,6 @@ const TYPES = {
VISITED_TASK: 'VISITED_TASK',
KEEP_COMPLETED_TASKS_REQUEST: 'KEEP_COMPLETED_TASKS_REQUEST',
KEEP_COMPLETED_TASKS_SUCCESS: 'KEEP_COMPLETED_TASKS_SUCCESS',
-};
+} as const;
export default TYPES;
diff --git a/packages/js/data/src/onboarding/actions.js b/packages/js/data/src/onboarding/actions.ts
similarity index 57%
rename from packages/js/data/src/onboarding/actions.js
rename to packages/js/data/src/onboarding/actions.ts
index bda9be7ffe1..8628f22031c 100644
--- a/packages/js/data/src/onboarding/actions.js
+++ b/packages/js/data/src/onboarding/actions.ts
@@ -11,22 +11,30 @@ import TYPES from './action-types';
import { WC_ADMIN_NAMESPACE } from '../constants';
import { DeprecatedTasks } from './deprecated-tasks';
import { STORE_NAME as OPTIONS_STORE_NAME } from '../options/constants';
+import {
+ ExtensionList,
+ ProfileItems,
+ TaskListType,
+ TaskType,
+ OnboardingProductType,
+} from './types';
+import { Plugin } from '../plugins/types';
-export function getFreeExtensionsError( error ) {
+export function getFreeExtensionsError( error: unknown ) {
return {
type: TYPES.GET_FREE_EXTENSIONS_ERROR,
error,
};
}
-export function getFreeExtensionsSuccess( freeExtensions ) {
+export function getFreeExtensionsSuccess( freeExtensions: ExtensionList[] ) {
return {
type: TYPES.GET_FREE_EXTENSIONS_SUCCESS,
freeExtensions,
};
}
-export function setError( selector, error ) {
+export function setError( selector: string, error: unknown ) {
return {
type: TYPES.SET_ERROR,
selector,
@@ -34,7 +42,7 @@ export function setError( selector, error ) {
};
}
-export function setIsRequesting( selector, isRequesting ) {
+export function setIsRequesting( selector: string, isRequesting: boolean ) {
return {
type: TYPES.SET_IS_REQUESTING,
selector,
@@ -42,7 +50,7 @@ export function setIsRequesting( selector, isRequesting ) {
};
}
-export function setProfileItems( profileItems, replace = false ) {
+export function setProfileItems( profileItems: ProfileItems, replace = false ) {
return {
type: TYPES.SET_PROFILE_ITEMS,
profileItems,
@@ -50,21 +58,21 @@ export function setProfileItems( profileItems, replace = false ) {
};
}
-export function getTaskListsError( error ) {
+export function getTaskListsError( error: unknown ) {
return {
type: TYPES.GET_TASK_LISTS_ERROR,
error,
};
}
-export function getTaskListsSuccess( taskLists ) {
+export function getTaskListsSuccess( taskLists: TaskListType[] ) {
return {
type: TYPES.GET_TASK_LISTS_SUCCESS,
taskLists,
};
}
-export function snoozeTaskError( taskId, error ) {
+export function snoozeTaskError( taskId: string, error: unknown ) {
return {
type: TYPES.SNOOZE_TASK_ERROR,
taskId,
@@ -72,21 +80,21 @@ export function snoozeTaskError( taskId, error ) {
};
}
-export function snoozeTaskRequest( taskId ) {
+export function snoozeTaskRequest( taskId: string ) {
return {
type: TYPES.SNOOZE_TASK_REQUEST,
taskId,
};
}
-export function snoozeTaskSuccess( task ) {
+export function snoozeTaskSuccess( task: Partial< TaskType > ) {
return {
type: TYPES.SNOOZE_TASK_SUCCESS,
task,
};
}
-export function undoSnoozeTaskError( taskId, error ) {
+export function undoSnoozeTaskError( taskId: string, error: unknown ) {
return {
type: TYPES.UNDO_SNOOZE_TASK_ERROR,
taskId,
@@ -94,21 +102,21 @@ export function undoSnoozeTaskError( taskId, error ) {
};
}
-export function undoSnoozeTaskRequest( taskId ) {
+export function undoSnoozeTaskRequest( taskId: string ) {
return {
type: TYPES.UNDO_SNOOZE_TASK_REQUEST,
taskId,
};
}
-export function undoSnoozeTaskSuccess( task ) {
+export function undoSnoozeTaskSuccess( task: Partial< TaskType > ) {
return {
type: TYPES.UNDO_SNOOZE_TASK_SUCCESS,
task,
};
}
-export function dismissTaskError( taskId, error ) {
+export function dismissTaskError( taskId: string, error: unknown ) {
return {
type: TYPES.DISMISS_TASK_ERROR,
taskId,
@@ -116,21 +124,21 @@ export function dismissTaskError( taskId, error ) {
};
}
-export function dismissTaskRequest( taskId ) {
+export function dismissTaskRequest( taskId: string ) {
return {
type: TYPES.DISMISS_TASK_REQUEST,
taskId,
};
}
-export function dismissTaskSuccess( task ) {
+export function dismissTaskSuccess( task: Partial< TaskType > ) {
return {
type: TYPES.DISMISS_TASK_SUCCESS,
task,
};
}
-export function undoDismissTaskError( taskId, error ) {
+export function undoDismissTaskError( taskId: string, error: unknown ) {
return {
type: TYPES.UNDO_DISMISS_TASK_ERROR,
taskId,
@@ -138,21 +146,21 @@ export function undoDismissTaskError( taskId, error ) {
};
}
-export function undoDismissTaskRequest( taskId ) {
+export function undoDismissTaskRequest( taskId: string ) {
return {
type: TYPES.UNDO_DISMISS_TASK_REQUEST,
taskId,
};
}
-export function undoDismissTaskSuccess( task ) {
+export function undoDismissTaskSuccess( task: Partial< TaskType > ) {
return {
type: TYPES.UNDO_DISMISS_TASK_SUCCESS,
task,
};
}
-export function hideTaskListError( taskListId, error ) {
+export function hideTaskListError( taskListId: string, error: unknown ) {
return {
type: TYPES.HIDE_TASK_LIST_ERROR,
taskListId,
@@ -160,14 +168,14 @@ export function hideTaskListError( taskListId, error ) {
};
}
-export function hideTaskListRequest( taskListId ) {
+export function hideTaskListRequest( taskListId: string ) {
return {
type: TYPES.HIDE_TASK_LIST_REQUEST,
taskListId,
};
}
-export function hideTaskListSuccess( taskList ) {
+export function hideTaskListSuccess( taskList: TaskListType ) {
return {
type: TYPES.HIDE_TASK_LIST_SUCCESS,
taskList,
@@ -175,7 +183,7 @@ export function hideTaskListSuccess( taskList ) {
};
}
-export function unhideTaskListError( taskListId, error ) {
+export function unhideTaskListError( taskListId: string, error: unknown ) {
return {
type: TYPES.UNHIDE_TASK_LIST_ERROR,
taskListId,
@@ -183,14 +191,14 @@ export function unhideTaskListError( taskListId, error ) {
};
}
-export function unhideTaskListRequest( taskListId ) {
+export function unhideTaskListRequest( taskListId: string ) {
return {
type: TYPES.UNHIDE_TASK_LIST_REQUEST,
taskListId,
};
}
-export function unhideTaskListSuccess( taskList ) {
+export function unhideTaskListSuccess( taskList: TaskListType ) {
return {
type: TYPES.UNHIDE_TASK_LIST_SUCCESS,
taskList,
@@ -198,14 +206,17 @@ export function unhideTaskListSuccess( taskList ) {
};
}
-export function optimisticallyCompleteTaskRequest( taskId ) {
+export function optimisticallyCompleteTaskRequest( taskId: string ) {
return {
type: TYPES.OPTIMISTICALLY_COMPLETE_TASK_REQUEST,
taskId,
};
}
-export function keepCompletedTaskListSuccess( taskListId, keepCompletedList ) {
+export function keepCompletedTaskListSuccess(
+ taskListId: string,
+ keepCompletedList: 'yes' | 'no'
+) {
return {
type: TYPES.KEEP_COMPLETED_TASKS_SUCCESS,
taskListId,
@@ -213,28 +224,28 @@ export function keepCompletedTaskListSuccess( taskListId, keepCompletedList ) {
};
}
-export function visitedTask( taskId ) {
+export function visitedTask( taskId: string ) {
return {
type: TYPES.VISITED_TASK,
taskId,
};
}
-export function setPaymentMethods( paymentMethods ) {
+export function setPaymentMethods( paymentMethods: Plugin[] ) {
return {
type: TYPES.GET_PAYMENT_METHODS_SUCCESS,
paymentMethods,
};
}
-export function setEmailPrefill( email ) {
+export function setEmailPrefill( email: string ) {
return {
type: TYPES.SET_EMAIL_PREFILL,
emailPrefill: email,
};
}
-export function actionTaskError( taskId, error ) {
+export function actionTaskError( taskId: string, error: unknown ) {
return {
type: TYPES.ACTION_TASK_ERROR,
taskId,
@@ -242,39 +253,43 @@ export function actionTaskError( taskId, error ) {
};
}
-export function actionTaskRequest( taskId ) {
+export function actionTaskRequest( taskId: string ) {
return {
type: TYPES.ACTION_TASK_REQUEST,
taskId,
};
}
-export function actionTaskSuccess( task ) {
+export function actionTaskSuccess( task: Partial< TaskType > ) {
return {
type: TYPES.ACTION_TASK_SUCCESS,
task,
};
}
-export function getProductTypesSuccess( productTypes ) {
+export function getProductTypesSuccess(
+ productTypes: OnboardingProductType[]
+) {
return {
type: TYPES.GET_PRODUCT_TYPES_SUCCESS,
productTypes,
};
}
-export function getProductTypesError( error ) {
+export function getProductTypesError( error: unknown ) {
return {
type: TYPES.GET_PRODUCT_TYPES_ERROR,
error,
};
}
-export function* keepCompletedTaskList( taskListId ) {
+export function* keepCompletedTaskList( taskListId: string ) {
const updateOptionsParams = {
woocommerce_task_list_keep_completed: 'yes',
};
- const response = yield controls.dispatch(
+ const response: {
+ success: 'yes' | 'no';
+ } = yield controls.dispatch(
OPTIONS_STORE_NAME,
'updateOptions',
updateOptionsParams
@@ -284,12 +299,15 @@ export function* keepCompletedTaskList( taskListId ) {
}
}
-export function* updateProfileItems( items ) {
+export function* updateProfileItems( items: ProfileItems ) {
yield setIsRequesting( 'updateProfileItems', true );
yield setError( 'updateProfileItems', null );
try {
- const results = yield apiFetch( {
+ const results: {
+ items: ProfileItems;
+ status: string;
+ } = yield apiFetch( {
path: `${ WC_ADMIN_NAMESPACE }/onboarding/profile`,
method: 'POST',
data: items,
@@ -309,11 +327,11 @@ export function* updateProfileItems( items ) {
}
}
-export function* snoozeTask( id ) {
+export function* snoozeTask( id: string ) {
yield snoozeTaskRequest( id );
try {
- const task = yield apiFetch( {
+ const task: TaskType = yield apiFetch( {
path: `${ WC_ADMIN_NAMESPACE }/onboarding/tasks/${ id }/snooze`,
method: 'POST',
} );
@@ -331,11 +349,11 @@ export function* snoozeTask( id ) {
}
}
-export function* undoSnoozeTask( id ) {
+export function* undoSnoozeTask( id: string ) {
yield undoSnoozeTaskRequest( id );
try {
- const task = yield apiFetch( {
+ const task: TaskType = yield apiFetch( {
path: `${ WC_ADMIN_NAMESPACE }/onboarding/tasks/${ id }/undo_snooze`,
method: 'POST',
} );
@@ -353,11 +371,11 @@ export function* undoSnoozeTask( id ) {
}
}
-export function* dismissTask( id ) {
+export function* dismissTask( id: string ) {
yield dismissTaskRequest( id );
try {
- const task = yield apiFetch( {
+ const task: TaskType = yield apiFetch( {
path: `${ WC_ADMIN_NAMESPACE }/onboarding/tasks/${ id }/dismiss`,
method: 'POST',
} );
@@ -374,11 +392,11 @@ export function* dismissTask( id ) {
}
}
-export function* undoDismissTask( id ) {
+export function* undoDismissTask( id: string ) {
yield undoDismissTaskRequest( id );
try {
- const task = yield apiFetch( {
+ const task: TaskType = yield apiFetch( {
path: `${ WC_ADMIN_NAMESPACE }/onboarding/tasks/${ id }/undo_dismiss`,
method: 'POST',
} );
@@ -395,11 +413,11 @@ export function* undoDismissTask( id ) {
}
}
-export function* hideTaskList( id ) {
+export function* hideTaskList( id: string ) {
yield hideTaskListRequest( id );
try {
- const taskList = yield apiFetch( {
+ const taskList: TaskListType = yield apiFetch( {
path: `${ WC_ADMIN_NAMESPACE }/onboarding/tasks/${ id }/hide`,
method: 'POST',
} );
@@ -411,11 +429,11 @@ export function* hideTaskList( id ) {
}
}
-export function* unhideTaskList( id ) {
+export function* unhideTaskList( id: string ) {
yield unhideTaskListRequest( id );
try {
- const taskList = yield apiFetch( {
+ const taskList: TaskListType = yield apiFetch( {
path: `${ WC_ADMIN_NAMESPACE }/onboarding/tasks/${ id }/unhide`,
method: 'POST',
} );
@@ -427,15 +445,15 @@ export function* unhideTaskList( id ) {
}
}
-export function* optimisticallyCompleteTask( id ) {
+export function* optimisticallyCompleteTask( id: string ) {
yield optimisticallyCompleteTaskRequest( id );
}
-export function* actionTask( id ) {
+export function* actionTask( id: string ) {
yield actionTaskRequest( id );
try {
- const task = yield apiFetch( {
+ const task: TaskType = yield apiFetch( {
path: `${ WC_ADMIN_NAMESPACE }/onboarding/tasks/${ id }/action`,
method: 'POST',
} );
@@ -448,3 +466,41 @@ export function* actionTask( id ) {
throw new Error();
}
}
+
+export type Action = ReturnType<
+ | typeof getFreeExtensionsError
+ | typeof getFreeExtensionsSuccess
+ | typeof setError
+ | typeof setIsRequesting
+ | typeof setProfileItems
+ | typeof snoozeTaskRequest
+ | typeof snoozeTaskSuccess
+ | typeof snoozeTaskError
+ | typeof getTaskListsError
+ | typeof getTaskListsSuccess
+ | typeof undoSnoozeTaskError
+ | typeof undoSnoozeTaskSuccess
+ | typeof dismissTaskError
+ | typeof dismissTaskSuccess
+ | typeof dismissTaskRequest
+ | typeof undoDismissTaskError
+ | typeof undoDismissTaskSuccess
+ | typeof undoDismissTaskRequest
+ | typeof undoSnoozeTaskRequest
+ | typeof hideTaskListError
+ | typeof hideTaskListSuccess
+ | typeof hideTaskListRequest
+ | typeof unhideTaskListError
+ | typeof unhideTaskListSuccess
+ | typeof unhideTaskListRequest
+ | typeof optimisticallyCompleteTaskRequest
+ | typeof keepCompletedTaskListSuccess
+ | typeof visitedTask
+ | typeof setPaymentMethods
+ | typeof setEmailPrefill
+ | typeof actionTaskError
+ | typeof actionTaskSuccess
+ | typeof actionTaskRequest
+ | typeof getProductTypesError
+ | typeof getProductTypesSuccess
+>;
diff --git a/packages/js/data/src/onboarding/deprecated-tasks.js b/packages/js/data/src/onboarding/deprecated-tasks.ts
similarity index 87%
rename from packages/js/data/src/onboarding/deprecated-tasks.js
rename to packages/js/data/src/onboarding/deprecated-tasks.ts
index 50958b5d736..e00783d41dd 100644
--- a/packages/js/data/src/onboarding/deprecated-tasks.js
+++ b/packages/js/data/src/onboarding/deprecated-tasks.ts
@@ -5,6 +5,11 @@ import { applyFilters } from '@wordpress/hooks';
import { parse } from 'qs';
import deprecated from '@wordpress/deprecated';
+/**
+ * Internal dependencies
+ */
+import { TaskListType, TaskType, DeprecatedTaskType } from './types';
+
function getQuery() {
const searchString = window.location && window.location.search;
if ( ! searchString ) {
@@ -19,6 +24,11 @@ function getQuery() {
* A simple class to handle deprecated tasks using the woocommerce_admin_onboarding_task_list filter.
*/
export class DeprecatedTasks {
+ filteredTasks: DeprecatedTaskType[];
+ tasks: {
+ [ key: string ]: DeprecatedTaskType[];
+ };
+
constructor() {
/**
* **Deprecated** Filter Onboarding tasks.
@@ -32,7 +42,7 @@ export class DeprecatedTasks {
'woocommerce_admin_onboarding_task_list',
[],
getQuery()
- );
+ ) as DeprecatedTaskType[];
if ( this.filteredTasks && this.filteredTasks.length > 0 ) {
deprecated( 'woocommerce_admin_onboarding_task_list', {
version: '2.10.0',
@@ -72,7 +82,7 @@ export class DeprecatedTasks {
: null;
}
- mergeDeprecatedCallbackFunctions( taskLists ) {
+ mergeDeprecatedCallbackFunctions( taskLists: TaskListType[] ) {
if ( this.filteredTasks.length > 0 ) {
for ( const taskList of taskLists ) {
// Merge any extended task list items, to keep the callback functions around.
@@ -99,10 +109,10 @@ export class DeprecatedTasks {
* @param {Array} keys to keep in the task object.
* @return {Object} task with the keys specified.
*/
- static possiblyPruneTaskData( task, keys ) {
+ static possiblyPruneTaskData( task: TaskType, keys: ( keyof TaskType )[] ) {
if ( ! task.time && ! task.title ) {
// client side task
- return keys.reduce(
+ return keys.reduce< Partial< TaskType > >(
( simplifiedTask, key ) => {
return {
...simplifiedTask,
diff --git a/packages/js/data/src/onboarding/index.ts b/packages/js/data/src/onboarding/index.ts
index d2b84f7afb3..a1e5b73193d 100644
--- a/packages/js/data/src/onboarding/index.ts
+++ b/packages/js/data/src/onboarding/index.ts
@@ -1,12 +1,10 @@
/**
* External dependencies
*/
-
import { registerStore } from '@wordpress/data';
import { controls } from '@wordpress/data-controls';
import { SelectFromMap, DispatchFromMap } from '@automattic/data-stores';
import { Reducer, AnyAction } from 'redux';
-
/**
* Internal dependencies
*/
@@ -14,11 +12,13 @@ import { STORE_NAME } from './constants';
import * as selectors from './selectors';
import * as actions from './actions';
import * as resolvers from './resolvers';
-import reducer from './reducer';
-import { WPDataSelectors } from '../types';
+import reducer, { State } from './reducer';
+import { WPDataActions, WPDataSelectors } from '../types';
+export * from './types';
+export type { State };
-registerStore( STORE_NAME, {
- reducer: reducer as Reducer< ReturnType< Reducer >, AnyAction >,
+registerStore< State >( STORE_NAME, {
+ reducer: reducer as Reducer< State, AnyAction >,
actions,
controls,
selectors,
@@ -27,12 +27,12 @@ registerStore( STORE_NAME, {
export const ONBOARDING_STORE_NAME = STORE_NAME;
-export type OnboardingSelector = SelectFromMap< typeof selectors >;
+export type OnboardingSelector = SelectFromMap< typeof selectors > &
+ WPDataSelectors;
declare module '@wordpress/data' {
- // TODO: convert action.js to TS
- function dispatch( key: typeof STORE_NAME ): DispatchFromMap< AnyAction >;
- function select(
+ function dispatch(
key: typeof STORE_NAME
- ): SelectFromMap< typeof selectors > & WPDataSelectors;
+ ): DispatchFromMap< typeof actions & WPDataActions >;
+ function select( key: typeof STORE_NAME ): OnboardingSelector;
}
diff --git a/packages/js/data/src/onboarding/reducer.js b/packages/js/data/src/onboarding/reducer.ts
similarity index 73%
rename from packages/js/data/src/onboarding/reducer.js
rename to packages/js/data/src/onboarding/reducer.ts
index c7c1e84c424..206007aedde 100644
--- a/packages/js/data/src/onboarding/reducer.js
+++ b/packages/js/data/src/onboarding/reducer.ts
@@ -1,9 +1,17 @@
+/**
+ * External dependencies
+ */
+
+import type { Reducer } from 'redux';
+
/**
* Internal dependencies
*/
import TYPES from './action-types';
+import { Action } from './actions';
+import { OnboardingState, TaskListType, TaskType } from './types';
-export const defaultState = {
+export const defaultState: OnboardingState = {
errors: {},
freeExtensions: [],
profileItems: {
@@ -31,7 +39,10 @@ export const defaultState = {
taskLists: {},
};
-const getUpdatedTaskLists = ( taskLists, args ) => {
+const getUpdatedTaskLists = (
+ taskLists: Record< string, TaskListType >,
+ args: Partial< TaskType >
+) => {
return Object.keys( taskLists ).reduce(
( lists, taskListId ) => {
return {
@@ -54,46 +65,29 @@ const getUpdatedTaskLists = ( taskLists, args ) => {
);
};
-const onboarding = (
+const reducer: Reducer< OnboardingState, Action > = (
state = defaultState,
- {
- freeExtensions,
- type,
- profileItems,
- emailPrefill,
- paymentMethods,
- productTypes,
- replace,
- error,
- isRequesting,
- selector,
- task,
- taskId,
- taskListId,
- taskList,
- taskLists,
- keepCompletedTaskList,
- }
+ action
) => {
- switch ( type ) {
+ switch ( action.type ) {
case TYPES.SET_PROFILE_ITEMS:
return {
...state,
- profileItems: replace
- ? profileItems
- : { ...state.profileItems, ...profileItems },
+ profileItems: action.replace
+ ? action.profileItems
+ : { ...state.profileItems, ...action.profileItems },
};
case TYPES.SET_EMAIL_PREFILL:
return {
...state,
- emailPrefill,
+ emailPrefill: action.emailPrefill,
};
case TYPES.SET_ERROR:
return {
...state,
errors: {
...state.errors,
- [ selector ]: error,
+ [ action.selector ]: action.error,
},
};
case TYPES.SET_IS_REQUESTING:
@@ -101,25 +95,25 @@ const onboarding = (
...state,
requesting: {
...state.requesting,
- [ selector ]: isRequesting,
+ [ action.selector ]: action.isRequesting,
},
};
case TYPES.GET_PAYMENT_METHODS_SUCCESS:
return {
...state,
- paymentMethods,
+ paymentMethods: action.paymentMethods,
};
case TYPES.GET_PRODUCT_TYPES_SUCCESS:
return {
...state,
- productTypes,
+ productTypes: action.productTypes,
};
case TYPES.GET_PRODUCT_TYPES_ERROR:
return {
...state,
errors: {
...state.errors,
- productTypes: error,
+ productTypes: action.error,
},
};
case TYPES.GET_FREE_EXTENSIONS_ERROR:
@@ -127,26 +121,26 @@ const onboarding = (
...state,
errors: {
...state.errors,
- getFreeExtensions: error,
+ getFreeExtensions: action.error,
},
};
case TYPES.GET_FREE_EXTENSIONS_SUCCESS:
return {
...state,
- freeExtensions,
+ freeExtensions: action.freeExtensions,
};
case TYPES.GET_TASK_LISTS_ERROR:
return {
...state,
errors: {
...state.errors,
- getTaskLists: error,
+ getTaskLists: action.error,
},
};
case TYPES.GET_TASK_LISTS_SUCCESS:
return {
...state,
- taskLists: taskLists.reduce( ( lists, list ) => {
+ taskLists: action.taskLists.reduce( ( lists, list ) => {
return {
...lists,
[ list.id ]: list,
@@ -158,10 +152,10 @@ const onboarding = (
...state,
errors: {
...state.errors,
- dismissTask: error,
+ dismissTask: action.error,
},
taskLists: getUpdatedTaskLists( state.taskLists, {
- id: taskId,
+ id: action.taskId,
isDismissed: false,
} ),
};
@@ -173,7 +167,7 @@ const onboarding = (
dismissTask: true,
},
taskLists: getUpdatedTaskLists( state.taskLists, {
- id: taskId,
+ id: action.taskId,
isDismissed: true,
} ),
};
@@ -184,17 +178,17 @@ const onboarding = (
...state.requesting,
dismissTask: false,
},
- taskLists: getUpdatedTaskLists( state.taskLists, task ),
+ taskLists: getUpdatedTaskLists( state.taskLists, action.task ),
};
case TYPES.UNDO_DISMISS_TASK_ERROR:
return {
...state,
errors: {
...state.errors,
- undoDismissTask: error,
+ undoDismissTask: action.error,
},
taskLists: getUpdatedTaskLists( state.taskLists, {
- id: taskId,
+ id: action.taskId,
isDismissed: true,
} ),
};
@@ -206,7 +200,7 @@ const onboarding = (
undoDismissTask: true,
},
taskLists: getUpdatedTaskLists( state.taskLists, {
- id: taskId,
+ id: action.taskId,
isDismissed: false,
} ),
};
@@ -217,17 +211,17 @@ const onboarding = (
...state.requesting,
undoDismissTask: false,
},
- taskLists: getUpdatedTaskLists( state.taskLists, task ),
+ taskLists: getUpdatedTaskLists( state.taskLists, action.task ),
};
case TYPES.SNOOZE_TASK_ERROR:
return {
...state,
errors: {
...state.errors,
- snoozeTask: error,
+ snoozeTask: action.error,
},
taskLists: getUpdatedTaskLists( state.taskLists, {
- id: taskId,
+ id: action.taskId,
isSnoozed: false,
} ),
};
@@ -239,7 +233,7 @@ const onboarding = (
snoozeTask: true,
},
taskLists: getUpdatedTaskLists( state.taskLists, {
- id: taskId,
+ id: action.taskId,
isSnoozed: true,
} ),
};
@@ -250,17 +244,17 @@ const onboarding = (
...state.requesting,
snoozeTask: false,
},
- taskLists: getUpdatedTaskLists( state.taskLists, task ),
+ taskLists: getUpdatedTaskLists( state.taskLists, action.task ),
};
case TYPES.UNDO_SNOOZE_TASK_ERROR:
return {
...state,
errors: {
...state.errors,
- undoSnoozeTask: error,
+ undoSnoozeTask: action.error,
},
taskLists: getUpdatedTaskLists( state.taskLists, {
- id: taskId,
+ id: action.taskId,
isSnoozed: true,
} ),
};
@@ -272,7 +266,7 @@ const onboarding = (
undoSnoozeTask: true,
},
taskLists: getUpdatedTaskLists( state.taskLists, {
- id: taskId,
+ id: action.taskId,
isSnoozed: false,
} ),
};
@@ -283,19 +277,19 @@ const onboarding = (
...state.requesting,
undoSnoozeTask: false,
},
- taskLists: getUpdatedTaskLists( state.taskLists, task ),
+ taskLists: getUpdatedTaskLists( state.taskLists, action.task ),
};
case TYPES.HIDE_TASK_LIST_ERROR:
return {
...state,
errors: {
...state.errors,
- hideTaskList: error,
+ hideTaskList: action.error,
},
taskLists: {
...state.taskLists,
- [ taskListId ]: {
- ...state.taskLists[ taskListId ],
+ [ action.taskListId ]: {
+ ...state.taskLists[ action.taskListId ],
isHidden: false,
isVisible: true,
},
@@ -310,8 +304,8 @@ const onboarding = (
},
taskLists: {
...state.taskLists,
- [ taskListId ]: {
- ...state.taskLists[ taskListId ],
+ [ action.taskListId ]: {
+ ...state.taskLists[ action.taskListId ],
isHidden: true,
isVisible: false,
},
@@ -326,7 +320,7 @@ const onboarding = (
},
taskLists: {
...state.taskLists,
- [ taskListId ]: taskList,
+ [ action.taskListId ]: action.taskList,
},
};
case TYPES.UNHIDE_TASK_LIST_ERROR:
@@ -334,12 +328,12 @@ const onboarding = (
...state,
errors: {
...state.errors,
- unhideTaskList: error,
+ unhideTaskList: action.error,
},
taskLists: {
...state.taskLists,
- [ taskListId ]: {
- ...state.taskLists[ taskListId ],
+ [ action.taskListId ]: {
+ ...state.taskLists[ action.taskListId ],
isHidden: true,
isVisible: false,
},
@@ -354,8 +348,8 @@ const onboarding = (
},
taskLists: {
...state.taskLists,
- [ taskListId ]: {
- ...state.taskLists[ taskListId ],
+ [ action.taskListId ]: {
+ ...state.taskLists[ action.taskListId ],
isHidden: false,
isVisible: true,
},
@@ -370,7 +364,7 @@ const onboarding = (
},
taskLists: {
...state.taskLists,
- [ taskListId ]: taskList,
+ [ action.taskListId ]: action.taskList,
},
};
case TYPES.KEEP_COMPLETED_TASKS_SUCCESS:
@@ -378,9 +372,9 @@ const onboarding = (
...state,
taskLists: {
...state.taskLists,
- [ taskListId ]: {
- ...state.taskLists[ taskListId ],
- keepCompletedTaskList,
+ [ action.taskListId ]: {
+ ...state.taskLists[ action.taskListId ],
+ keepCompletedTaskList: action.keepCompletedTaskList,
},
},
};
@@ -388,7 +382,7 @@ const onboarding = (
return {
...state,
taskLists: getUpdatedTaskLists( state.taskLists, {
- id: taskId,
+ id: action.taskId,
isComplete: true,
} ),
};
@@ -396,7 +390,7 @@ const onboarding = (
return {
...state,
taskLists: getUpdatedTaskLists( state.taskLists, {
- id: taskId,
+ id: action.taskId,
isVisited: true,
} ),
};
@@ -405,10 +399,10 @@ const onboarding = (
...state,
errors: {
...state.errors,
- actionTask: error,
+ actionTask: action.error,
},
taskLists: getUpdatedTaskLists( state.taskLists, {
- id: taskId,
+ id: action.taskId,
isActioned: false,
} ),
};
@@ -420,7 +414,7 @@ const onboarding = (
actionTask: true,
},
taskLists: getUpdatedTaskLists( state.taskLists, {
- id: taskId,
+ id: action.taskId,
isActioned: true,
} ),
};
@@ -431,11 +425,12 @@ const onboarding = (
...state.requesting,
actionTask: false,
},
- taskLists: getUpdatedTaskLists( state.taskLists, task ),
+ taskLists: getUpdatedTaskLists( state.taskLists, action.task ),
};
default:
return state;
}
};
-export default onboarding;
+export type State = ReturnType< typeof reducer >;
+export default reducer;
diff --git a/packages/js/data/src/onboarding/resolvers.js b/packages/js/data/src/onboarding/resolvers.ts
similarity index 84%
rename from packages/js/data/src/onboarding/resolvers.js
rename to packages/js/data/src/onboarding/resolvers.ts
index 466a2109625..ef9b03ed38b 100644
--- a/packages/js/data/src/onboarding/resolvers.js
+++ b/packages/js/data/src/onboarding/resolvers.ts
@@ -22,13 +22,20 @@ import {
getProductTypesError,
} from './actions';
import { DeprecatedTasks } from './deprecated-tasks';
+import {
+ ExtensionList,
+ OnboardingProductType,
+ ProfileItems,
+ TaskListType,
+} from './types';
+import { Plugin } from '../plugins/types';
const resolveSelect =
controls && controls.resolveSelect ? controls.resolveSelect : select;
export function* getProfileItems() {
try {
- const results = yield apiFetch( {
+ const results: ProfileItems = yield apiFetch( {
path: WC_ADMIN_NAMESPACE + '/onboarding/profile',
method: 'GET',
} );
@@ -41,7 +48,9 @@ export function* getProfileItems() {
export function* getEmailPrefill() {
try {
- const results = yield apiFetch( {
+ const results: {
+ email: string;
+ } = yield apiFetch( {
path:
WC_ADMIN_NAMESPACE +
'/onboarding/profile/experimental_get_email_prefill',
@@ -57,7 +66,7 @@ export function* getEmailPrefill() {
export function* getTaskLists() {
const deprecatedTasks = new DeprecatedTasks();
try {
- const results = yield apiFetch( {
+ const results: TaskListType[] = yield apiFetch( {
path: WC_ADMIN_NAMESPACE + '/onboarding/tasks',
method: deprecatedTasks.hasDeprecatedTasks() ? 'POST' : 'GET',
data: deprecatedTasks.getPostData(),
@@ -85,7 +94,7 @@ export function* getTask() {
export function* getPaymentGatewaySuggestions() {
try {
- const results = yield apiFetch( {
+ const results: Plugin[] = yield apiFetch( {
path: WC_ADMIN_NAMESPACE + '/payment-gateway-suggestions',
method: 'GET',
} );
@@ -98,7 +107,7 @@ export function* getPaymentGatewaySuggestions() {
export function* getFreeExtensions() {
try {
- const results = yield apiFetch( {
+ const results: ExtensionList[] = yield apiFetch( {
path: WC_ADMIN_NAMESPACE + '/onboarding/free-extensions',
method: 'GET',
} );
@@ -111,7 +120,7 @@ export function* getFreeExtensions() {
export function* getProductTypes() {
try {
- const results = yield apiFetch( {
+ const results: OnboardingProductType[] = yield apiFetch( {
path: WC_ADMIN_NAMESPACE + '/onboarding/product-types',
method: 'GET',
} );
diff --git a/packages/js/data/src/onboarding/selectors.ts b/packages/js/data/src/onboarding/selectors.ts
index 5647a048650..b73c1111211 100644
--- a/packages/js/data/src/onboarding/selectors.ts
+++ b/packages/js/data/src/onboarding/selectors.ts
@@ -11,7 +11,7 @@ import {
TaskListType,
OnboardingState,
ExtensionList,
- ProfileItemsState,
+ ProfileItems,
OnboardingProductType,
} from './types';
import { WPDataSelectors } from '../types';
@@ -25,7 +25,7 @@ export const getFreeExtensions = (
export const getProfileItems = (
state: OnboardingState
-): ProfileItemsState | Record< string, never > => {
+): ProfileItems | Record< string, never > => {
return state.profileItems || {};
};
diff --git a/packages/js/data/src/onboarding/test/reducer.js b/packages/js/data/src/onboarding/test/reducer.ts
similarity index 52%
rename from packages/js/data/src/onboarding/test/reducer.js
rename to packages/js/data/src/onboarding/test/reducer.ts
index d7b2efbff84..64074e86117 100644
--- a/packages/js/data/src/onboarding/test/reducer.js
+++ b/packages/js/data/src/onboarding/test/reducer.ts
@@ -8,8 +8,40 @@
import reducer, { defaultState } from '../reducer';
import TYPES from '../action-types';
+const profileItems = {
+ business_extensions: [],
+ completed: false,
+ industry: null,
+ number_employees: null,
+ other_platform: null,
+ other_platform_name: '',
+ product_count: null,
+ product_types: null,
+ revenue: null,
+ selling_venues: null,
+ setup_client: false,
+ skipped: true,
+ theme: null,
+ wccom_connected: null,
+ is_agree_marketing: null,
+ store_email: null,
+};
+
+const paymentMethods = [
+ {
+ id: '',
+ content: '',
+ plugins: [],
+ title: '',
+ category_additional: [],
+ category_other: [],
+ image: '',
+ },
+];
+
describe( 'plugins reducer', () => {
it( 'should return a default state', () => {
+ // @ts-expect-error - we're testing the default state
const state = reducer( undefined, {} );
expect( state ).toEqual( defaultState );
} );
@@ -17,52 +49,53 @@ describe( 'plugins reducer', () => {
it( 'should handle SET_PROFILE_ITEMS', () => {
const state = reducer(
{
- profileItems: { previousItem: 'value' },
+ // @ts-expect-error - we're only testing profileItems
+ profileItems,
},
{
type: TYPES.SET_PROFILE_ITEMS,
- profileItems: { propertyName: 'value' },
+ profileItems: { is_agree_marketing: true },
}
);
- expect( state.profileItems ).toHaveProperty( 'previousItem' );
- expect( state.profileItems ).toHaveProperty( 'propertyName' );
- expect( state.profileItems.propertyName ).toBe( 'value' );
+ expect( state.profileItems.is_agree_marketing ).toBe( true );
} );
it( 'should handle SET_PROFILE_ITEMS with replace', () => {
const state = reducer(
{
- profileItems: { previousItem: 'value' },
+ // @ts-expect-error - we're only testing profileItems
+ profileItems,
},
{
type: TYPES.SET_PROFILE_ITEMS,
- profileItems: { propertyName: 'value' },
+ profileItems: { is_agree_marketing: true },
replace: true,
}
);
- expect( state.profileItems ).not.toHaveProperty( 'previousItem' );
- expect( state.profileItems ).toHaveProperty( 'propertyName' );
- expect( state.profileItems.propertyName ).toBe( 'value' );
+ expect( state.profileItems ).not.toHaveProperty( 'store_email' );
+ expect( state.profileItems ).toHaveProperty( 'is_agree_marketing' );
+ expect( state.profileItems.is_agree_marketing ).toBe( true );
} );
it( 'should handle GET_PAYMENT_METHODS_SUCCESS', () => {
const state = reducer(
+ // @ts-expect-error - we're only testing paymentMethods
{
- paymentMethods: [ { previousItem: 'value' } ],
+ paymentMethods,
},
{
type: TYPES.GET_PAYMENT_METHODS_SUCCESS,
- paymentMethods: [ { newItem: 'changed' } ],
+ paymentMethods: [ { image_72x72: 'changed' } ],
}
);
expect( state.paymentMethods[ 0 ] ).not.toHaveProperty(
'previousItem'
);
- expect( state.paymentMethods[ 0 ] ).toHaveProperty( 'newItem' );
- expect( state.paymentMethods[ 0 ].newItem ).toBe( 'changed' );
+ expect( state.paymentMethods[ 0 ] ).toHaveProperty( 'image_72x72' );
+ expect( state.paymentMethods[ 0 ].image_72x72 ).toBe( 'changed' );
} );
it( 'should handle SET_ERROR', () => {
@@ -73,6 +106,7 @@ describe( 'plugins reducer', () => {
} );
/* eslint-disable dot-notation */
+ // @ts-expect-error we're asserting error properties
expect( state.errors[ 'getProfileItems' ].code ).toBe( 'error' );
/* eslint-enable dot-notation */
} );
diff --git a/packages/js/data/src/onboarding/types.ts b/packages/js/data/src/onboarding/types.ts
index 2bc05fafcc5..a41a295ba18 100644
--- a/packages/js/data/src/onboarding/types.ts
+++ b/packages/js/data/src/onboarding/types.ts
@@ -30,6 +30,27 @@ export type TaskType = {
taxJarActivated?: boolean;
avalaraActivated?: boolean;
};
+ // Possibly added in DeprecatedTasks.mergeDeprecatedCallbackFunctions
+ isDeprecated?: boolean;
+};
+
+// reference: https://github.com/woocommerce/woocommerce-admin/blob/75cf5292f66bf69202f67356d143743a8796a7f6/docs/examples/extensions/add-task/js/index.js#L77-L101
+export type DeprecatedTaskType = {
+ key: string;
+ title: string;
+ content: string;
+ container: React.ReactNode;
+ completed: boolean;
+ visible: boolean;
+ additionalInfo: string;
+ time: string;
+ isDismissable: boolean;
+ onDelete: () => void;
+ onDismiss: () => void;
+ allowRemindMeLater: string;
+ remindMeLater: () => () => void;
+ level?: string;
+ type?: string;
};
export type TaskListSection = {
@@ -60,7 +81,7 @@ export type TaskListType = {
export type OnboardingState = {
freeExtensions: ExtensionList[];
- profileItems: ProfileItemsState;
+ profileItems: ProfileItems;
taskLists: Record< string, TaskListType >;
paymentMethods: Plugin[];
productTypes: OnboardingProductType[];
@@ -104,7 +125,7 @@ export type RevenueTypeSlug =
| '50000-250000'
| 'more-than-250000';
-export type ProfileItemsState = {
+export type ProfileItems = {
business_extensions: [ ] | null;
completed: boolean | null;
industry: Industry[] | null;
diff --git a/packages/js/data/src/onboarding/with-onboarding-hydration.js b/packages/js/data/src/onboarding/with-onboarding-hydration.js
deleted file mode 100644
index b36032bee38..00000000000
--- a/packages/js/data/src/onboarding/with-onboarding-hydration.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * External dependencies
- */
-import { createHigherOrderComponent } from '@wordpress/compose';
-import { useSelect } from '@wordpress/data';
-import { createElement, useRef } from '@wordpress/element';
-
-/**
- * Internal dependencies
- */
-import { STORE_NAME } from './constants';
-
-export const withOnboardingHydration = ( data ) => {
- let hydratedProfileItems = false;
-
- return createHigherOrderComponent(
- ( OriginalComponent ) => ( props ) => {
- const onboardingRef = useRef( data );
-
- useSelect( ( select, registry ) => {
- if ( ! onboardingRef.current ) {
- return;
- }
-
- const { isResolving, hasFinishedResolution } = select(
- STORE_NAME
- );
- const {
- startResolution,
- finishResolution,
- setProfileItems,
- } = registry.dispatch( STORE_NAME );
-
- const { profileItems } = onboardingRef.current;
-
- if (
- profileItems &&
- ! hydratedProfileItems &&
- ! isResolving( 'getProfileItems', [] ) &&
- ! hasFinishedResolution( 'getProfileItems', [] )
- ) {
- startResolution( 'getProfileItems', [] );
- setProfileItems( profileItems, true );
- finishResolution( 'getProfileItems', [] );
-
- hydratedProfileItems = true;
- }
- }, [] );
-
- return ;
- },
- 'withOnboardingHydration'
- );
-};
diff --git a/packages/js/data/src/onboarding/with-onboarding-hydration.tsx b/packages/js/data/src/onboarding/with-onboarding-hydration.tsx
new file mode 100644
index 00000000000..914d01f9fda
--- /dev/null
+++ b/packages/js/data/src/onboarding/with-onboarding-hydration.tsx
@@ -0,0 +1,62 @@
+/**
+ * External dependencies
+ */
+import { createHigherOrderComponent } from '@wordpress/compose';
+import { useSelect } from '@wordpress/data';
+import { createElement, useRef } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import { STORE_NAME } from './constants';
+import { ProfileItems } from './types';
+import { OnboardingSelector } from './';
+
+export const withOnboardingHydration = ( data: {
+ profileItems: ProfileItems;
+} ) => {
+ let hydratedProfileItems = false;
+
+ return createHigherOrderComponent< Record< string, unknown > >(
+ ( OriginalComponent ) => ( props ) => {
+ const onboardingRef = useRef( data );
+
+ useSelect(
+ // @ts-expect-error // @ts-expect-error registry is not defined in the wp.data typings
+ ( select: ( s: string ) => OnboardingSelector, registry ) => {
+ if ( ! onboardingRef.current ) {
+ return;
+ }
+
+ const { isResolving, hasFinishedResolution } = select(
+ STORE_NAME
+ );
+ const {
+ startResolution,
+ finishResolution,
+ setProfileItems,
+ } = registry.dispatch( STORE_NAME );
+
+ const { profileItems } = onboardingRef.current;
+
+ if (
+ profileItems &&
+ ! hydratedProfileItems &&
+ ! isResolving( 'getProfileItems', [] ) &&
+ ! hasFinishedResolution( 'getProfileItems', [] )
+ ) {
+ startResolution( 'getProfileItems', [] );
+ setProfileItems( profileItems, true );
+ finishResolution( 'getProfileItems', [] );
+
+ hydratedProfileItems = true;
+ }
+ },
+ []
+ );
+
+ return ;
+ },
+ 'withOnboardingHydration'
+ );
+};
diff --git a/packages/js/data/src/types/wp-data.ts b/packages/js/data/src/types/wp-data.ts
index 22e04f270f2..46b5287fc6b 100644
--- a/packages/js/data/src/types/wp-data.ts
+++ b/packages/js/data/src/types/wp-data.ts
@@ -1,15 +1,24 @@
// Type for the basic selectors built into @wordpress/data, note these
// types define the interface for the public selectors, so state is not an
// argument.
+// [wp.data.getSelectors](https://github.com/WordPress/gutenberg/blob/319deee5f4d4838d6bc280e9e2be89c7f43f2509/packages/data/src/store/index.js#L16-L20)
+// [selector.js](https://github.com/WordPress/gutenberg/blob/trunk/packages/data/src/redux-store/metadata/selectors.js#L48-L52)
export type WPDataSelectors = {
+ getIsResolving: ( selector: string, args?: string[] ) => boolean;
hasStartedResolution: ( selector: string, args?: string[] ) => boolean;
hasFinishedResolution: ( selector: string, args?: string[] ) => boolean;
isResolving: ( selector: string, args?: string[] ) => boolean;
+ getCachedResolvers: () => unknown;
};
+// [wp.data.getActions](https://github.com/WordPress/gutenberg/blob/319deee5f4d4838d6bc280e9e2be89c7f43f2509/packages/data/src/store/index.js#L31-L35)
+// [actions.js](https://github.com/WordPress/gutenberg/blob/aa2bed9010aa50467cb43063e370b70a91591e9b/packages/data/src/redux-store/metadata/actions.js)
export type WPDataActions = {
startResolution: ( selector: string, args?: string[] ) => void;
finishResolution: ( selector: string, args?: string[] ) => void;
+ invalidateResolution: ( selector: string ) => void;
+ invalidateResolutionForStore: ( selector: string ) => void;
+ invalidateResolutionForStoreSelector: ( selector: string ) => void;
};
// Omitting state from selector parameter
diff --git a/plugins/woocommerce-admin/client/tasks/deprecated-tasks.tsx b/plugins/woocommerce-admin/client/tasks/deprecated-tasks.tsx
index 9893639c501..66ff5330455 100644
--- a/plugins/woocommerce-admin/client/tasks/deprecated-tasks.tsx
+++ b/plugins/woocommerce-admin/client/tasks/deprecated-tasks.tsx
@@ -4,18 +4,19 @@
import { registerPlugin } from '@wordpress/plugins';
import { WooOnboardingTask } from '@woocommerce/onboarding';
import { useSelect } from '@wordpress/data';
-import { ONBOARDING_STORE_NAME, TaskType } from '@woocommerce/data';
+import {
+ ONBOARDING_STORE_NAME,
+ TaskType,
+ DeprecatedTaskType,
+} from '@woocommerce/data';
import { useEffect, useState } from '@wordpress/element';
-type DeprecatedTask = TaskType & {
- container?: React.ReactNode;
- isDeprecated?: boolean;
-};
+type MergedTask = TaskType & DeprecatedTaskType;
const DeprecatedWooOnboardingTaskFills = () => {
- const [ deprecatedTasks, setDeprecatedTasks ] = useState<
- DeprecatedTask[]
- >( [] );
+ const [ deprecatedTasks, setDeprecatedTasks ] = useState< MergedTask[] >(
+ []
+ );
const { isResolving, taskLists } = useSelect( ( select ) => {
return {
isResolving: select( ONBOARDING_STORE_NAME ).isResolving(
@@ -27,20 +28,18 @@ const DeprecatedWooOnboardingTaskFills = () => {
useEffect( () => {
if ( taskLists && taskLists.length > 0 ) {
- const deprecatedTasksWithContainer = [];
+ const deprecatedTasksWithContainer: MergedTask[] = [];
for ( const tasklist of taskLists ) {
for ( const task of tasklist.tasks ) {
if (
- ( task as DeprecatedTask ).isDeprecated &&
- ( task as DeprecatedTask ).container
+ ( task as MergedTask ).isDeprecated &&
+ ( task as MergedTask ).container
) {
- deprecatedTasksWithContainer.push( task );
+ deprecatedTasksWithContainer.push( task as MergedTask );
}
}
}
- setDeprecatedTasks(
- deprecatedTasksWithContainer as DeprecatedTask[]
- );
+ setDeprecatedTasks( deprecatedTasksWithContainer );
}
}, [ taskLists ] );
diff --git a/plugins/woocommerce/changelog/dev-migrate-onboarding-store-to-ts b/plugins/woocommerce/changelog/dev-migrate-onboarding-store-to-ts
new file mode 100644
index 00000000000..82912e3487d
--- /dev/null
+++ b/plugins/woocommerce/changelog/dev-migrate-onboarding-store-to-ts
@@ -0,0 +1,5 @@
+Significance: patch
+Type: dev
+Comment: Simply update deprecated-tasks.tsx type annotations
+
+