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

Storage Add Ons: Implement dropdown checkout functionality #81340

Merged
merged 19 commits into from
Sep 25, 2023

Conversation

jeyip
Copy link
Contributor

@jeyip jeyip commented Sep 4, 2023

Related to #79041 (comment)
Issue https://github.com/Automattic/martech/issues/2025
Tracking https://github.com/Automattic/martech/issues/2023

Proposed Changes

  • Update checkout cart for /start signup onboarding flow with storage add ons

GIFs

2023-08-31 16 10 43

To be left as a Follow Up for the Future

  • Make the storage add-on in checkout cart a dropdown ( to allow user to switch between storage add-ons ) @saygunnyc has stated that this is something we can build on iteratively

Testing Instructions

Pre-merge Checklist

  • Has the general commit checklist been followed? (PCYsg-hS-p2)
  • https://wpcalypso.wordpress.com/devdocs/docs/testing/index.md for your changes?
  • Have you tested the feature in Simple (P9HQHe-k8-p2), Atomic (P9HQHe-jW-p2), and self-hosted Jetpack sites (PCYsg-g6b-p2)?
  • Have you checked for TypeScript, React or other console errors?
  • Have you used memoizing on expensive computations? More info in Memoizing with create-selector and Using memoizing selectors and Our Approach to Data
  • Have we added the "[Status] String Freeze" label as soon as any new strings were ready for translation (p4TIVU-5Jq-p2)?
  • For changes affecting Jetpack: Have we added the "[Status] Needs Privacy Updates" label if this pull request changes what data or activity we track or use (p4TIVU-ajp-p2)?

@jeyip jeyip self-assigned this Sep 4, 2023
@github-actions
Copy link

github-actions bot commented Sep 4, 2023

@jeyip jeyip changed the base branch from trunk to add/storage-addon-dropdown-UI-functionality September 4, 2023 03:16
@matticbot
Copy link
Contributor

matticbot commented Sep 4, 2023

Here is how your PR affects size of JS and CSS bundles shipped to the user's browser:

Sections (~598 bytes added 📈 [gzipped])

name                               parsed_size           gzip_size
update-design-flow                      +610 B  (+0.0%)     +185 B  (+0.1%)
link-in-bio-tld-flow                    +608 B  (+0.0%)     +175 B  (+0.0%)
plans                                   +532 B  (+0.0%)     +136 B  (+0.0%)
plugins                                 +495 B  (+0.0%)     +132 B  (+0.0%)
signup                                  +463 B  (+0.1%)     +142 B  (+0.2%)
home                                    +229 B  (+0.0%)      +71 B  (+0.0%)
free-flow                               +229 B  (+0.0%)      +72 B  (+0.0%)
jetpack-connect                         +228 B  (+0.0%)      +75 B  (+0.0%)
accept-invite                           +228 B  (+0.1%)      +72 B  (+0.1%)
write-flow                              +227 B  (+0.0%)      +72 B  (+0.0%)
videopress-flow                         +227 B  (+0.0%)      +74 B  (+0.0%)
build-flow                              +227 B  (+0.0%)      +72 B  (+0.0%)
checkout                                +166 B  (+0.0%)      +38 B  (+0.0%)
domains                                 +164 B  (+0.0%)      +36 B  (+0.0%)
tailored-ecommerce-flow                 +162 B  (+0.0%)      +37 B  (+0.0%)
sensei-flow                             +162 B  (+0.0%)      +37 B  (+0.0%)
podcasts-flow                           +162 B  (+0.0%)      +37 B  (+0.0%)
copy-site-flow                          +162 B  (+0.0%)      +37 B  (+0.0%)
themes                                  +149 B  (+0.0%)      +39 B  (+0.0%)
theme                                   +149 B  (+0.0%)      +39 B  (+0.0%)
site-purchases                          +147 B  (+0.0%)      +34 B  (+0.0%)
site-blocks                             +147 B  (+0.0%)      +37 B  (+0.0%)
security                                +147 B  (+0.0%)      +37 B  (+0.0%)
purchases                               +147 B  (+0.0%)      +34 B  (+0.0%)
privacy                                 +147 B  (+0.0%)      +37 B  (+0.0%)
notification-settings                   +147 B  (+0.0%)      +37 B  (+0.0%)
me                                      +147 B  (+0.0%)      +37 B  (+0.0%)
marketplace                             +147 B  (+0.0%)      +32 B  (+0.0%)
link-in-bio-flow-domain                 +147 B  (+0.6%)      +37 B  (+0.6%)
jetpack-cloud-pricing                   +147 B  (+0.0%)      +37 B  (+0.0%)
jetpack-cloud-features-comparison       +147 B  (+0.0%)      +37 B  (+0.0%)
help                                    +147 B  (+0.0%)      +37 B  (+0.0%)
email                                   +147 B  (+0.0%)      +37 B  (+0.0%)
connect-domain                          +147 B  (+0.6%)      +37 B  (+0.6%)
account-close                           +147 B  (+0.0%)      +37 B  (+0.0%)
account                                 +147 B  (+0.0%)      +39 B  (+0.0%)
add-ons                                  +31 B  (+0.0%)       +7 B  (+0.0%)
gutenberg-editor                         +15 B  (+0.0%)       +0 B

