Expensify / App

Welcome to New Expensify: a complete re-imagination of financial collaboration, centered around chat. Help us build the next generation of Expensify by sharing feedback and contributing to the code.
https://new.expensify.com
MIT License
3.53k stars 2.88k forks source link

[HOLD for payment 2023-03-16] [$2000] Web - Emoji - There is no tooltip for the category picker #15108

Closed kbecciv closed 1 year ago

kbecciv commented 1 year ago

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Issue found when executing PR https://github.com/Expensify/App/pull/14532

Action Performed:

  1. Go to staging.new.expensify.com
  2. Log in with any account
  3. Go to any conversation
  4. Select emoji option
  5. Hovering on one of the option

Expected Result:

When hovering over one of the category pickers, a tooltip containing the name of the category should appear.

Actual Result:

There is no tooltip for the category picker

Workaround:

Unknown

Platforms:

Which of our officially supported platforms is this issue occurring on?

Version Number: 1.2.71.0

Reproducible in staging?: Yes

Reproducible in production?: No - New feature

If this was caught during regression testing, add the test name, ID and link from TestRail:

Email or phone of affected tester (no customers):

Logs: https://stackoverflow.com/c/expensify/questions/4856

Notes/Photos/Videos: Any additional supporting documentation

image

https://user-images.githubusercontent.com/93399543/218580554-3dd53e0e-8b4e-48c3-9b52-ac48e84fe8d3.mp4

Expensify/Expensify Issue URL:

Issue reported by: Applause - Internal Team

Slack conversation:

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~010a0b351e969622b9
  • Upwork Job ID: 1625929024649732096
  • Last Price Increase: 2023-02-22
MelvinBot commented 1 year ago

Triggered auto assignment to @trjExpensify (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details.

MelvinBot commented 1 year ago

Bug0 Triage Checklist (Main S/O)

trjExpensify commented 1 year ago

This is a recent feature we released here, asking in this thread on the expected behaviour.

JmillsExpensify commented 1 year ago

Great catch, I agree with Applause that we just overlooked this and should close the gap.

trjExpensify commented 1 year ago

Alrighty, moving it on. CC: @stitesExpensify for vis

MelvinBot commented 1 year ago

Job added to Upwork: https://www.upwork.com/jobs/~010a0b351e969622b9

MelvinBot commented 1 year ago

Current assignee @trjExpensify is eligible for the External assigner, not assigning anyone new.

MelvinBot commented 1 year ago

Triggered auto assignment to Contributor-plus team member for initial proposal review - @aimane-chnaif (External)

MelvinBot commented 1 year ago

Triggered auto assignment to @robertjchen (External), see https://stackoverflow.com/c/expensify/questions/7972 for more details.

daraksha-dk commented 1 year ago

Proposal

Please re-state the problem that we are trying to solve in this issue.

There is no tooltip present for category shortcut icons

What is the root cause of that problem?

This is happening because we were not using Tooltip initially for these icons. (This is more like a feature request or improvement)

What changes do you think we should make in order to solve the problem?

To fix this we need to first pass the translation key for all the category headers here. We can get the values similar to how we're getting headerIndices - by creating a utility function in EmojiUtils to get all the headerCodes from emojis.js

// Example Code for EmojiUtils.js
function getHeaderCodes(emojis, headerIndices = []) {
    return _.map(!_.isEmpty(headerIndices) ? headerIndices : getHeaderIndices(emojis), headerIndex => emojis[headerIndex].code);
}

We'll be using the above function inside EmojiPickerMenu/index.js & the same can be used inside native as well

// Example code
       this.headerIndices = EmojiUtils.getHeaderIndices(allEmojis);
       this.headerCodes = EmojiUtils.getHeaderCodes(allEmojis, this.headerIndices);

After that we need to use Tooltip component in CategoryShortcutButton with the required props.

Result

https://user-images.githubusercontent.com/71884990/219115694-839032d0-e605-4141-8d81-d8a1d7e16f99.mp4

PrashantMangukiya commented 1 year ago

Proposal

Please re-state the problem that we are trying to solve in this issue.

Within web we have to show tooltip when mouse over on emoji picker category icon.

What is the root cause of that problem?

Tooltip not used within <CategoryShortcutButton> so it will not show tooltip whenever mouse over the cateogry icon.

What changes do you think we should make in order to solve the problem?

I think solution is pretty simple and clean as explained below:

Within src/components/EmojiPicker/CategoryShortcutBar.js file we already have an array of category icons as shown below.

https://github.com/Expensify/App/blob/1180571bf3059d0388f57d1c661ff61f7fc4758a/src/components/EmojiPicker/CategoryShortcutBar.js#L26-L31

So within src/components/EmojiPicker/CategoryShortcutBar.js file we have to create 1) Another array that consist translation keys corresponding to category icons and 2) Add translation key for "Frequently used" section if exist and 3) pass new prop named tooltipText to <CategoryShortcutButton> component as shown code below:

