Skip to content

Update Global Create and Workspace chat tooltips #58997

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 8 additions & 7 deletions src/components/ProductTrainingContext/TOOLTIPS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type ProductTrainingTooltipName = ValueOf<typeof CONST.PRODUCT_TRAINING_TOOLTIP_

type ShouldShowConditionProps = {
shouldUseNarrowLayout: boolean;
isUserPolicyEmployee: boolean;
isUserPolicyAdmin: boolean;
hasBeenAddedToNudgeMigration: boolean;
};
Expand Down Expand Up @@ -60,11 +61,12 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
{text: 'productTrainingTooltip.globalCreateTooltip.part1', isBold: true},
{text: 'productTrainingTooltip.globalCreateTooltip.part2', isBold: false},
{text: 'productTrainingTooltip.globalCreateTooltip.part3', isBold: false},
{text: 'productTrainingTooltip.globalCreateTooltip.part4', isBold: false},
],
onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(GLOBAL_CREATE_TOOLTIP, isDismissedUsingCloseButton),
name: GLOBAL_CREATE_TOOLTIP,
priority: 1200,
shouldShow: () => true,
priority: 1950,
shouldShow: ({isUserPolicyEmployee}) => isUserPolicyEmployee,
},
[BOTTOM_NAV_INBOX_TOOLTIP]: {
Copy link
Contributor

Choose a reason for hiding this comment

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

Screenshot 2025-04-10 at 2 02 39 AM

lets update this one also

Copy link
Contributor

Choose a reason for hiding this comment

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

oh i see its done on other PR, nvm!

content: [
Expand All @@ -80,14 +82,13 @@ const TOOLTIPS: Record<ProductTrainingTooltipName, TooltipData> = {
},
[LHN_WORKSPACE_CHAT_TOOLTIP]: {
content: [
{text: 'productTrainingTooltip.workspaceChatTooltip.part1', isBold: true},
{text: 'productTrainingTooltip.workspaceChatTooltip.part2', isBold: false},
{text: 'productTrainingTooltip.workspaceChatTooltip.part3', isBold: false},
{text: 'productTrainingTooltip.workspaceChatTooltip.part1', isBold: false},
{text: 'productTrainingTooltip.workspaceChatTooltip.part2', isBold: true},
],
onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(LHN_WORKSPACE_CHAT_TOOLTIP, isDismissedUsingCloseButton),
name: LHN_WORKSPACE_CHAT_TOOLTIP,
priority: 800,
shouldShow: () => true,
priority: 1800,
shouldShow: ({isUserPolicyEmployee}) => isUserPolicyEmployee,
},
[EXPENSE_REPORTS_FILTER]: {
content: [
Expand Down
12 changes: 11 additions & 1 deletion src/components/ProductTrainingContext/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
import {parseFSAttributes} from '@libs/Fullstory';
import getPlatform from '@libs/getPlatform';
import {hasCompletedGuidedSetupFlowSelector} from '@libs/onboardingSelectors';
import {getActiveAdminWorkspaces} from '@libs/PolicyUtils';
import {getActiveAdminWorkspaces, getActiveEmployeeWorkspaces} from '@libs/PolicyUtils';
import isProductTrainingElementDismissed from '@libs/TooltipUtils';
import variables from '@styles/variables';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -60,6 +60,13 @@ function ProductTrainingContextProvider({children}: ChildrenProps) {
const [allPolicies, allPoliciesMetadata] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true});
const [currentUserLogin, currentUserLoginMetadata] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.email, canBeMissing: true});

const isUserPolicyEmployee = useMemo(() => {
if (!allPolicies || !currentUserLogin || isLoadingOnyxValue(allPoliciesMetadata, currentUserLoginMetadata)) {
return false;
}
return getActiveEmployeeWorkspaces(allPolicies, currentUserLogin).length > 0;
}, [allPolicies, currentUserLogin, allPoliciesMetadata, currentUserLoginMetadata]);

const isUserPolicyAdmin = useMemo(() => {
if (!allPolicies || !currentUserLogin || isLoadingOnyxValue(allPoliciesMetadata, currentUserLoginMetadata)) {
return false;
Expand All @@ -68,6 +75,7 @@ function ProductTrainingContextProvider({children}: ChildrenProps) {
}, [allPolicies, currentUserLogin, allPoliciesMetadata, currentUserLoginMetadata]);

const [dismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true});

const {shouldUseNarrowLayout} = useResponsiveLayout();

const [modal] = useOnyx(ONYXKEYS.MODAL, {canBeMissing: true});
Expand Down Expand Up @@ -141,6 +149,7 @@ function ProductTrainingContextProvider({children}: ChildrenProps) {

return tooltipConfig.shouldShow({
shouldUseNarrowLayout,
isUserPolicyEmployee,
isUserPolicyAdmin,
hasBeenAddedToNudgeMigration,
});
Expand All @@ -153,6 +162,7 @@ function ProductTrainingContextProvider({children}: ChildrenProps) {
shouldUseNarrowLayout,
isModalVisible,
isLoadingApp,
isUserPolicyEmployee,
isUserPolicyAdmin,
],
);
Expand Down
8 changes: 4 additions & 4 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6218,14 +6218,14 @@ const translations = {
part4: 'chat about expenses.',
},
workspaceChatTooltip: {
part1: 'Submit expenses',
part2: ' and chat with',
part3: '\napprovers here!',
part1: 'Chat with ',
part2: 'approvers',
},
globalCreateTooltip: {
part1: 'Create expenses',
part2: ', start chatting,',
part3: '\nand more!',
part3: '\nand more.',
part4: ' Try it out!',
},
expenseReportsFilter: {
part1: 'Welcome! Find all of your',
Expand Down
10 changes: 5 additions & 5 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6743,14 +6743,14 @@ const translations = {
part4: 'chatea sobre los gastos.',
},
workspaceChatTooltip: {
part1: 'Envía gastos',
part2: ' y chatea con',
part3: '\naprobadores aquí!',
part1: 'Chatea con ',
part2: 'los aprobadores',
},
globalCreateTooltip: {
part1: 'Crea gastos',
part2: ', comienza a chatear,',
part3: '\ny mucho más!',
part2: ', empieza a chatear',
part3: '\ny más.',
part4: ' ¡Pruébalo!',
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Transalations confirmed in slack?

expenseReportsFilter: {
part1: '¡Bienvenido! Aquí encontrarás todos los',
Expand Down
7 changes: 7 additions & 0 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,12 @@ function getActiveAdminWorkspaces(policies: OnyxCollection<Policy> | null, curre
return activePolicies.filter((policy) => shouldShowPolicy(policy, isOfflineNetworkStore(), currentUserLogin) && isPolicyAdmin(policy, currentUserLogin));
}

/** Return active policies where current user is an employee (of the role "user") */
function getActiveEmployeeWorkspaces(policies: OnyxCollection<Policy> | null, currentUserLogin: string | undefined): Policy[] {
const activePolicies = getActivePolicies(policies, currentUserLogin);
return activePolicies.filter((policy) => shouldShowPolicy(policy, isOfflineNetworkStore(), currentUserLogin) && isPolicyUser(policy, currentUserLogin));
}

/**
*
* Checks whether the current user has a policy with Xero accounting software integration
Expand Down Expand Up @@ -1559,6 +1565,7 @@ export {
getManagerAccountID,
isPrefferedExporter,
areAllGroupPoliciesExpenseChatDisabled,
getActiveEmployeeWorkspaces,
isUserInvitedToWorkspace,
};

Expand Down
28 changes: 14 additions & 14 deletions tests/ui/components/ProductTrainingContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ describe('ProductTrainingContextProvider', () => {
Onyx.merge(ONYXKEYS.IS_LOADING_APP, true);
await waitForBatchedUpdatesWithAct();

const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP;
const {result} = renderHook(() => useProductTrainingContext(testTooltip), {wrapper});

// Then tooltip should not show
Expand All @@ -105,7 +105,7 @@ describe('ProductTrainingContextProvider', () => {
Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: false});
await waitForBatchedUpdatesWithAct();

const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP;
const {result} = renderHook(() => useProductTrainingContext(testTooltip), {wrapper});

// Then tooltip should not show
Expand All @@ -117,15 +117,15 @@ describe('ProductTrainingContextProvider', () => {
Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true});
await waitForBatchedUpdatesWithAct();

const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP;
const {result} = renderHook(() => useProductTrainingContext(testTooltip), {wrapper});

// Then tooltip should show
expect(result.current.shouldShowProductTrainingTooltip).toBe(true);
});

it('should keep tooltip visible when another tooltip with shouldShow=false is unmounted', async () => {
const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP;
const ref = createRef<ProductTrainingRef>();

// When multiple tooltips with the same name but different shouldShow values are rendered
Expand Down Expand Up @@ -178,7 +178,7 @@ describe('ProductTrainingContextProvider', () => {
await waitForBatchedUpdatesWithAct();

// Then tooltips should not show
const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.BOTTOM_NAV_INBOX_TOOLTIP;
const {result} = renderHook(() => useProductTrainingContext(testTooltip), {wrapper});

// Expect tooltip to be hidden
Expand All @@ -197,7 +197,7 @@ describe('ProductTrainingContextProvider', () => {
});
await waitForBatchedUpdatesWithAct();

const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.BOTTOM_NAV_INBOX_TOOLTIP;
const {result} = renderHook(() => useProductTrainingContext(testTooltip), {wrapper});

// Then tooltip should show
Expand All @@ -210,7 +210,7 @@ describe('ProductTrainingContextProvider', () => {
// When a tooltip has been dismissed
const date = new Date();
Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true});
const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP;
Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
migratedUserWelcomeModal: {
timestamp: DateUtils.getDBTime(date.valueOf()),
Expand All @@ -237,7 +237,7 @@ describe('ProductTrainingContextProvider', () => {
},
});
await waitForBatchedUpdatesWithAct();
const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP;
const {result, rerender} = renderHook(() => useProductTrainingContext(testTooltip), {wrapper});
// When the user dismiss the tooltip
result.current.hideProductTrainingTooltip();
Expand Down Expand Up @@ -295,8 +295,8 @@ describe('ProductTrainingContextProvider', () => {
await waitForBatchedUpdatesWithAct();

// Then only highest priority tooltip should show
const highPriorityTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
const lowPriorityTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.LHN_WORKSPACE_CHAT_TOOLTIP;
const highPriorityTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP_MANAGER;
const lowPriorityTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP;

const {result} = renderHook(
() => ({
Expand All @@ -315,8 +315,8 @@ describe('ProductTrainingContextProvider', () => {
// When higher priority tooltip is dismissed
Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true});
const date = new Date();
const highPriorityTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
const lowPriorityTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.LHN_WORKSPACE_CHAT_TOOLTIP;
const highPriorityTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP_MANAGER;
const lowPriorityTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP;

Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
migratedUserWelcomeModal: {
Expand Down Expand Up @@ -353,8 +353,8 @@ describe('ProductTrainingContextProvider', () => {
});
await waitForBatchedUpdatesWithAct();

const highPriorityTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP;
const lowPriorityTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.LHN_WORKSPACE_CHAT_TOOLTIP;
const highPriorityTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP_MANAGER;
const lowPriorityTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP;

const {result} = renderHook(
() => ({
Expand Down