Sections contain code specific for a given set of routes. Is downloaded and parsed only when a particular route is navigated to.

Async-loaded Components (~148 bytes added 📈 [gzipped])

name                                                              parsed_size           gzip_size
async-load-signup-steps-plans-theme-preselected                        +349 B  (+0.1%)     +102 B  (+0.1%)
async-load-signup-steps-plans                                          +349 B  (+0.1%)     +102 B  (+0.1%)
async-load-calypso-my-sites-checkout-modal                             +166 B  (+0.0%)      +41 B  (+0.0%)
async-load-calypso-blocks-editor-checkout-modal                        +151 B  (+0.0%)      +41 B  (+0.0%)
async-load-calypso-my-sites-current-site-stale-cart-items-notice       +147 B  (+0.7%)      +37 B  (+0.7%)
async-load-signup-steps-add-ons                                         +32 B  (+0.0%)       +9 B  (+0.0%)
async-load-calypso-blocks-app-banner                                    +15 B  (+0.0%)       +0 B

React components that are loaded lazily, when a certain part of UI is displayed for the first time.

Legend

What is parsed and gzip size?

Parsed Size: Uncompressed size of the JS and CSS files. This much code needs to be parsed and stored in memory.
Gzip Size: Compressed size of the JS and CSS files. This much data needs to be downloaded over network.

Generated by performance advisor bot at iscalypsofastyet.com.

@jeyip jeyip marked this pull request as ready for review September 4, 2023 04:29
@@ -1270,7 +1269,7 @@ export function isNewOrExistingSiteFulfilled( stepName, defaultDependencies, nex
}
}