const CategoryShortcutBar = (props) => {
     const icons = [Smiley, AnimalsAndNature, FoodAndDrink, TravelAndPlaces, Activities, Objects, Symbols, Flags];

    // *** Add this code ***
    // Prepare array of translation keys to show as tooltip for each category icon
    const tooltipTextKeys = _.map([
        'smileysAndEmotion',
        'animalsAndNature',
        'foodAndDrink',
        'travelAndPlaces',
        'activities',
        'objects',
        'symbols',
        'flags',
    ], item => `emojiPicker.headers.${item}`);

    // If the user has frequently used emojis, there will be 9 headers, otherwise there will be 8
    if (props.headerIndices.length === 9) {
        icons.unshift(FrequentlyUsed);
        tooltipTextKeys.unshift('emojiPicker.headers.frequentlyUsed');    // *** Add this code ***
    }

    return (
        <View style={[styles.pt2, styles.ph4, styles.flexRow]}>
            {_.map(props.headerIndices, (headerIndex, i) => (
                <CategoryShortcutButton
                    icon={icons[i]}
                    onPress={() => props.onPress(headerIndex)}
                    key={`categoryShortcut${i}`}
                    tooltipText={props.translate(tooltipTextKeys[i])}.  // *** Add this code ***
                />
            ))}
        </View>
    );

}

Within src/components/EmojiPicker/CategoryShortcutButton.js file we have view with icon as shown below:

https://github.com/Expensify/App/blob/1180571bf3059d0388f57d1c661ff61f7fc4758a/src/components/EmojiPicker/CategoryShortcutButton.js#L39-L46

So within src/components/EmojiPicker/CategoryShortcutButton.js file we have to define new prop named tooltipText and wrap View with tooltip as shown code below:


const propTypes = {

    /** Tooltip text to show when mouse over (Add this code) */
    tooltipText: PropTypes.string.isRequired,
};

                <Tooltip
                    text={this.props.tooltipText}
                    shiftVertical={-7}
                >
                    <View style={styles.alignSelfCenter}>
                        <Icon
                            fill={themeColors.icon}
                            src={this.props.icon}
                            height={variables.iconSizeNormal}
                            width={variables.iconSizeNormal}
                        />
                    </View>
                </Tooltip>

So this solution is efficient and requires minimum code changes.

It will also take care to show tooltip in corresponding language when language changed as shown in result video below. Also it will keep button size consistent in all platform as other platform does not show tooltip.

What alternative solutions did you explore? (Optional)

None

Result video:

Web
https://user-images.githubusercontent.com/7823358/219662535-ffd73ad4-3a66-48ff-95d1-814d5e6c72ef.mp4
iOS
https://user-images.githubusercontent.com/7823358/219663676-66e8c534-b30e-4837-9662-bc5fcaa767e2.mov
Android
https://user-images.githubusercontent.com/7823358/219662845-7ecd2c3a-0789-49d8-9405-b5275bbd0f19.mov
trjExpensify commented 1 year ago

@aimane-chnaif what do you think of this proposal?

JmillsExpensify commented 1 year ago

Assigning myself as well so I can keep track of this one as part of the tracking issue.

aimane-chnaif commented 1 year ago

@daraksha-dk your proposal will do the job but can we think of better solution for optimization? emojis data is very large and it would be good to get both codes and indices of header in one loop.

