From ed4abb4cfe30f73899d397f35970286b3c7e7885 Mon Sep 17 00:00:00 2001 From: amorcian Date: Thu, 14 May 2020 16:27:20 +0300 Subject: [PATCH 1/7] Add external JSX rendering to Vetrina component --- apps/vetrina-staging/.build-size-sha256 | 2 +- packages/vetrina/src/Vetrina/Vetrina.purs | 86 +++++++++++++---------- 2 files changed, 51 insertions(+), 37 deletions(-) diff --git a/apps/vetrina-staging/.build-size-sha256 b/apps/vetrina-staging/.build-size-sha256 index 41cdd3f57..d77538bf3 100644 --- a/apps/vetrina-staging/.build-size-sha256 +++ b/apps/vetrina-staging/.build-size-sha256 @@ -1,3 +1,3 @@ # SHA256 of the content of the build directory. # This is used for triggering project deployment when there are updated dependecies. -be1d6a49da254740363a4b0785c517318a36979b6f7f8d068e75acbfbaaf93d7 +803dd7a35f702d4798c0d290d83bae061ee2df8558dbad0958db14d9ac97f1c4 diff --git a/packages/vetrina/src/Vetrina/Vetrina.purs b/packages/vetrina/src/Vetrina/Vetrina.purs index 8e6f43621..58371decb 100644 --- a/packages/vetrina/src/Vetrina/Vetrina.purs +++ b/packages/vetrina/src/Vetrina/Vetrina.purs @@ -41,12 +41,14 @@ type JSProps = { onClose :: Nullable (Effect Unit) , onLogin :: Nullable (Effect Unit) , products :: Nullable (Array JSProduct) + , unexpectedError :: Nullable JSX } type Props = - { onClose :: Effect Unit - , onLogin :: Effect Unit - , products :: Either Error (Array Product) + { onClose :: Effect Unit + , onLogin :: Effect Unit + , products :: Either Error (Array Product) + , unexpectedError :: Maybe JSX } fromJSProps :: JSProps -> Props @@ -61,18 +63,20 @@ fromJSProps jsProps = , not null products -> Right products | otherwise -> Left productError Nothing -> Left productError + , unexpectedError : toMaybe jsProps.unexpectedError } type State = - { user :: Maybe User - , purchaseState :: PurchaseState - , poller :: Aff.Fiber Unit - , isLoading :: Maybe Spinner.Loading - , accountStatus :: AccountStatus - , logger :: Sentry.Logger - , products :: Array Product + { user :: Maybe User + , purchaseState :: PurchaseState + , poller :: Aff.Fiber Unit + , isLoading :: Maybe Spinner.Loading + , accountStatus :: AccountStatus + , logger :: Sentry.Logger + , products :: Array Product , productSelection :: Maybe Product - , paymentMethod :: User.PaymentMethod + , paymentMethod :: User.PaymentMethod + , unexpectedError :: JSX } type Self = React.Self Props State @@ -88,6 +92,7 @@ data PurchaseState | PurchaseFailed OrderFailure | PurchaseSetPassword | PurchaseCompleted AccountStatus + | UnexpectedServerError data OrderFailure = EmailInUse String @@ -121,34 +126,41 @@ initialState = , products: [] , productSelection: Nothing , paymentMethod: CreditCard + , unexpectedError: mempty } didMount :: Self -> Effect Unit -didMount self = do - sentryDsn <- sentryDsn_ - logger <- Sentry.mkLogger sentryDsn Nothing - self.setState _ { logger = logger } - -- Before rendering the form, we need to: - -- 1. fetch the user if access token is found in the browser - Aff.launchAff_ do - Aff.finally - -- When user has been fetched, hide loading spinner - (liftEffect $ self.setState \s -> s { isLoading = Nothing }) - do - -- Try to login with local storage information and set user to state - tryMagicLogin self - - products <- liftEffect $ case self.props.products of - Right p -> pure p - Left err -> do - self.setState _ { purchaseState = PurchaseFailed $ UnexpectedError "" } - logger.error err - throwError err - - liftEffect $ self.setState _ { products = products } - -- If there is only one product given, automatically select that for the customer - when (length products == 1) $ - liftEffect $ self.setState _ { productSelection = head products } +didMount self = + case self.props.unexpectedError of + Just view -> + self.setState _ { purchaseState = UnexpectedServerError + , unexpectedError = view + } + Nothing -> do + sentryDsn <- sentryDsn_ + logger <- Sentry.mkLogger sentryDsn Nothing + self.setState _ { logger = logger } + -- Before rendering the form, we need to: + -- 1. fetch the user if access token is found in the browser + Aff.launchAff_ do + Aff.finally + -- When user has been fetched, hide loading spinner + (liftEffect $ self.setState \s -> s { isLoading = Nothing }) + do + -- Try to login with local storage information and set user to state + tryMagicLogin self + + products <- liftEffect $ case self.props.products of + Right p -> pure p + Left err -> do + self.setState _ { purchaseState = PurchaseFailed $ UnexpectedError "" } + logger.error err + throwError err + + liftEffect $ self.setState _ { products = products } + -- If there is only one product given, automatically select that for the customer + when (length products == 1) $ + liftEffect $ self.setState _ { productSelection = head products } tryMagicLogin :: Self -> Aff Unit tryMagicLogin self = @@ -274,6 +286,8 @@ render self = vetrinaContainer self $ , user: self.state.user , accountStatus } + UnexpectedServerError -> + self.state.unexpectedError where onRetry = self.setState _ { purchaseState = NewPurchase } From 6e437f32390b1abce3e79c8e38f0d3daf1565d9d Mon Sep 17 00:00:00 2001 From: amorcian Date: Fri, 15 May 2020 14:32:33 +0300 Subject: [PATCH 2/7] Fix Vetrina module * Add InitializationError constructor to OrderFailure * Remove UnexpectedServerError from PurchaseState * Change prop unexpectedError type to JSX * Render external view on InitializationError, UnexpectedError, ServerError --- packages/vetrina/src/Vetrina/Vetrina.purs | 70 +++++++++++------------ 1 file changed, 32 insertions(+), 38 deletions(-) diff --git a/packages/vetrina/src/Vetrina/Vetrina.purs b/packages/vetrina/src/Vetrina/Vetrina.purs index 58371decb..4bc5f740a 100644 --- a/packages/vetrina/src/Vetrina/Vetrina.purs +++ b/packages/vetrina/src/Vetrina/Vetrina.purs @@ -48,7 +48,7 @@ type Props = { onClose :: Effect Unit , onLogin :: Effect Unit , products :: Either Error (Array Product) - , unexpectedError :: Maybe JSX + , unexpectedError :: JSX } fromJSProps :: JSProps -> Props @@ -63,7 +63,7 @@ fromJSProps jsProps = , not null products -> Right products | otherwise -> Left productError Nothing -> Left productError - , unexpectedError : toMaybe jsProps.unexpectedError + , unexpectedError : fromMaybe mempty $ toMaybe jsProps.unexpectedError } type State = @@ -76,7 +76,6 @@ type State = , products :: Array Product , productSelection :: Maybe Product , paymentMethod :: User.PaymentMethod - , unexpectedError :: JSX } type Self = React.Self Props State @@ -92,11 +91,11 @@ data PurchaseState | PurchaseFailed OrderFailure | PurchaseSetPassword | PurchaseCompleted AccountStatus - | UnexpectedServerError data OrderFailure = EmailInUse String | SubscriptionExists + | InitializationError | FormFieldError (Array NewPurchase.FormInputField) | AuthenticationError | ServerError @@ -126,41 +125,34 @@ initialState = , products: [] , productSelection: Nothing , paymentMethod: CreditCard - , unexpectedError: mempty } didMount :: Self -> Effect Unit -didMount self = - case self.props.unexpectedError of - Just view -> - self.setState _ { purchaseState = UnexpectedServerError - , unexpectedError = view - } - Nothing -> do - sentryDsn <- sentryDsn_ - logger <- Sentry.mkLogger sentryDsn Nothing - self.setState _ { logger = logger } - -- Before rendering the form, we need to: - -- 1. fetch the user if access token is found in the browser - Aff.launchAff_ do - Aff.finally - -- When user has been fetched, hide loading spinner - (liftEffect $ self.setState \s -> s { isLoading = Nothing }) - do - -- Try to login with local storage information and set user to state - tryMagicLogin self - - products <- liftEffect $ case self.props.products of - Right p -> pure p - Left err -> do - self.setState _ { purchaseState = PurchaseFailed $ UnexpectedError "" } - logger.error err - throwError err - - liftEffect $ self.setState _ { products = products } - -- If there is only one product given, automatically select that for the customer - when (length products == 1) $ - liftEffect $ self.setState _ { productSelection = head products } +didMount self = do + sentryDsn <- sentryDsn_ + logger <- Sentry.mkLogger sentryDsn Nothing + self.setState _ { logger = logger } + -- Before rendering the form, we need to: + -- 1. fetch the user if access token is found in the browser + Aff.launchAff_ do + Aff.finally + -- When user has been fetched, hide loading spinner + (liftEffect $ self.setState \s -> s { isLoading = Nothing }) + do + -- Try to login with local storage information and set user to state + tryMagicLogin self + + products <- liftEffect $ case self.props.products of + Right p -> pure p + Left err -> do + self.setState _ { purchaseState = PurchaseFailed $ InitializationError } + logger.error err + throwError err + + liftEffect $ self.setState _ { products = products } + -- If there is only one product given, automatically select that for the customer + when (length products == 1) $ + liftEffect $ self.setState _ { productSelection = head products } tryMagicLogin :: Self -> Aff Unit tryMagicLogin self = @@ -265,6 +257,10 @@ render self = vetrinaContainer self $ , productSelection: self.state.productSelection , onLogin: self.props.onLogin } + ServerError -> self.props.unexpectedError + UnexpectedError _ -> self.props.unexpectedError + InitializationError -> + self.props.unexpectedError _ -> Purchase.Error.error { onRetry: onRetry @@ -286,8 +282,6 @@ render self = vetrinaContainer self $ , user: self.state.user , accountStatus } - UnexpectedServerError -> - self.state.unexpectedError where onRetry = self.setState _ { purchaseState = NewPurchase } From 01acc2d5a40c89c4fd04f430ba518d2e6d96b7c2 Mon Sep 17 00:00:00 2001 From: amorcian Date: Fri, 15 May 2020 14:36:05 +0300 Subject: [PATCH 3/7] Update vetrina-staging build hash --- apps/vetrina-staging/.build-size-sha256 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vetrina-staging/.build-size-sha256 b/apps/vetrina-staging/.build-size-sha256 index d77538bf3..6e9c73211 100644 --- a/apps/vetrina-staging/.build-size-sha256 +++ b/apps/vetrina-staging/.build-size-sha256 @@ -1,3 +1,3 @@ # SHA256 of the content of the build directory. # This is used for triggering project deployment when there are updated dependecies. -803dd7a35f702d4798c0d290d83bae061ee2df8558dbad0958db14d9ac97f1c4 +9e9416f3f41961084ec02d2949de68ed736302bc6c54e284f28ae2d8da8a53cb From 8510b3fb68f4fdfb38f05932986f91cdf74f03db Mon Sep 17 00:00:00 2001 From: amorcian Date: Fri, 15 May 2020 16:32:23 +0300 Subject: [PATCH 4/7] Fix Vetrina module * Render vetrina error view on ServerError, UnexpectedError --- packages/vetrina/src/Vetrina/Vetrina.purs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/vetrina/src/Vetrina/Vetrina.purs b/packages/vetrina/src/Vetrina/Vetrina.purs index 4bc5f740a..809944999 100644 --- a/packages/vetrina/src/Vetrina/Vetrina.purs +++ b/packages/vetrina/src/Vetrina/Vetrina.purs @@ -257,8 +257,14 @@ render self = vetrinaContainer self $ , productSelection: self.state.productSelection , onLogin: self.props.onLogin } - ServerError -> self.props.unexpectedError - UnexpectedError _ -> self.props.unexpectedError + ServerError -> + Purchase.Error.error + { onRetry: onRetry + } + UnexpectedError _ -> + Purchase.Error.error + { onRetry: onRetry + } InitializationError -> self.props.unexpectedError _ -> From 2c39b4048509875e853f3a13ab8874da9195c559 Mon Sep 17 00:00:00 2001 From: amorcian Date: Fri, 15 May 2020 16:41:25 +0300 Subject: [PATCH 5/7] Update vetrina build hash --- apps/vetrina-staging/.build-size-sha256 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vetrina-staging/.build-size-sha256 b/apps/vetrina-staging/.build-size-sha256 index 6e9c73211..d13f1a5a7 100644 --- a/apps/vetrina-staging/.build-size-sha256 +++ b/apps/vetrina-staging/.build-size-sha256 @@ -1,3 +1,3 @@ # SHA256 of the content of the build directory. # This is used for triggering project deployment when there are updated dependecies. -9e9416f3f41961084ec02d2949de68ed736302bc6c54e284f28ae2d8da8a53cb +d68175e2899308e3a36e5ac9847b68ec94ffc26c62155ce357a1535a2f1d287c From b83893dd02e914ef86348cc19e3e6b6986230338 Mon Sep 17 00:00:00 2001 From: amorcian Date: Fri, 15 May 2020 16:41:59 +0300 Subject: [PATCH 6/7] Update vetrina README --- packages/vetrina/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/vetrina/README.md b/packages/vetrina/README.md index 70d97f86e..7722b197e 100644 --- a/packages/vetrina/README.md +++ b/packages/vetrina/README.md @@ -1,8 +1,8 @@ # ksf-media/vetrina - + ## For javascript use -Install it from npm `yarn add @ksf-media/vetrina` and just import it into your project: +Install it from npm `yarn add @ksf-media/vetrina` and just import it into your project: ```javascript import ReactDOM from 'react-dom'; import { Vetrina } from '@ksf-media/vetrina'; @@ -24,6 +24,9 @@ The props/callbacks for `Vetrina` are - products - an array of `Products` we want to be subscribeable, see type of `Product` below - `products={[id: "HBL", description: "HBL is amazing!", priceCents: 990 }]}` +- unexpectedError + - a view to be rendered when an unexpected error occurs + - `
Error!
` NOTE: Currently, the `products` array only supports one element. @@ -48,4 +51,3 @@ Depending on the production environment we're in (dev, prod), the configuration - `BOTTEGA_URL` [dotenv](https://github.com/motdotla/dotenv) is used for setting the variables in place. - From e4df7b0a0e07a4c5df6fb7b9d23797ac426422dc Mon Sep 17 00:00:00 2001 From: amorcian Date: Fri, 15 May 2020 16:42:23 +0300 Subject: [PATCH 7/7] Bump vetrina version --- packages/vetrina/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vetrina/package.json b/packages/vetrina/package.json index 9a254a6f7..6bd80b4a8 100644 --- a/packages/vetrina/package.json +++ b/packages/vetrina/package.json @@ -1,6 +1,6 @@ { "name": "@ksf-media/vetrina", - "version": "1.0.4", + "version": "1.0.5", "description": "Vetrina, frontend for purchasing KSF Media products", "license": "MIT", "scripts": {