From 806fc4043b111934709282b300bef644e661ca45 Mon Sep 17 00:00:00 2001 From: "arun.mishra" Date: Mon, 28 Aug 2023 17:52:10 +0530 Subject: [PATCH 1/3] error boundary component added --- src/Index.res | 4 +- src/PaymentElement.res | 91 ++++++++------- src/Payments/PaymentMethodsWrapper.res | 10 +- src/orca-log-catcher/ErrorBoundary.res | 155 ++++++++++++++++++++++++- 4 files changed, 212 insertions(+), 48 deletions(-) diff --git a/src/Index.res b/src/Index.res index 6d8601cc9..1a32a7066 100644 --- a/src/Index.res +++ b/src/Index.res @@ -9,7 +9,9 @@ let app = switch ReactDOM.querySelector("#app") { root->render(
- + + +
, ) diff --git a/src/PaymentElement.res b/src/PaymentElement.res index dfc18381b..44fdbaf1d 100644 --- a/src/PaymentElement.res +++ b/src/PaymentElement.res @@ -190,52 +190,57 @@ let make = ( } let checkoutEle = { - switch selectedOption->paymentMode { - | Card => - | Klarna => - - {switch tokenObj { - | OtherTokenOptional(optToken) => - switch optToken { - | Some(token) => - - - - | None => + + {switch selectedOption->paymentMode { + | Card => + | Klarna => + + {switch tokenObj { + | OtherTokenOptional(optToken) => + switch optToken { + | Some(token) => + + + + | None => + + + + } + | _ => - } - | _ => - - - - }} - - | ACHTransfer => - - - - | SepaTransfer => - - - - | BacsTransfer => - - - - | ACHBankDebit => - - | SepaBankDebit => - - | BacsBankDebit => - - | BanContactCard => - - | BecsBankDebit => - - | _ => - } + }} + + | ACHTransfer => + + + + | SepaTransfer => + + + + | BacsTransfer => + + + + | ACHBankDebit => + + | SepaBankDebit => + + | BacsBankDebit => + + | BanContactCard => + + | BecsBankDebit => + + | _ => + + + + }} + } <> { postFailedSubmitResponse(~errortype="validation_error", ~message="Please enter all fields") } } - }, (fullName, email, country, blikCode, props.paymentMethodName, phoneNumber.value, (selectedBank, currency))) + }, ( + fullName, + email, + country, + blikCode, + props.paymentMethodName, + phoneNumber.value, + (selectedBank, currency), + )) submitPaymentData(submitCallback) let bottomElement =
React.null +let errorIcon = { + + + + + + + + + + + + +} + +module ErrorCard = { + @react.component + let make = (~topLevel) => { + let (divH, setDivH) = React.useState(_ => 0.0) + let {themeObj} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom) + let (keys, _setKeys) = Recoil.useRecoilState(RecoilAtoms.keys) + let {iframeId} = keys + let divRef = React.useRef(Js.Nullable.null) + + let observer = ResizeObserver.newResizerObserver(entries => { + entries + ->Js.Array2.map(item => { + setDivH(_ => item.contentRect.height) + }) + ->ignore + }) + + switch divRef.current->Js.Nullable.toOption { + | Some(r) => observer.observe(. r) + | None => () + } + + React.useEffect2(() => { + if topLevel { + Utils.handlePostMessage([ + ("iframeHeight", (divH +. 1.0)->Js.Json.number), + ("iframeId", iframeId->Js.Json.string), + ]) + } + None + }, (divH, iframeId)) + + let message = topLevel ? "We'll be back with you shortly :)" : "Try another payment method ;)" +
ReactDOM.Ref.domRef} + style={ReactDOMStyle.make( + ~color=themeObj.colorPrimary, + ~backgroundColor=themeObj.colorBackground, + ~borderRadius=themeObj.borderRadius, + ~borderColor=themeObj.borderColor, + (), + )} + className="flex items-center"> +
+
{errorIcon}
+
+
{"Oops, something went wrong!"->React.string}
+
{message->React.string}
+
+
+
+ } +} +let defaultFallback = (_, topLevel) => @react.component -let make = (~children, ~renderFallback=defaultFallback) => { - children +let make = (~children, ~renderFallback=defaultFallback, ~topLevel=false) => { + renderFallback(e, topLevel)}> + children + } From 966d93b76d55a35a13d5efba242b7fa8034a7a62 Mon Sep 17 00:00:00 2001 From: "arun.mishra" Date: Mon, 28 Aug 2023 18:49:43 +0530 Subject: [PATCH 2/3] sending logs to grafana and handling for payment request button --- src/Index.res | 2 +- src/PaymentElement.res | 4 +- src/Payments/PaymentRequestButtonElement.res | 79 ++++----- src/orca-log-catcher/ErrorBoundary.res | 106 +++++++++--- src/orca-log-catcher/OrcaLogger.res | 165 ++++++++++--------- 5 files changed, 209 insertions(+), 147 deletions(-) diff --git a/src/Index.res b/src/Index.res index 1a32a7066..722e053ff 100644 --- a/src/Index.res +++ b/src/Index.res @@ -10,7 +10,7 @@ let app = switch ReactDOM.querySelector("#app") {
- +
, diff --git a/src/PaymentElement.res b/src/PaymentElement.res index 44fdbaf1d..cd73ea5fa 100644 --- a/src/PaymentElement.res +++ b/src/PaymentElement.res @@ -246,7 +246,9 @@ let make = ( Js.Array2.length > 0 || walletOptions->Js.Array2.length > 0}>
- + + + Js.Array2.length > 0 && walletOptions->Js.Array2.length > 0 && diff --git a/src/Payments/PaymentRequestButtonElement.res b/src/Payments/PaymentRequestButtonElement.res index b48922dd4..201760bd9 100644 --- a/src/Payments/PaymentRequestButtonElement.res +++ b/src/Payments/PaymentRequestButtonElement.res @@ -33,46 +33,49 @@ let make = (~sessions, ~walletOptions, ~list: PaymentMethodsRecord.list) => {
{walletOptions ->Js.Array2.mapi((item, i) => { - } key={i->Belt.Int.toString}> - {switch clientSecret { - | Some(_) => - switch item->paymentMode { - | GPayWallet => - - {switch gPayToken { - | OtherTokenOptional(optToken) => - switch googlePayThirdPartyToken { - | GooglePayThirdPartyTokenOptional(googlePayThirdPartyOptToken) => - - | _ => - } + Belt.Int.toString}-request-button`}> + } key={i->Belt.Int.toString}> + {switch clientSecret { + | Some(_) => + switch item->paymentMode { + | GPayWallet => + + {switch gPayToken { + | OtherTokenOptional(optToken) => + switch googlePayThirdPartyToken { + | GooglePayThirdPartyTokenOptional(googlePayThirdPartyOptToken) => + + | _ => + } + | _ => React.null + }} + + | PaypalWallet => + + {switch paypalToken { + | OtherTokenOptional(optToken) => + switch optToken { + | Some(token) => + | None => + } + | _ => + }} + + | ApplePayWallet => + switch applePayToken { + | ApplePayTokenOptional(optToken) => | _ => React.null - }} - - | PaypalWallet => - - {switch paypalToken { - | OtherTokenOptional(optToken) => - switch optToken { - | Some(token) => - | None => - } - | _ => - }} - - | ApplePayWallet => - switch applePayToken { - | ApplePayTokenOptional(optToken) => - | _ => React.null - } + } - | NONE => React.null - } - | None => React.null - }} - + | NONE => React.null + } + | None => React.null + }} + + }) ->React.array}
diff --git a/src/orca-log-catcher/ErrorBoundary.res b/src/orca-log-catcher/ErrorBoundary.res index 53be06ec0..9735a67b5 100644 --- a/src/orca-log-catcher/ErrorBoundary.res +++ b/src/orca-log-catcher/ErrorBoundary.res @@ -1,3 +1,6 @@ +external errorToJson: Sentry.ErrorBoundary.fallbackArg => Js.Json.t = "%identity" +type errorLevel = Top | RequestButton | PaymentMethod + let errorIcon = { @@ -92,7 +95,49 @@ let errorIcon = { module ErrorCard = { @react.component - let make = (~topLevel) => { + let make = (~error: Sentry.ErrorBoundary.fallbackArg, ~level) => { + let beaconApiCall = data => { + if data->Js.Array2.length > 0 { + let logData = + [("data", data->Js.Array2.map(OrcaLogger.logFileToObj)->Js.Json.array)] + ->Js.Dict.fromArray + ->Js.Json.object_ + ->Js.Json.stringify + let logEndpoint = "https://api.hyperswitch.io/sdk-logs" + GlobalVars.sendBeacon(logEndpoint, logData) + } + } + + React.useEffect0(() => { + let errorLog: OrcaLogger.logFile = { + logType: ERROR, + timestamp: Js.Date.now()->Belt.Float.toString, + sessionId: "", + source: "orca-elements", + version: GlobalVars.repoVersion, + component: "payment", + value: error->errorToJson->Js.Json.stringify, + category: USER_ERROR, + paymentId: "", + merchantId: "", + browserName: OrcaLogger.arrayOfNameAndVersion + ->Belt.Array.get(0) + ->Belt.Option.getWithDefault("Others"), + browserVersion: OrcaLogger.arrayOfNameAndVersion + ->Belt.Array.get(1) + ->Belt.Option.getWithDefault("0"), + platform: GlobalVars.platform, + userAgent: GlobalVars.userAgent, + appId: "", + eventName: "SDK_CRASH", + latency: "", + paymentMethod: "", + firstEvent: false, + } + beaconApiCall([errorLog]) + None + }) + let (divH, setDivH) = React.useState(_ => 0.0) let {themeObj} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom) let (keys, _setKeys) = Recoil.useRecoilState(RecoilAtoms.keys) @@ -113,43 +158,52 @@ module ErrorCard = { } React.useEffect2(() => { - if topLevel { + switch level { + | Top => Utils.handlePostMessage([ ("iframeHeight", (divH +. 1.0)->Js.Json.number), ("iframeId", iframeId->Js.Json.string), ]) + | _ => () } None }, (divH, iframeId)) - let message = topLevel ? "We'll be back with you shortly :)" : "Try another payment method ;)" -
ReactDOM.Ref.domRef} - style={ReactDOMStyle.make( - ~color=themeObj.colorPrimary, - ~backgroundColor=themeObj.colorBackground, - ~borderRadius=themeObj.borderRadius, - ~borderColor=themeObj.borderColor, - (), - )} - className="flex items-center"> -
-
{errorIcon}
-
-
{"Oops, something went wrong!"->React.string}
-
{message->React.string}
+ let message = switch level { + | Top => "We'll be back with you shortly :)" + | _ => "Try another payment method ;)" + } + switch level { + | RequestButton => React.null + | _ => +
ReactDOM.Ref.domRef} + style={ReactDOMStyle.make( + ~color=themeObj.colorPrimary, + ~backgroundColor=themeObj.colorBackground, + ~borderRadius=themeObj.borderRadius, + ~borderColor=themeObj.borderColor, + (), + )} + className="flex items-center"> +
+
{errorIcon}
+
+
{"Oops, something went wrong!"->React.string}
+
{message->React.string}
+
-
+ } } } -let defaultFallback = (_, topLevel) => +let defaultFallback = (e, level) => { + +} @react.component -let make = (~children, ~renderFallback=defaultFallback, ~topLevel=false) => { - renderFallback(e, topLevel)}> - children - +let make = (~children, ~renderFallback=defaultFallback, ~level=PaymentMethod) => { + renderFallback(e, level)}> children } diff --git a/src/orca-log-catcher/OrcaLogger.res b/src/orca-log-catcher/OrcaLogger.res index 3d9fa3b18..222d9f907 100644 --- a/src/orca-log-catcher/OrcaLogger.res +++ b/src/orca-log-catcher/OrcaLogger.res @@ -46,6 +46,7 @@ type eventName = | PAYMENT_RESPONSE | CONFIRM_PAYMENT | CONFIRM_CARD_PAYMENT + | SDK_CRASH | Others(string) let eventNameToStrMapper = eventName => { @@ -79,6 +80,7 @@ let eventNameToStrMapper = eventName => { | PAYMENT_RESPONSE => "PAYMENT_RESPONSE" | CONFIRM_PAYMENT => "CONFIRM_PAYMENT" | CONFIRM_CARD_PAYMENT => "CONFIRM_CARD_PAYMENT" + | SDK_CRASH => "SDK_CRASH" | Others(string) => string } } @@ -290,6 +292,88 @@ let getSourceString = source => { } } +let findVersion = (re, content) => { + let result = Js.Re.exec_(re, content) + let version = switch result { + | Some(val) => Js.Re.captures(val) + | None => [] + } + version +} + +let browserDetect = content => { + if Js.Re.test_("Edg"->Js.Re.fromString, content) { + let re = %re("/Edg\/([\d]+\.[\w]?\.?[\w]+)/ig") + let version = switch findVersion(re, content) + ->Belt.Array.get(1) + ->Belt.Option.getWithDefault(Js.Nullable.null) + ->Js.Nullable.toOption { + | Some(a) => a + | None => "" + } + `Microsoft Edge-${version}` + } else if Js.Re.test_("Chrome"->Js.Re.fromString, content) { + let re = %re("/Chrome\/([\d]+\.[\w]?\.?[\w]+)/ig") + let version = switch findVersion(re, content) + ->Belt.Array.get(1) + ->Belt.Option.getWithDefault(Js.Nullable.null) + ->Js.Nullable.toOption { + | Some(a) => a + | None => "" + } + `Chrome-${version}` + } else if Js.Re.test_("Safari"->Js.Re.fromString, content) { + let re = %re("/Safari\/([\d]+\.[\w]?\.?[\w]+)/ig") + let version = switch findVersion(re, content) + ->Belt.Array.get(1) + ->Belt.Option.getWithDefault(Js.Nullable.null) + ->Js.Nullable.toOption { + | Some(a) => a + | None => "" + } + `Safari-${version}` + } else if Js.Re.test_("opera"->Js.Re.fromString, content) { + let re = %re("/Opera\/([\d]+\.[\w]?\.?[\w]+)/ig") + let version = switch findVersion(re, content) + ->Belt.Array.get(1) + ->Belt.Option.getWithDefault(Js.Nullable.null) + ->Js.Nullable.toOption { + | Some(a) => a + | None => "" + } + `Opera-${version}` + } else if ( + Js.Re.test_("Firefox"->Js.Re.fromString, content) || + Js.Re.test_("fxios"->Js.Re.fromString, content) + ) { + if Js.Re.test_("Firefox"->Js.Re.fromString, content) { + let re = %re("/Firefox\/([\d]+\.[\w]?\.?[\w]+)/ig") + let version = switch findVersion(re, content) + ->Belt.Array.get(1) + ->Belt.Option.getWithDefault(Js.Nullable.null) + ->Js.Nullable.toOption { + | Some(a) => a + | None => "" + } + `Firefox-${version}` + } else { + let re = %re("/fxios\/([\d]+\.[\w]?\.?[\w]+)/ig") + let version = switch findVersion(re, content) + ->Belt.Array.get(1) + ->Belt.Option.getWithDefault(Js.Nullable.null) + ->Js.Nullable.toOption { + | Some(a) => a + | None => "" + } + `Firefox-${version}` + } + } else { + "Others-0" + } +} + +let arrayOfNameAndVersion = Js.String2.split(GlobalVars.userAgent->browserDetect, "-") + let make = ( ~component, ~sessionId=?, @@ -337,87 +421,6 @@ let make = ( let events = ref(Js.Dict.empty()) - let findVersion = (re, content) => { - let result = Js.Re.exec_(re, content) - let version = switch result { - | Some(val) => Js.Re.captures(val) - | None => [] - } - version - } - - let browserDetect = content => { - if Js.Re.test_("Edg"->Js.Re.fromString, content) { - let re = %re("/Edg\/([\d]+\.[\w]?\.?[\w]+)/ig") - let version = switch findVersion(re, content) - ->Belt.Array.get(1) - ->Belt.Option.getWithDefault(Js.Nullable.null) - ->Js.Nullable.toOption { - | Some(a) => a - | None => "" - } - `Microsoft Edge-${version}` - } else if Js.Re.test_("Chrome"->Js.Re.fromString, content) { - let re = %re("/Chrome\/([\d]+\.[\w]?\.?[\w]+)/ig") - let version = switch findVersion(re, content) - ->Belt.Array.get(1) - ->Belt.Option.getWithDefault(Js.Nullable.null) - ->Js.Nullable.toOption { - | Some(a) => a - | None => "" - } - `Chrome-${version}` - } else if Js.Re.test_("Safari"->Js.Re.fromString, content) { - let re = %re("/Safari\/([\d]+\.[\w]?\.?[\w]+)/ig") - let version = switch findVersion(re, content) - ->Belt.Array.get(1) - ->Belt.Option.getWithDefault(Js.Nullable.null) - ->Js.Nullable.toOption { - | Some(a) => a - | None => "" - } - `Safari-${version}` - } else if Js.Re.test_("opera"->Js.Re.fromString, content) { - let re = %re("/Opera\/([\d]+\.[\w]?\.?[\w]+)/ig") - let version = switch findVersion(re, content) - ->Belt.Array.get(1) - ->Belt.Option.getWithDefault(Js.Nullable.null) - ->Js.Nullable.toOption { - | Some(a) => a - | None => "" - } - `Opera-${version}` - } else if ( - Js.Re.test_("Firefox"->Js.Re.fromString, content) || - Js.Re.test_("fxios"->Js.Re.fromString, content) - ) { - if Js.Re.test_("Firefox"->Js.Re.fromString, content) { - let re = %re("/Firefox\/([\d]+\.[\w]?\.?[\w]+)/ig") - let version = switch findVersion(re, content) - ->Belt.Array.get(1) - ->Belt.Option.getWithDefault(Js.Nullable.null) - ->Js.Nullable.toOption { - | Some(a) => a - | None => "" - } - `Firefox-${version}` - } else { - let re = %re("/fxios\/([\d]+\.[\w]?\.?[\w]+)/ig") - let version = switch findVersion(re, content) - ->Belt.Array.get(1) - ->Belt.Option.getWithDefault(Js.Nullable.null) - ->Js.Nullable.toOption { - | Some(a) => a - | None => "" - } - `Firefox-${version}` - } - } else { - "Others-0" - } - } - - let arrayOfNameAndVersion = Js.String2.split(GlobalVars.userAgent->browserDetect, "-") let rec sendLogs = () => { switch timeOut.contents { | Some(val) => { From 95f45d53bb3bf94f35b31ce8d3eaaea181fef970 Mon Sep 17 00:00:00 2001 From: "arun.mishra" Date: Wed, 30 Aug 2023 16:33:38 +0530 Subject: [PATCH 3/3] emoji change --- src/orca-log-catcher/ErrorBoundary.res | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orca-log-catcher/ErrorBoundary.res b/src/orca-log-catcher/ErrorBoundary.res index 9735a67b5..68af4910a 100644 --- a/src/orca-log-catcher/ErrorBoundary.res +++ b/src/orca-log-catcher/ErrorBoundary.res @@ -171,7 +171,7 @@ module ErrorCard = { let message = switch level { | Top => "We'll be back with you shortly :)" - | _ => "Try another payment method ;)" + | _ => "Try another payment method :)" } switch level { | RequestButton => React.null