aimane-chnaif commented 1 year ago

@PrashantMangukiya it's not ideal to re-define emoji codes for tooltip text keys. We can use already existing emoji codes defined in emojis.js

daraksha-dk commented 1 year ago

@aimane-chnaif - I think to avoid looping twice, we can use a second parameter called headerIndices as shown below

function getHeaderCodes(emojis, headerIndices = []) {
    return _.map(!_.isEmpty(headerIndices) ? headerIndices : getHeaderIndices(emojis), headerIndex => emojis[headerIndex].code);
}
MelvinBot commented 1 year ago

📣 @daraksha-dk! 📣

Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork. Please follow these steps:

  1. Get the email address used to login to your Expensify account. If you don't already have an Expensify account, create one here. If you have multiple accounts (e.g. one for testing), please use your main account email.
  2. Get the link to your Upwork profile. It's necessary because we only pay via Upwork. You can access it by logging in, and then clicking on your name. It'll look like this. If you don't already have an account, sign up for one here.
  3. Copy the format below and paste it in a comment on this issue. Replace the placeholder text with your actual details.

Screen Shot 2022-11-16 at 4 42 54 PM

Format:

Contributor details
Your Expensify account email: <REPLACE EMAIL HERE>
Upwork Profile Link: <REPLACE LINK HERE>
akshayasalvi commented 1 year ago

Proposal

Please re-state the problem that we are trying to solve in this issue.

What is the root cause of that problem?

What changes do you think we should make in order to solve the problem?

I think we should update the CategoryShortcutBar to accept the {code , index} [] array of the headers, so that we can apply the tooltip to each of the icon.

  1. Add props to CategoryShortcutBar, headerEmojis which consist of the code and index.
  2. Add a new prop code to CategoryShortcutButton which takes the headerEmoji.code
  3. Add withLocalize HoC to CategoryShortcutButton, so that we can access the translate method
  4. Wrap the following View with Tooltip

https://github.com/Expensify/App/blob/a87b802a09c48de7274855af56e27ab544463ef6/src/components/EmojiPicker/CategoryShortcutButton.js#L39

  1. For the Tooltip use translate('emojiPicker.headers.${code}')

  2. Update getHeaderIndices in EmojiUtils to return the whole object along with the index (or atleast the code and the index) https://github.com/Expensify/App/blob/a87b802a09c48de7274855af56e27ab544463ef6/src/libs/EmojiUtils.js#L89

  3. In EmojiPicker/index.js and can be applied to native as well.

https://github.com/Expensify/App/blob/a87b802a09c48de7274855af56e27ab544463ef6/src/components/EmojiPicker/EmojiPickerMenu/index.js#L63

Modify the above block as:

