upcoming: [UIE-9823] - Implement the Contact Sales Drawer for Marketplace products#13368
upcoming: [UIE-9823] - Implement the Contact Sales Drawer for Marketplace products#13368harsh-akamai merged 28 commits intolinode:developfrom
Conversation
|
The form initializes additional email to ['']. API Spec expects: ["email1@akamai.com"] or omit if empty |
|
One observation in api spec doc there is a typo API Spec shows: "parner_name": "Akamai" (typo - missing 't'). Please get this corrected from backend team. |
| ? getAPIErrorOrDefault(error)?.[0].reason | ||
| : "Oops! Something went wrong and we couldn't send your contacts. Please try again in a moment, or refresh the page."; | ||
| enqueueSnackbar(errorMessage, { variant: 'error' }); | ||
| onClose(); |
There was a problem hiding this comment.
On api error do we need to close the drawer?
There was a problem hiding this comment.
The snackbar will only be shown if we close the drawer.
There was a problem hiding this comment.
We might not want to close the drawer on API errors since that would require the user to re-enter their details, which isn't ideal. Typically, in CM, we don't close drawers when an API call fails; instead, we usually show an error notification banner within the drawer itself
I also noticed that form data persists when reopening the drawer, but navigating between tabs within the details page resets the form data. I think the drawer should always open with an empty state
| return ( | ||
| <Drawer | ||
| data-testid="contact-sales-drawer" | ||
| onClose={() => { |
There was a problem hiding this comment.
Instead of resetting the form onClose which can cause visual glitches if the form resets while the drawer is animating closed. we can use onTransitionExited={() => reset()}
packages/manager/src/features/Marketplace/ProductDetails/ContactSalesDrawer.tsx
Show resolved
Hide resolved
| } from '@linode/ui'; | ||
| import { createPartnerReferralSchema } from '@linode/validation'; | ||
| import { createFilterOptions, Grid } from '@mui/material'; | ||
| import { enqueueSnackbar } from 'notistack'; |
There was a problem hiding this comment.
mostly this pattern is follwed in the codebase import { useSnackbar } from 'notistack';
const { enqueueSnackbar } = useSnackbar(); . Direct import works but is inconsistent with codebase conventions.
There was a problem hiding this comment.
I believe both the implementations are supported. Importing enqueueSnackBar has been followed in multiple places like here: https://github.com/linode/manager/blob/develop/packages/manager/src/features/Kubernetes/KubernetesClusterDetail/KubeEntityDetailFooter.tsx#L6
packages/manager/src/features/Marketplace/ProductDetails/ContactSalesDrawer.tsx
Show resolved
Hide resolved
| <MultipleIPInput | ||
| buttonText="Add email address" | ||
| className={ | ||
| field.value?.length === 2 |
There was a problem hiding this comment.
can we use a constant here : MAX_ADDITIONAL_EMAILS = 2
|
|
||
| const { | ||
| control, | ||
| formState: { errors, isSubmitting }, |
There was a problem hiding this comment.
When the form is submitted While isSubmitting is used to disable form fields. Is this is correct submitting state. Can we check with ux on this.
| const { classes } = useStyles(); | ||
| const { onClose, open, partnerName, productName } = props; | ||
|
|
||
| const { data: profile } = useProfile(); |
There was a problem hiding this comment.
Are we sure this data is not asynchronous and will always be available when drawer is opened? Basically do you this we should handle async nature of this data?
There was a problem hiding this comment.
The useProfile() api is loaded on login so we will always have the data.
packages/manager/src/features/Marketplace/ProductDetails/ContactSalesDrawer.tsx
Show resolved
Hide resolved
packages/manager/src/features/Marketplace/ProductDetails/ContactSalesDrawer.tsx
Show resolved
Hide resolved
| */ | ||
| renderVariant?: () => JSX.Element | null; | ||
| /** | ||
| * An optional prop to set the ARIA role of the selection card. |
There was a problem hiding this comment.
| * An optional prop to set the ARIA role of the selection card. | |
| * An optional prop to set the ARIA role of the selection card. |
Very minor nit: extra spacing between words
| }} | ||
| > | ||
| Load More... | ||
| Load more offers > |
| slotProps={{ | ||
| paper: { | ||
| sx: { | ||
| overflow: 'hidden', | ||
| // Set the options width to cover the entire textfield when the drawer is at or above its designed width | ||
| width: { | ||
| sm: '401px', | ||
| xs: '366px', | ||
| }, | ||
| // When the drawer width is less than 445px, expand to drawer width (minus padding offset) on mobile | ||
| '@media (max-width: 445px)': { | ||
| width: 'calc(100vw - 79px)', | ||
| }, | ||
| }, | ||
| }, | ||
| }} |
There was a problem hiding this comment.
| slotProps={{ | |
| paper: { | |
| sx: { | |
| overflow: 'hidden', | |
| // Set the options width to cover the entire textfield when the drawer is at or above its designed width | |
| width: { | |
| sm: '401px', | |
| xs: '366px', | |
| }, | |
| // When the drawer width is less than 445px, expand to drawer width (minus padding offset) on mobile | |
| '@media (max-width: 445px)': { | |
| width: 'calc(100vw - 79px)', | |
| }, | |
| }, | |
| }, | |
| }} |
I don't see any effect from these slotProps styles on the phone number field. We usually avoid using media queries directly like this and prefer breakpoints instead. Since I didn't notice any visible impact from the above, this might not be required at all. Could you double-check?
There was a problem hiding this comment.
The slotProps help set the width for the options dropdown.
I've used media queries because the drawer width is set to 445px for small screens. Using breakpoints here wouldn't really help once we reach screen sizes less than the drawer width.
| }} | ||
| options={countryList} | ||
| placeholder="" | ||
| renderOption={({ key, ...props }, option) => ( |
There was a problem hiding this comment.
Looks like this key prop is unused here
packages/manager/src/features/Marketplace/ProductDetails/ContactSalesDrawer.tsx
Show resolved
Hide resolved
packages/manager/src/features/Marketplace/ProductDetails/ContactSalesDrawer.tsx
Show resolved
Hide resolved
packages/manager/src/features/Marketplace/ProductDetails/ContactSalesDrawer.tsx
Show resolved
Hide resolved
pmakode-akamai
left a comment
There was a problem hiding this comment.
thanks @harsh-akamai! Since we made the ARAI role prop optional (with no default) in SelectionCard, I think we'll still need to pass role="button" from ProductSelectionCard.tsx just for this case
Cloud Manager UI test results🔺 2 failing tests on test run #24 ↗︎
Details
TroubleshootingUse this command to re-run the failing tests: pnpm cy:run -s "cypress/e2e/core/linodes/rebuild-linode.spec.ts,cypress/e2e/core/cloudpulse/timerange-verification.spec.ts" |
||||||||||||||||||||

Description 📝
Implement the Contact Sales Drawer for Marketplace products
Scope 🚢
Upon production release, changes in this PR will be visible to:
Preview 📷
How to test 🧪
Prerequisites
Verification steps
Author Checklists
As an Author, to speed up the review process, I considered 🤔
👀 Doing a self review
❔ Our contribution guidelines
🤏 Splitting feature into small PRs
➕ Adding a changeset
🧪 Providing/improving test coverage
🔐 Removing all sensitive information from the code and PR description
🚩 Using a feature flag to protect the release
👣 Providing comprehensive reproduction steps
📑 Providing or updating our documentation
🕛 Scheduling a pair reviewing session
📱 Providing mobile support
♿ Providing accessibility support
As an Author, before moving this PR from Draft to Open, I confirmed ✅