Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add tasks for new user first workspace #55302

Merged
merged 28 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1002d3b
add tasks for new user first workspace
ishpaul777 Jan 9, 2025
7014f2d
prettier
ishpaul777 Jan 15, 2025
c9b2f4f
replace meetSetupSpecialist task with meetGuideTask and fix guidedSet…
ishpaul777 Jan 10, 2025
61609ec
fix upgrade workspace case
ishpaul777 Jan 14, 2025
2f8e673
Fix merge conflicts before merging main
ishpaul777 Jan 15, 2025
4921332
namespace imports lint failure
ishpaul777 Jan 15, 2025
1063cfa
fix Do not default string IDs lint failure
ishpaul777 Jan 15, 2025
85c73bb
update onboarding task posting logic for TRACK_WORKSPACE action
ishpaul777 Jan 16, 2025
d83382d
workaround for failing lint
ishpaul777 Jan 16, 2025
06e71bc
fix: update to correct adminsChatReportID param
ishpaul777 Jan 16, 2025
9fa9862
merge main
ishpaul777 Jan 17, 2025
e177668
Merge branch 'main' into new-user-workspace-tasks
ishpaul777 Jan 19, 2025
b315040
fi onboarding accounting page not showing
ishpaul777 Jan 19, 2025
bb02e14
fix: post tasks in admin room
ishpaul777 Jan 19, 2025
eb483d1
reverse uninteded change
ishpaul777 Jan 20, 2025
8f8c6ec
Merge branch 'Expensify:main' into new-user-workspace-tasks
ishpaul777 Jan 20, 2025
c509fd5
fix: eslint
ishpaul777 Jan 20, 2025
e757aa3
fix tests
ishpaul777 Jan 20, 2025
385fd67
Merge branch 'main' into new-user-workspace-tasks
ishpaul777 Jan 21, 2025
70b455f
fix type
ishpaul777 Jan 21, 2025
65dd712
revert submodule update
ishpaul777 Jan 22, 2025
2eeafd0
Merge branch 'Expensify:main' into new-user-workspace-tasks
ishpaul777 Jan 24, 2025
69b6333
fix typing
ishpaul777 Jan 24, 2025
fa48e46
fix more type error
ishpaul777 Jan 24, 2025
98dbb52
fix report message not sent in payload
ishpaul777 Jan 26, 2025
40c93f0
Merge branch 'Expensify:main' into new-user-workspace-tasks
ishpaul777 Jan 28, 2025
0e2565a
fix copy
ishpaul777 Jan 29, 2025
142545d
merge main
ishpaul777 Jan 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 85 additions & 50 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ const selectableOnboardingChoices = {
const backendOnboardingChoices = {
ADMIN: 'newDotAdmin',
SUBMIT: 'newDotSubmit',
TRACK_WORKSPACE: 'newDotTrackWorkspace',
} as const;

const onboardingChoices = {
Expand All @@ -101,6 +102,50 @@ const selfGuidedTourTask: OnboardingTask = {
description: ({navatticURL}) => `[Take a self-guided product tour](${navatticURL}) and learn about everything Expensify has to offer.`,
};

const createWorkspaceTask: OnboardingTask = {
type: 'createWorkspace',
autoCompleted: true,
title: 'Create a workspace',
description: ({workspaceSettingsLink}) =>
'*Create a workspace* to track expenses, scan receipts, chat, and more.\n' +
'\n' +
'Here’s how to create a workspace:\n' +
'\n' +
'1. Click *Settings*.\n' +
'2. Click *Workspaces* > *New workspace*.\n' +
'\n' +
`*Your new workspace is ready!* [Check it out](${workspaceSettingsLink}).`,
};

const meetGuideTask: OnboardingTask = {
type: 'meetGuide',
autoCompleted: false,
title: 'Meet your setup specialist',
description: ({adminsRoomLink}) =>
`Meet your setup specialist, who can answer any questions as you get started with Expensify. Yes, a real human!\n` +
'\n' +
`Chat with the specialist in your [#admins room](${adminsRoomLink}).`,
};

const setupCategoriesTask: OnboardingTask = {
type: 'setupCategories',
autoCompleted: false,
title: 'Set up categories',
description: ({workspaceCategoriesLink}) =>
'*Set up categories* so your team can code expenses for easy reporting.\n' +
'\n' +
'Here’s how to set up categories:\n' +
'\n' +
'1. Click *Settings*.\n' +
'2. Go to *Workspaces*.\n' +
'3. Select your workspace.\n' +
'4. Click *Categories*.\n' +
"5. Disable any categories you don't need.\n" +
'6. Add your own categories in the top right.\n' +
'\n' +
`[Take me to workspace category settings](${workspaceCategoriesLink}).`,
};

const onboardingEmployerOrSubmitMessage: OnboardingMessage = {
message: 'Getting paid back is as easy as sending a message. Let’s go over the basics.',
video: {
Expand Down Expand Up @@ -5023,30 +5068,9 @@ const CONST = {
height: 960,
},
tasks: [
{
type: 'createWorkspace',
autoCompleted: true,
title: 'Create a workspace',
description: ({workspaceSettingsLink}) =>
'*Create a workspace* to track expenses, scan receipts, chat, and more.\n' +
'\n' +
'Here’s how to create a workspace:\n' +
'\n' +
'1. Click *Settings*.\n' +
'2. Click *Workspaces* > *New workspace*.\n' +
'\n' +
`*Your new workspace is ready!* [Check it out](${workspaceSettingsLink}).`,
},
createWorkspaceTask,
selfGuidedTourTask,
{
type: 'meetGuide',
autoCompleted: false,
title: 'Meet your setup specialist',
description: ({adminsRoomLink}) =>
`Meet your setup specialist, who can answer any questions as you get started with Expensify. Yes, a real human!\n` +
'\n' +
`Chat with the specialist in your [#admins room](${adminsRoomLink}).`,
},
meetGuideTask,
{
type: 'setupCategoriesAndTags',
autoCompleted: false,
Expand All @@ -5056,24 +5080,7 @@ const CONST = {
'\n' +
`Import them automatically by [connecting your accounting software](${workspaceAccountingLink}), or set them up manually in your [workspace settings](${workspaceSettingsLink}).`,
},
{
type: 'setupCategories',
autoCompleted: false,
title: 'Set up categories',
description: ({workspaceCategoriesLink}) =>
'*Set up categories* so your team can code expenses for easy reporting.\n' +
'\n' +
'Here’s how to set up categories:\n' +
'\n' +
'1. Click *Settings*.\n' +
'2. Go to *Workspaces*.\n' +
'3. Select your workspace.\n' +
'4. Click *Categories*.\n' +
"5. Disable any categories you don't need.\n" +
'6. Add your own categories in the top right.\n' +
'\n' +
`[Take me to workspace category settings](${workspaceCategoriesLink}).`,
},
setupCategoriesTask,
{
type: 'setupTags',
autoCompleted: false,
Expand Down Expand Up @@ -5151,6 +5158,42 @@ const CONST = {
},
],
},
[onboardingChoices.TRACK_WORKSPACE]: {
message: 'Here are some important tasks to help get your workspace set up.',
video: {
url: `${CLOUDFRONT_URL}/videos/guided-setup-manage-team-v2.mp4`,
thumbnailUrl: `${CLOUDFRONT_URL}/images/guided-setup-manage-team.jpg`,
duration: 55,
width: 1280,
height: 960,
},
tasks: [
createWorkspaceTask,
meetGuideTask,
setupCategoriesTask,
{
type: 'inviteAccountant',
autoCompleted: false,
title: 'Invite your accountant',
description: ({workspaceMembersLink}) =>
'*Invite your accountant* to Expensify and share your expenses with them to make tax time easier.\n' +
'\n' +
'Here’s how to invite your accountant:\n' +
'\n' +
'1. Click your profile picture.\n' +
'2. Go to *Workspaces*.\n' +
'3. Select your workspace.\n' +
'4. Click *Members* > Invite member.\n' +
'5. Enter their email or phone number.\n' +
'6. Add an invite message if you’d like.\n' +
'7. You’ll be set as the expense approver. You can change this to any admin once you invite your team.\n' +
'\n' +
'That’s it, happy expensing! 😄\n' +
'\n' +
`[View your workspace members](${workspaceMembersLink}).`,
},
],
},
[onboardingChoices.PERSONAL_SPEND]: onboardingPersonalSpendMessage,
[onboardingChoices.CHAT_SPLIT]: {
message: 'Splitting bills with friends is as easy as sending a message. Here’s how.',
Expand Down Expand Up @@ -5209,15 +5252,7 @@ const CONST = {
height: 960,
},
tasks: [
{
type: 'meetSetupSpecialist',
autoCompleted: false,
title: 'Meet your setup specialist',
description:
'*Meet your setup specialist* who can answer any questions as you get started with Expensify. Yes, a real human!' +
'\n' +
'Chat with them in your #admins room or schedule a call today.',
},
meetGuideTask,
{
type: 'reviewWorkspaceSettings',
autoCompleted: false,
Expand Down
2 changes: 1 addition & 1 deletion src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ const ROUTES = {
},
MONEY_REQUEST_STEP_CATEGORY: {
route: ':action/:iouType/category/:transactionID/:reportID/:reportActionID?',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '', reportActionID?: string) =>
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string | undefined, backTo = '', reportActionID?: string) =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/category/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo),
},
MONEY_REQUEST_ATTENDEE: {
Expand Down
2 changes: 2 additions & 0 deletions src/libs/API/parameters/CategorizeTrackedExpenseParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ type CategorizeTrackedExpenseParams = {
policyExpenseCreatedReportActionID?: string;
adminsChatReportID?: string;
adminsCreatedReportActionID?: string;
guidedSetupData?: string;
engagementChoice?: string;
};

export default CategorizeTrackedExpenseParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/CreateWorkspaceParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type CreateWorkspaceParams = {
customUnitID: string;
customUnitRateID: string;
engagementChoice?: string;
guidedSetupData?: string;
currency: string;
file?: File;
};
Expand Down
2 changes: 2 additions & 0 deletions src/libs/API/parameters/ShareTrackedExpenseParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ type ShareTrackedExpenseParams = {
policyExpenseCreatedReportActionID?: string;
adminsChatReportID?: string;
adminsCreatedReportActionID?: string;
engagementChoice?: string;
guidedSetupData?: string;
};

export default ShareTrackedExpenseParams;
3 changes: 2 additions & 1 deletion src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ import {createDraftTransaction, getIOUReportActionToApproveOrPay, setMoneyReques
import {createDraftWorkspace} from './actions/Policy/Policy';
import {autoSwitchToFocusMode} from './actions/PriorityMode';
import {hasCreditBankAccount} from './actions/ReimbursementAccount/store';
import {handleReportChanged} from './actions/Report';
import {handleReportChanged, prepareOnboardingOnyxData} from './actions/Report';
import {isAnonymousUser as isAnonymousUserSession} from './actions/Session';
import {convertToDisplayString, getCurrencySymbol} from './CurrencyUtils';
import DateUtils from './DateUtils';
Expand Down Expand Up @@ -9212,6 +9212,7 @@ export {
getReportMetadata,
buildOptimisticSelfDMReport,
isHiddenForCurrentUser,
prepareOnboardingOnyxData,
};

export type {
Expand Down
2 changes: 1 addition & 1 deletion src/libs/actions/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ function createWorkspaceWithPolicyDraftAndNavigateToIt(
* @param [file] Optional, avatar file for workspace
*/
function savePolicyDraftByNewWorkspace(policyID?: string, policyName?: string, policyOwnerEmail = '', makeMeAdmin = false, currency = '', file?: File) {
createWorkspace(policyOwnerEmail, makeMeAdmin, policyName, policyID, '', currency, file);
createWorkspace(policyOwnerEmail, makeMeAdmin, policyName, policyID, CONST.ONBOARDING_CHOICES.MANAGE_TEAM, currency, file);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ishpaul777 @francoisl do you see a need for adding a comment on why we're passing MANAGE_TEAM ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no strong feelings, but it feel self explanatory if we don't typescript will yell

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No strong feelings either, though I think it might be more beneficial if we add an explanation in the doc of the function definition, in Policy.ts. Right now it says @param [engagementChoice] Purpose of using application selected by user in guided setup flow - we can add a note saying that the default is MANAGE_TEAM and you can change for specific policy creation flows

}

/**
Expand Down
6 changes: 5 additions & 1 deletion src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3030,7 +3030,7 @@ function getTrackExpenseInformation(
let createdWorkspaceParams: CreateWorkspaceParams | undefined;

if (isDraftReportLocal) {
const workspaceData = buildPolicyData(undefined, policy?.makeMeAdmin, policy?.name, policy?.id, chatReport?.reportID);
const workspaceData = buildPolicyData(undefined, policy?.makeMeAdmin, policy?.name, policy?.id, chatReport?.reportID, CONST.ONBOARDING_CHOICES.TRACK_WORKSPACE);
createdWorkspaceParams = workspaceData.params;
optimisticData.push(...workspaceData.optimisticData);
successData.push(...workspaceData.successData);
Expand Down Expand Up @@ -4231,6 +4231,8 @@ function categorizeTrackedExpense(trackedExpenseParams: TrackedExpenseParams) {
policyExpenseCreatedReportActionID: createdWorkspaceParams?.expenseCreatedReportActionID,
adminsChatReportID: createdWorkspaceParams?.adminsChatReportID,
adminsCreatedReportActionID: createdWorkspaceParams?.adminsCreatedReportActionID,
engagementChoice: createdWorkspaceParams?.engagementChoice,
guidedSetupData: createdWorkspaceParams?.guidedSetupData,
};

API.write(WRITE_COMMANDS.CATEGORIZE_TRACKED_EXPENSE, parameters, {optimisticData, successData, failureData});
Expand Down Expand Up @@ -4289,6 +4291,8 @@ function shareTrackedExpense(trackedExpenseParams: TrackedExpenseParams) {
policyExpenseCreatedReportActionID: createdWorkspaceParams?.expenseCreatedReportActionID,
adminsChatReportID: createdWorkspaceParams?.adminsChatReportID,
adminsCreatedReportActionID: createdWorkspaceParams?.adminsCreatedReportActionID,
engagementChoice: createdWorkspaceParams?.engagementChoice,
guidedSetupData: createdWorkspaceParams?.guidedSetupData,
};

API.write(WRITE_COMMANDS.SHARE_TRACKED_EXPENSE, parameters, {optimisticData, successData, failureData});
Expand Down
42 changes: 39 additions & 3 deletions src/libs/actions/Policy/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ import * as ReportUtils from '@libs/ReportUtils';
import type {PolicySelector} from '@pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover';
import * as PaymentMethods from '@userActions/PaymentMethods';
import * as PersistedRequests from '@userActions/PersistedRequests';
import type {OnboardingPurpose} from '@src/CONST';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {
IntroSelected,
InvitedEmailsToAccountIDs,
PersonalDetailsList,
Policy,
Expand Down Expand Up @@ -1698,6 +1700,12 @@ function createDraftInitialWorkspace(policyOwnerEmail = '', policyName = '', pol
Onyx.update(optimisticData);
}

let introSelected: OnyxEntry<IntroSelected>;
Onyx.connect({
key: ONYXKEYS.NVP_INTRO_SELECTED,
callback: (value) => (introSelected = value),
});

/**
* Generates onyx data for creating a new workspace
*
Expand All @@ -1709,16 +1717,18 @@ function createDraftInitialWorkspace(policyOwnerEmail = '', policyName = '', pol
* @param [engagementChoice] Purpose of using application selected by user in guided setup flow
* @param [currency] Optional, selected currency for the workspace
* @param [file] Optional, avatar file for workspace
* @param [shouldAddOnboardingTasks] whether to add onboarding tasks to the workspace
*/
function buildPolicyData(
policyOwnerEmail = '',
makeMeAdmin = false,
policyName = '',
policyID = generatePolicyID(),
expenseReportId?: string,
engagementChoice?: string,
engagementChoice?: OnboardingPurpose,
currency = '',
file?: File,
shouldAddOnboardingTasks = true,
) {
const workspaceName = policyName || generateDefaultWorkspaceName(policyOwnerEmail);

Expand Down Expand Up @@ -1991,6 +2001,21 @@ function buildPolicyData(
file: clonedFile,
};

if (!introSelected?.createWorkspace && engagementChoice && shouldAddOnboardingTasks) {
const onboardingData = ReportUtils.prepareOnboardingOnyxData(engagementChoice, CONST.ONBOARDING_MESSAGES[engagementChoice], adminsChatReportID, policyID);
if (!onboardingData) {
return {successData, optimisticData, failureData, params};
}
const {guidedSetupData, optimisticData: taskOptimisticData, successData: taskSuccessData, failureData: taskFailureData} = onboardingData;

params.guidedSetupData = JSON.stringify(guidedSetupData);
params.engagementChoice = engagementChoice;

optimisticData.push(...taskOptimisticData);
successData.push(...taskSuccessData);
failureData.push(...taskFailureData);
}

return {successData, optimisticData, failureData, params};
}

Expand All @@ -2010,11 +2035,22 @@ function createWorkspace(
makeMeAdmin = false,
policyName = '',
policyID = generatePolicyID(),
engagementChoice = '',
engagementChoice: OnboardingPurpose = CONST.ONBOARDING_CHOICES.MANAGE_TEAM,
currency = '',
file?: File,
shouldAddOnboardingTasks = true,
): CreateWorkspaceParams {
const {optimisticData, failureData, successData, params} = buildPolicyData(policyOwnerEmail, makeMeAdmin, policyName, policyID, undefined, engagementChoice, currency, file);
const {optimisticData, failureData, successData, params} = buildPolicyData(
policyOwnerEmail,
makeMeAdmin,
policyName,
policyID,
undefined,
engagementChoice,
currency,
file,
shouldAddOnboardingTasks,
);
API.write(WRITE_COMMANDS.CREATE_WORKSPACE, params, {optimisticData, successData, failureData});

// Publish a workspace created event if this is their first policy
Expand Down
Loading
Loading