this.headerEmojis = = EmojiUtils.getHeaderEmojis(allEmojis);`
this.headerRowIndices = _.map(this.headerEmojis, (headerEmoji) => Math.floor(headerEmoji.index / CONST.EMOJI_NUM_PER_ROW));

What alternative solutions did you explore? (Optional)

I would also recommend one additional refactor. We can move the following imports also to assets/emoji.js

https://github.com/Expensify/App/blob/a87b802a09c48de7274855af56e27ab544463ef6/src/components/EmojiPicker/CategoryShortcutBar.js#L7-L15

So that in future whenever we add a new category we only have one place of truth. We don't need to maintain arrays at two places. We can get rid of const icons = [Smiley, AnimalsAndNature, FoodAndDrink, TravelAndPlaces, Activities, Objects, Symbols, Flags]; and the code becomes a lot cleaner.

MelvinBot commented 1 year ago

📣 @akshayasalvi! 📣

Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork. Please follow these steps:

  1. Get the email address used to login to your Expensify account. If you don't already have an Expensify account, create one here. If you have multiple accounts (e.g. one for testing), please use your main account email.
  2. Get the link to your Upwork profile. It's necessary because we only pay via Upwork. You can access it by logging in, and then clicking on your name. It'll look like this. If you don't already have an account, sign up for one here.
  3. Copy the format below and paste it in a comment on this issue. Replace the placeholder text with your actual details.

Screen Shot 2022-11-16 at 4 42 54 PM

Format:

Contributor details
Your Expensify account email: <REPLACE EMAIL HERE>
Upwork Profile Link: <REPLACE LINK HERE>
PrashantMangukiya commented 1 year ago

@aimane-chnaif here is my proposal 2

Proposal 2

Please re-state the problem that we are trying to solve in this issue.

Within web we have to show tooltip when mouse over on emoji picker category icon.

What is the root cause of that problem?

Tooltip not used within <CategoryShortcutButton> so it will not show tooltip whenever mouse over the cateogry icon.

What changes do you think we should make in order to solve the problem?

Within src/libs/EmojiUtils.js file we have to add helper function as shown below that will return header indices with coresponding code.

function getHeaderIndicesWithCode(emojis) {
    const headerIndices = [];
    _.each(emojis, (emoji, index) => {
        if (!emoji.header) {
            return;
        }
        headerIndices.push({index, code: emoji.code});
    });
    return headerIndices;
}

Within src/components/EmojiPicker/EmojiPickerMenu/index.js file we have to update code as shown below:


        // This is the actual header index starting at the first emoji and counting each one
        //this.headerIndices = EmojiUtils.getHeaderIndices(allEmojis);    // *** OLD CODE
        const headerIndicesWithCode = EmojiUtils.getHeaderIndicesWithCode(allEmojis);   // *** New Code ****
        this.headerIndices = _.map(headerIndicesWithCode, item => item.index);    // *** New Code ****
        this.headerCodes = _.map(headerIndicesWithCode, item => item.code);        // *** New Code ****

        <CategoryShortcutBar
            headerIndices={this.headerIndices}
            headerCodes={this.headerCodes}  // *** Add this code
            onPress={this.scrollToHeader}
        />

So within src/components/EmojiPicker/CategoryShortcutBar.js we have to pass tooltipText as props to CategoryShortcutButton component.

const CategoryShortcutBar = (props) => {

    return (
        <View style={[styles.pt2, styles.ph4, styles.flexRow]}>
            {_.map(props.headerIndices, (headerIndex, i) => (
                <CategoryShortcutButton
                    icon={icons[i]}
                    onPress={() => props.onPress(headerIndex)}
                    key={`categoryShortcut${i}`}
                    tooltipText={props.translate(`emojiPicker.headers.${props.headerCodes[i]}`)} // *** Add this prop ***
                />
            ))}
        </View>
    );
}

Within src/components/EmojiPicker/CategoryShortcutButton.js file we have view with icon as shown below:

https://github.com/Expensify/App/blob/1180571bf3059d0388f57d1c661ff61f7fc4758a/src/components/EmojiPicker/CategoryShortcutButton.js#L39-L46

So within src/components/EmojiPicker/CategoryShortcutButton.js file we have to define new prop named tooltipText and wrap View with tooltip as shown code below:


const propTypes = {

    /** Tooltip text to show when mouse over (Add this code) */
    tooltipText: PropTypes.string.isRequired,
};

                <Tooltip
                    text={this.props.tooltipText}
                    shiftVertical={-7}
                >
                    <View style={styles.alignSelfCenter}>
                        <Icon
                            fill={themeColors.icon}
                            src={this.props.icon}
                            height={variables.iconSizeNormal}
                            width={variables.iconSizeNormal}
                        />
                    </View>
                </Tooltip>

What alternative solutions did you explore? (Optional)

None

MelvinBot commented 1 year ago

📣 @PrashantMangukiya! 📣

Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork. Please follow these steps:

  1. Get the email address used to login to your Expensify account. If you don't already have an Expensify account, create one here. If you have multiple accounts (e.g. one for testing), please use your main account email.
  2. Get the link to your Upwork profile. It's necessary because we only pay via Upwork. You can access it by logging in, and then clicking on your name. It'll look like this. If you don't already have an account, sign up for one here.
  3. Copy the format below and paste it in a comment on this issue. Replace the placeholder text with your actual details.

Screen Shot 2022-11-16 at 4 42 54 PM

Format:

Contributor details
Your Expensify account email: <REPLACE EMAIL HERE>
Upwork Profile Link: <REPLACE LINK HERE>
daraksha-dk commented 1 year ago

Proposal

Updated

Updated the proposal as per https://github.com/Expensify/App/issues/15108#issuecomment-1440424550 to include changes mentioned here

aimane-chnaif commented 1 year ago

@akshayasalvi's proposal looks good to me.

@daraksha-dk your updated proposal still references large data twice. @PrashantMangukiya your proposal 2 is same as @akshayasalvi's.

I just wonder if this should be on hold for https://github.com/Expensify/App/issues/15132 (or in reverse) because same file will be touched in two issues and might conflict. Also screenshots will be different.

🎀 👀 🎀 C+ reviewed

cc: @stitesExpensify

daraksha-dk commented 1 year ago

I think @akshayasalvi's proposal is same as mine it's just using the function differently which I was already addressing (provided an optimized and reusable function and could have provided another update if asked for)

@daraksha-dk your proposal will do the job

As @aimane-chnaif mentioned my proposal was working correctly and according to the new guidelines if the proposal's concept is correct then it should be chosen as the code improvements are to be done in PR. (Here, the concept and logic didn't change at all just one minor improvement which was already being addressed)

Quoting marc from slack thread:

Overall we value a solid proposal over raw “proof” that the solution works. The proof happens in the PR review.

I think if we are at the point where a code diff is necessary then you should be hired for the job and we are probably wasting time.

cc: @aimane-chnaif @stitesExpensify

aimane-chnaif commented 1 year ago

@daraksha-dk I requested changes for performance optimization and you were online at that moment. So I think it's fair. But in your updated proposal, you still didn't get the meaning of my suggestion. Since this is new feature request, there's no special root cause. Actually adding tooltip to button is a straightforward solution, so different proposals should come from how to implement. I will let @stitesExpensify decide whom we should go forward with.

stitesExpensify commented 1 year ago

I agree with @aimane-chnaif 's take on the situation. Because the actual solution (just add a tooltip) is straightforward, we should choose the most accurate proposal in the issue, which I believe in this case is @akshayasalvi.

MelvinBot commented 1 year ago

📣 @akshayasalvi You have been assigned to this job by @stitesExpensify! Please apply to this job in Upwork and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review 🧑‍💻 Keep in mind: Code of Conduct | Contributing 📖

akshayasalvi commented 1 year ago

@stitesExpensify @aimane-chnaif I can see a PR already for the linked issue so should I wait for the other PR to be merged or can I start with my PR?

aimane-chnaif commented 1 year ago

@stitesExpensify @aimane-chnaif I can see a PR already for the linked issue so should I wait for the other PR to be merged or can I start with my PR?

~I see that they're minor code changes and not much conflicts with ours, so I think you can start your PR.~ Hmm, @stitesExpensify can we hold this a bit? I think screenshots will be different after merging that PR. Hopefully that PR will be merged by tomorrow.

akshayasalvi commented 1 year ago

Yeah and then I'll have to test if Tooltip behavior doesn't cause issue in the later position of the Category Shortcuts Bar.

I think we should wait. But do let me know if you want me to start I'll start right away (I just don't want this to affect the PR bonus).

stitesExpensify commented 1 year ago

Yeah, let's wait until it's merged. I will make sure that the PR bonus is not affected.

akshayasalvi commented 1 year ago

@stitesExpensify The PR is now merged, I will now start the PR and raise it by tomorrow.

I would also recommend one additional refactor. We can move the following imports also to assets/emoji.js

Meanwhile, can you or @aimane-chnaif please confirm if you want this refactor to be done?

aimane-chnaif commented 1 year ago

@stitesExpensify The PR is now merged, I will now start the PR and raise it by tomorrow.

I would also recommend one additional refactor. We can move the following imports also to assets/emoji.js

Meanwhile, can you or @aimane-chnaif please confirm if you want this refactor to be done?

More like question for @stitesExpensify Leave as is for now

akshayasalvi commented 1 year ago

@aimane-chnaif @stitesExpensify One more question.

How much displacement should a Tooltip generally have from the icon?

This is how it looks after applying the Tooltip. If you notice it is applied to View, so the hover background is covered by the Tooltip.

Screenshot 2023-02-27 at 11 12 57 PM

I tried applying the Tooltip to Pressable, but we would have to move the styling to a View and then wrap that View around Tooltip.

Screenshot 2023-02-27 at 11 10 57 PM

Lastly, I applied shiftVertical={-8}, which I think is apt for this case. I am pushing with this change but happy to update with whatever path you choose.

Screenshot 2023-02-27 at 11 16 10 PM
stitesExpensify commented 1 year ago

please confirm if you want this refactor to be done?

Sure @akshayasalvi let's move those imports to emoji.js

How much displacement should a Tooltip generally have from the icon?

I'll defer to the expert :) @shawnborton

shawnborton commented 1 year ago

I think it should be what you have in your second screenshot, so shiftVertical={-8}

akshayasalvi commented 1 year ago

Okay @stitesExpensify I'll refactor that and thanks @shawnborton.

akshayasalvi commented 1 year ago

@stitesExpensify @aimane-chnaif PR is raised and ready for review.

aimane-chnaif commented 1 year ago

@shawnborton which one is preferred?

no space:

0px

2px:

2px

4px:

4px
akshayasalvi commented 1 year ago

@aimane-chnaif Based on this comment and this response, should we go ahead with 2px? And complete the checklist ?

Or do you recommend waiting more?

aimane-chnaif commented 1 year ago

Let's wait a bit more until design confirmation. Btw, I like 2px too

akshayasalvi commented 1 year ago

@aimane-chnaif I've update the change to have 2px. Because it was somewhat agreed earlier and you're also okay with it. Just to ensure that if I am offline later (and we get confirmation), it shouldn't block you from testing. If changes are requested, for 0px or 4px, I'll try to do them asap.

Meanwhile, is there any other change/feedback that needs to be worked upon? I am online for a few hours, so I can close them. Thank you very much for your time.

aimane-chnaif commented 1 year ago

@aimane-chnaif I've update the change to have 2px. Because it was somewhat agreed earlier and you're also okay with it. Just to ensure that if I am offline later (and we get confirmation), it shouldn't block you from testing. If changes are requested, for 0px or 4px, I'll try to do them asap.

Meanwhile, is there any other change/feedback that needs to be worked upon? I am online for a few hours, so I can close them. Thank you very much for your time.

I've already done reviewing and testing and after design confirmation, ready to fill checklist and approve on my side immediately. But there might be suggested changes from @stitesExpensify

akshayasalvi commented 1 year ago

@aimane-chnaif Can you add @stitesExpensify as a reviewer? When I requested your review again I don't know how it removed them. I can't seem to be able to add anybody.

aimane-chnaif commented 1 year ago

@aimane-chnaif Can you add @stitesExpensify as a reviewer? When I requested your review again I don't know how it removed them. I can't seem to be able to add anybody.

I also don't have permission. It's not your mistake. It often happens so seems github automation bug.

shawnborton commented 1 year ago

I think I like 4px since that is a standard spacing unit for us.

akshayasalvi commented 1 year ago

@shawnborton Okay I've updated the spacing to 4px.

Screenshot 2023-03-02 at 7 05 31 PM

cc - @aimane-chnaif if you want to test again.

stitesExpensify commented 1 year ago

For clarity for the bugZero assignee (@trjExpensify) we had this on hold, and then I was OOO and delayed the merging of this. This issue should be eligible for the speed bonus

MelvinBot commented 1 year ago

Reviewing label has been removed, please complete the "BugZero Checklist".

MelvinBot commented 1 year ago

The solution for this issue has been :rocket: deployed to production :rocket: in version 1.2.80-2 and is now subject to a 7-day regression period :calendar:. Here is the list of pull requests that resolve this issue:

If no regressions arise, payment will be issued on 2023-03-16. :confetti_ball:

After the hold period is over and BZ checklist items are completed, please complete any of the applicable payments for this issue, and check them off once done.

As a reminder, here are the bonuses/penalties that should be applied for any External issue: