diff --git a/.changeset/four-peaches-bake.md b/.changeset/four-peaches-bake.md new file mode 100644 index 0000000000..fc3d4577a2 --- /dev/null +++ b/.changeset/four-peaches-bake.md @@ -0,0 +1,5 @@ +--- +"@graphcommerce/magento-cart": patch +--- + +When signing in the cartFab would not always properly reflect the current items in the cart diff --git a/.changeset/quiet-boats-leave.md b/.changeset/quiet-boats-leave.md new file mode 100644 index 0000000000..c16a80afef --- /dev/null +++ b/.changeset/quiet-boats-leave.md @@ -0,0 +1,6 @@ +--- +'@graphcommerce/magento-customer': patch +'@graphcommerce/magento-cart': patch +--- + +Added user session reevaluation after unathenticated call. Queries will be paused untill user has signed in again diff --git a/.changeset/rude-bags-draw.md b/.changeset/rude-bags-draw.md new file mode 100644 index 0000000000..9476e457b3 --- /dev/null +++ b/.changeset/rude-bags-draw.md @@ -0,0 +1,5 @@ +--- +"@graphcommerce/magento-customer": patch +--- + +Created a debug.sessions config that allows debugging sessions. Enable with GC_DEBUG_SESSIONS=1 in your env or modify your graphcommerce.config.js diff --git a/.gitignore b/.gitignore index 74170c4c4f..8d68207d37 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ # dependencies node_modules +/.pnp +.pnp.js +.swc # testing /coverage diff --git a/docs/framework/config.md b/docs/framework/config.md index 8979e76fc0..2f8ecf2865 100644 --- a/docs/framework/config.md +++ b/docs/framework/config.md @@ -311,6 +311,10 @@ Debug configuration for GraphCommerce Reports which plugins are enabled or disabled. +#### sessions: boolean + +Enable debugging interface to debug sessions + #### webpackCircularDependencyPlugin: boolean Cyclic dependencies can cause memory issues and other strange bugs. diff --git a/packages/magento-cart/hooks/UseMergeCustomerCart.graphql b/packages/magento-cart/hooks/UseMergeCustomerCart.graphql index 0f135dc187..2ffb7fc8ad 100644 --- a/packages/magento-cart/hooks/UseMergeCustomerCart.graphql +++ b/packages/magento-cart/hooks/UseMergeCustomerCart.graphql @@ -2,5 +2,6 @@ mutation UseMergeCustomerCart($sourceCartId: String!, $destinationCartId: String mergeCarts(source_cart_id: $sourceCartId, destination_cart_id: $destinationCartId) { __typename id + ...CartItemCountChanged } } diff --git a/packages/magento-cart/link/createCartErrorLink.ts b/packages/magento-cart/link/createCartErrorLink.ts index 4c859699f9..b86ae4e00a 100644 --- a/packages/magento-cart/link/createCartErrorLink.ts +++ b/packages/magento-cart/link/createCartErrorLink.ts @@ -26,10 +26,6 @@ export const cartErrorLink = onError(({ graphQLErrors, operation, forward }) => const isErrorCategory = (err: GraphQLError, category: ErrorCategory) => err.extensions?.category === category - const isAuthorizationError = (err: GraphQLError) => - isErrorCategory(err, 'graphql-authorization') && - errorIsIncluded(err.path, ['addProductsToCart']) - const isNoSuchEntityError = (err: GraphQLError) => isErrorCategory(err, 'graphql-no-such-entity') && errorIsIncluded(err.path, [ @@ -49,7 +45,7 @@ export const cartErrorLink = onError(({ graphQLErrors, operation, forward }) => // 'applyCouponToCart', // 'removeCouponFromCart' ]) - const cartErr = graphQLErrors.find((err) => isNoSuchEntityError(err) || isAuthorizationError(err)) + const cartErr = graphQLErrors.find((err) => isNoSuchEntityError(err)) if (!cartErr) return undefined diff --git a/packages/magento-customer/Config.graphqls b/packages/magento-customer/Config.graphqls index 24557497f6..f665860d89 100644 --- a/packages/magento-customer/Config.graphqls +++ b/packages/magento-customer/Config.graphqls @@ -19,3 +19,10 @@ extend input GraphCommerceConfig { """ enableGuestCheckoutLogin: Boolean } + +extend input GraphCommerceDebugConfig { + """ + Enable debugging interface to debug sessions + """ + sessions: Boolean +} diff --git a/packages/magento-customer/components/AccountSignInUpForm/AccountSignInUpForm.tsx b/packages/magento-customer/components/AccountSignInUpForm/AccountSignInUpForm.tsx index d3380015dc..2b930dd200 100644 --- a/packages/magento-customer/components/AccountSignInUpForm/AccountSignInUpForm.tsx +++ b/packages/magento-customer/components/AccountSignInUpForm/AccountSignInUpForm.tsx @@ -1,7 +1,7 @@ -import { TextFieldElement, emailPattern } from '@graphcommerce/ecommerce-ui' +import { FormAutoSubmit, TextFieldElement, emailPattern } from '@graphcommerce/ecommerce-ui' +import { useApolloClient } from '@graphcommerce/graphql' import { ActionCard, - ActionCardLayout, ActionCardListForm, Button, FormActions, @@ -13,11 +13,11 @@ import { import { Trans } from '@lingui/react' import { Box, CircularProgress, Link, SxProps, Theme, Typography } from '@mui/material' import { useRouter } from 'next/router' -import { useEffect } from 'react' -import { CustomerDocument, useFormIsEmailAvailable } from '../../hooks' +import { CustomerDocument, useAccountSignInUpForm } from '../../hooks' import { useCustomerQuery } from '../../hooks/useCustomerQuery' import { ApolloCustomerErrorAlert } from '../ApolloCustomerError' import { SignInForm } from '../SignInForm/SignInForm' +import { signOut } from '../SignOutForm/signOut' import { SignUpForm } from '../SignUpForm/SignUpForm' export type AccountSignInUpFormProps = { sx?: SxProps } @@ -25,96 +25,87 @@ export type AccountSignInUpFormProps = { sx?: SxProps } const parts = ['root', 'titleContainer'] as const const { classes } = extendableComponent('AccountSignInUpForm', parts) -const titleContainerSx: SxProps = (theme) => ({ - typography: 'body1', - marginBottom: theme.spacings.xs, -}) - export function AccountSignInUpForm(props: AccountSignInUpFormProps) { const { sx = [] } = props const customerQuery = useCustomerQuery(CustomerDocument) const { email, firstname = '' } = customerQuery.data?.customer ?? {} - const { mode, form, autoSubmitting, submit } = useFormIsEmailAvailable({ email }) + const { mode, form, submit } = useAccountSignInUpForm() const { formState, watch, control, error } = form - const disableFields = formState.isSubmitting && !autoSubmitting - - const { setValue, trigger } = form const router = useRouter() - useEffect(() => { - const emailFromParams = router.query.email as string - if (!email && emailFromParams) { - setValue('email', emailFromParams) - // eslint-disable-next-line @typescript-eslint/no-floating-promises - trigger('email') - } - }, [email, router.query.email, setValue, trigger]) + + const client = useApolloClient() return ( - {mode === 'email' && ( - - - - - - - - - )} + ({ typography: 'body1', marginBottom: theme.spacings.xs })} + > + {mode === 'email' && ( + <> + + + + + + + + )} - {mode === 'signin' && ( - - - - - - - - - )} + {mode === 'signin' && ( + <> + + + + + + + + )} - {mode === 'signup' && ( - - - - - - - - - )} + {mode === 'signup' && ( + <> + + + + + + + + )} - {mode === 'signedin' && ( - - - - - - - - - - - - - - - )} + {mode === 'signedin' && ( + <> + + + + + + + + + + + + + + )} - {mode === 'session-expired' && ( - - - - - - - - - )} + {mode === 'session-expired' && ( + <> + + + + + + + + )} + {!import.meta.graphCommerce.enableGuestCheckoutLogin && (mode === 'signin' || mode === 'signup' || mode === 'email') && ( @@ -144,6 +135,7 @@ export function AccountSignInUpForm(props: AccountSignInUpFormProps) { {mode !== 'signedin' && (
+ } - disabled={disableFields} InputProps={{ - endAdornment: formState.isSubmitting && ( - - ), + endAdornment: + mode === 'session-expired' ? ( + + ) : ( + formState.isSubmitting && + ), readOnly: !!email, }} /> @@ -171,7 +177,7 @@ export function AccountSignInUpForm(props: AccountSignInUpFormProps) { - {(mode === 'email' || mode === 'session-expired') && ( + {mode === 'email' && ( - - - ) -} diff --git a/packages/magento-customer/components/SignInForm/SignInForm.tsx b/packages/magento-customer/components/SignInForm/SignInForm.tsx index 21e329fe69..919ae27be7 100644 --- a/packages/magento-customer/components/SignInForm/SignInForm.tsx +++ b/packages/magento-customer/components/SignInForm/SignInForm.tsx @@ -8,8 +8,9 @@ import { Box, FormControl, Link, SxProps, Theme } from '@mui/material' import { CustomerDocument } from '../../hooks' import { ApolloCustomerErrorAlert } from '../ApolloCustomerError/ApolloCustomerErrorAlert' import { SignInDocument } from './SignIn.gql' +import { signOut } from '../SignOutForm/signOut' -type SignInFormProps = { email: string; sx?: SxProps } +export type SignInFormProps = { email: string; sx?: SxProps } export function SignInForm(props: SignInFormProps) { const { email, sx } = props @@ -25,7 +26,7 @@ export function SignInForm(props: SignInFormProps) { * We are logging in because the session expired, but we're logging in with a different * email address, we need to reset the store. */ - if (oldEmail && oldEmail !== email) await client.resetStore() + if (oldEmail && oldEmail !== email) signOut(client) return { ...values, email } }, }, @@ -75,7 +76,7 @@ export function SignInForm(props: SignInFormProps) { variant='pill' size='large' > - + diff --git a/packages/magento-customer/components/SignOutForm/SignOutForm.tsx b/packages/magento-customer/components/SignOutForm/SignOutForm.tsx index 0e5e32b414..bcdb3389b0 100644 --- a/packages/magento-customer/components/SignOutForm/SignOutForm.tsx +++ b/packages/magento-customer/components/SignOutForm/SignOutForm.tsx @@ -4,13 +4,14 @@ import { useRouter } from 'next/router' import React from 'react' import { ApolloCustomerErrorAlert } from '../ApolloCustomerError/ApolloCustomerErrorAlert' import { SignOutFormDocument } from './SignOutForm.gql' +import { signOut } from './signOut' type SignOutFormProps = { button: (props: { formState: FormState> }) => React.ReactNode } export function SignOutForm(props: SignOutFormProps) { - const { button } = props + const { button: Button } = props const router = useRouter() const client = useApolloClient() @@ -18,7 +19,7 @@ export function SignOutForm(props: SignOutFormProps) { SignOutFormDocument, { onComplete: async () => { - await client.clearStore() + signOut(client) await router.push('/') }, }, @@ -28,7 +29,7 @@ export function SignOutForm(props: SignOutFormProps) { return ( - {button({ formState })} +