export const buildUpgradeFunction = ( planProps, cartItem ) => {
export const buildUpgradeFunction = ( planProps, cartItem, addOnItem ) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note:

Amendments to this file allow us to add storage add-ons to the shopping cart in signup onboarding flows

@jeyip jeyip requested review from a team and aneeshd16 September 4, 2023 23:45
@matticbot matticbot added [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. labels Sep 4, 2023
@jeyip
Copy link
Contributor Author

jeyip commented Sep 5, 2023

Note:

There's a delay between when a storage upgrade add-on is purchased and when the purchase is reflected in the /plans page ( it will look as if nothing has changed until a minute or two later ). I'll work more on this tomorrow

@jeyip jeyip force-pushed the add/storage-addon-dropdown-UI-functionality branch from 86e9897 to fe2ed2a Compare September 5, 2023 20:49
@jeyip jeyip force-pushed the add/storage-addon-dropdown-checkout-functionality branch from ab7ad7b to d4e35ef Compare September 5, 2023 23:31
Copy link
Contributor

@southp southp left a comment

Choose a reason for hiding this comment

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

@jeyip I didn't manage to look into the code deeply today, but the /start flow works as expected :)

Since we are now restricting it into /start only, could you help remove all the unncessary part outside of that? That will greatly reduce the required amout of code review and testing :)

@@ -140,7 +140,7 @@ const useAddOns = ( siteId?: number ): ( AddOnMeta | null )[] => {

const spaceUpgradesPurchased: number[] = [];

if ( filteredTransactions?.length ) {
if ( filteredTransactions?.length && siteId ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I understand why the siteId all of a sudden is needed here. Could you help me understand?

Copy link
Contributor Author

@jeyip jeyip Sep 15, 2023

Choose a reason for hiding this comment

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

Thanks for the patience!

This was meant to fix a bug when we call use-add-ons in the context of onboarding. For some reason, add-on data incorrectly decides that both 50GB add-ons and 100GB add-ons are already purchased, even though no site has been created yet.

Screenshot 2023-09-15 at 1 29 29 AM

To elaborate on why, filteredTransactions returns transactions for a given site when siteId exists. When, however, siteId is undefined, filteredTransactions fetches all transactions for a user, regardless of what site the purchase was made on.

Since I had made some space upgrade add-on purchase in the past on any site, the logic then proceeded to mark add-on data as purchased

// if storage add on is already purchased
if (
spaceUpgradesPurchased.findIndex(
( spaceUpgrade ) => spaceUpgrade === addOn.quantity
) >= 0 &&
product
) {
return {
...addOn,
name,
description,
purchased: true,
};
}

By checking for a truthy siteId, I intended to only look for space upgrade add-on transactions if the site has already been created ( and we're in the plans page )

With that being said, I wrote this when I was really tired 😴 , so we might consider better inline documentation or exploring alternative ways to address the bug. Ex. It looked like it might be possible to update the params for filterTransactions such that, when called with an undefined siteId, it returns no transactions, rather than all transactions, but I haven't looked to closely yet

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the explanation. It looks like the transaction data is used for filtering out the storage add-ons that have lower volumn than the owned one. Also, how the whole transaction data is fetched and filtered is actually quite non-ideal –– it fetches the whole transaction history and than filter from the client side, while all these should be done from the server side so our users don't have to waste their bandwidth and local computational resources to perform all these. Since correcting the whole thing would be out of scope, let's start by not fetching those transaction data in the onboarding flow since that doesn't make sense. It'd involve some level of decoupling, but we will have a cleaner code without tricky conditions needing explicit documentation :)

Copy link
Contributor Author

@jeyip jeyip Sep 20, 2023

Choose a reason for hiding this comment

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

I took a very simplistic approach to this in ce39121 and 21e2cfb. I added a guard with isInSignup to prevent fetching. I'm not sure if that's the best flag, but it seemed reasonable to me

@jeyip jeyip force-pushed the add/storage-addon-dropdown-UI-functionality branch from e5a8436 to 4a92911 Compare September 6, 2023 18:09
@jeyip
Copy link
Contributor Author

jeyip commented Sep 6, 2023

I didn't manage to look into the code deeply today, but the /start flow works as expected :)

Since we are now restricting it into /start only, could you help remove all the unncessary part outside of that? That will greatly reduce the required amout of code review and testing :)

Working on it now :D

@jeyip jeyip force-pushed the add/storage-addon-dropdown-checkout-functionality branch from e7f13f0 to 9527344 Compare September 6, 2023 22:46
@jeyip jeyip force-pushed the add/storage-addon-dropdown-UI-functionality branch from 3e7843b to 1ad269a Compare September 7, 2023 00:11
@jeyip jeyip force-pushed the add/storage-addon-dropdown-checkout-functionality branch 2 times, most recently from 9a05d1b to 7130bd4 Compare September 7, 2023 00:21
@jeyip
Copy link
Contributor Author

jeyip commented Sep 7, 2023

@vinimotaa 👋

Hey Vini! After purchasing the space storage add-on, it takes a minute or two for all of the information to be correctly updated in the database

When a user visits the plans page while the data is still being updated, they'll see incorrect storage information. Do you have thoughts on what we should display for the storage label to indicate the pending state?

Screenshot 2023-09-06 at 9 40 33 PM

One thing to note is that it's a bit of an edge case ( the user has to visit the plans page within a few minutes after making their purchase

I was also curious if we could figure out how to handle larger cost strings in the storage add on dropdown. My first thought is to round the cost up or down to the nearest dollar, or to hide the cost after selection

Screenshot 2023-09-01 at 12 46 31 AM

@southp
Copy link
Contributor

southp commented Sep 7, 2023

@jeyip Sorry for being ignorant about the design decisions made in the past, but could you help me point out the reference of showing the standard storage + the add-on storage in the plans grid? I'm asking since I feel this is a bit confusing:

  1. If we want to show the accumulated space, then I'm wondering if we should also do that for Free / Personal / Premium. Nothing prevent them from purchasing storage add-ons anyway :)
  2. Overall I feel it's risky to show the accumulated space without further explanation. As someone who is familar with that label, I might think the eCommerce plan has 100G space so I'd have 100G + 50G space once upgraded. Have we considered to separate them as two labels or something if we really want to emphasize the extra space from the owning storage add-on in the plans grid?

Also cc @gmovr and @dzver here in case you both happen to know this on top of your mind :)

@dzver
Copy link
Member

dzver commented Sep 7, 2023

@southp I don't know on top of my head. My goal is to unblock this task so that it gets shipped, and I'm leaning toward simplification rather than making things more complex. Whatever the design is, it has to show we support space upgrades, and that's pretty much the only solid requirement.

@jeyip could you point to the latest design on this? I don't see a link in the PR or the corresponding issue.

@jeyip
Copy link
Contributor Author

jeyip commented Sep 7, 2023

Sorry for being ignorant about the design decisions made in the past, but could you help me point out the reference of showing the standard storage + the add-on storage in the plans grid?

Sure I'd be happy to:

'm wondering if we should also do that for Free / Personal / Premium. Nothing prevent them from purchasing storage add-ons anyway :)

"As the 50 GB and 100GB storage upgrades don't make sense for Free, Personal, and Premium –Simply upgrading to the Business plan would provide 50 GB space much cheaper. I didn't include storage options for those plans on the grid even though they are technically possible."

https://github.com/Automattic/martech/issues/1907#issuecomment-1630537955

@southp
Copy link
Contributor

southp commented Sep 8, 2023

Thanks for pointing out the references for me, @jeyip :)

From my view, this design decision works with the dropdowns, since the label and the dropdowns are obviously communicating different things. However, when all that we have is the label, it doesn't work since they look the same but having different meanings. If we still agree to the original decision of rolling the add-on UI out to /start only, I think it's the best to not touch the label and just leave /plans the way it is –– we already have the storage add-ons and it's been this way, so it shouldn't be a deal breaker. We will then work on /plans as the next milestone.

Does that make sense to you?

@jeyip
Copy link
Contributor Author

jeyip commented Sep 12, 2023

If we still agree to the original decision of rolling the add-on UI out to /start only, I think it's the best to not touch the label and just leave /plans the way it is –– we already have the storage add-ons and it's been this way, so it shouldn't be a deal breaker. We will then work on /plans as the next milestone.

Does that make sense to you?

This does 🙂 If we end up changing our minds, we can draft a relatively quick PR to update the storage add-ons label in /plans as well

@jeyip jeyip force-pushed the add/storage-addon-dropdown-UI-functionality branch from 7f500b3 to 8384f7a Compare September 14, 2023 00:29
@@ -100,6 +102,7 @@ export interface PlanFeatures2023GridProps {
planTypeSelectorProps: PlanTypeSelectorProps;
// temporary: callback ref to scroll Odie AI Assistant into view once "Compare plans" button is clicked
observableForOdieRef: ( observableElement: Element | null ) => void;
selectedStorageOptions?: SelectedStorageOptionForPlans;
Copy link
Contributor

Choose a reason for hiding this comment

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

selectedStorageOptions prop doesn't seem relevant here and should be removed.
The only relevant type for your case is PlanFeatures2023GridType below I think

(it's a little confusing, I know. parts that are being cleaned up in other work)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for pointing this out! I removed the unnecessary type here d5a8c5c

@@ -111,6 +114,7 @@ interface PlanFeatures2023GridType extends PlanFeatures2023GridProps {
isPlanUpgradeCreditEligible: boolean;
// temporary: element ref to scroll comparison grid into view once "Compare plans" button is clicked
plansComparisonGridRef: ForwardedRef< HTMLDivElement >;
selectedStorageOptions?: SelectedStorageOptionForPlans;
Copy link
Contributor

Choose a reason for hiding this comment

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

so this is fine and the only place you need to define this

@jeyip
Copy link
Contributor Author

jeyip commented Sep 22, 2023

The final bit we need to address is the regression of the /start/domain flow.

There was a cartItem dependency for the site-picker step in the domain flow that needed to be updated to cartItems. On closer inspection, however, it appears as if the site-picker step doesn't need the dependency at all. The logic within the site-picker component makes no indication of needing it, so I remove the cartItem dependency instead. Some smoke testing seems to confirm this.

Additionally, the plans step in the domain flow was being skipped under certain circumstances, so we update the provided cartItem dependency to cartItems in those circumstances as well. As far as I can tell, the domain flow is now fixed

As it exists today, storage labels show the default amount of storage in the pricing grid, even if a storage upgrade add-on is purchased. We ensure that we continue to do so if the storage add-on dropdown is not displayed
Revert isEmpty change

Remove unnecessary check for cartItem

Fix pro plan upgrade button

Fix plan step unit test

Fix typescript errors
There was a cartItem dependency for the site-picker step that needed to be updated to cartItems. On closer inspection, however, it appears as if the site-picker step doesn't need the dependency at all. The logic within the site-picker component makes no indication of needing it, so I remove the cartItem dependency instead.

Additionally, the plans step in the domain flow was being skipped under certain circumstances, so we update the provided cartItem dependency to cartItems in those circumstances as well.
@jeyip jeyip force-pushed the add/storage-addon-dropdown-checkout-functionality branch from 9da13ef to d09c44b Compare September 24, 2023 20:59
@jeyip jeyip mentioned this pull request Sep 25, 2023
7 tasks
Copy link
Contributor

@southp southp left a comment

Choose a reason for hiding this comment

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

Beautifully done. Thanks for the great effort you've put into the fix, @jeyip . It's impressive to see you go extra miles further tidying the code up while fixing it up.

@southp
Copy link
Contributor

southp commented Sep 25, 2023

Also, since @chriskmnds has two PRs based on this PR(#81960 and #82054), I'm deploying this shortly to move things forward :)

@southp southp merged commit 5975148 into trunk Sep 25, 2023
@southp southp deleted the add/storage-addon-dropdown-checkout-functionality branch September 25, 2023 07:01
@github-actions github-actions bot removed the [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. label Sep 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants