string_of_int}
onClick={_ => {
- setCurrentSelected(_ => requestId)
- setRequestObject(_ => requestObject)
- setResponseObject(_ => responseObject)
- setCurrentSelectedType(_ => logType)
+ setLogDetails(_ => {
+ response: responseObject,
+ request: requestObject,
+ })
+ setSelectedOption(_ => {
+ value: index,
+ optionType: logType,
+ })
}}>
-
-
{statusCode->React.string}
+
+
+
+ {statusCode->React.string}
+
+
{switch logType {
- | Sdk =>
{apiName->React.string}
- | Payment =>
-
- {method->String.toUpperCase->React.string}
- {apiPath->React.string}
+ | SDK =>
+
+ {apiName->camelCaseToTitle->React.string}
+
+ | PAYMENTS | WEBHOOKS | CONNECTOR =>
+
+
+ {method->String.toUpperCase->React.string}
+
+ {apiPath->React.string}
}}
-
+
{createdTime->Js.Date.fromString->Js.Date.toUTCString->React.string}
@@ -204,71 +265,97 @@ module ApiDetailsComponent = {
}
}
+
@react.component
let make = (~paymentId, ~createdAt) => {
+ open APIUtils
+ open LogicUtils
+ open PaymentLogsUtils
let fetchDetails = useGetMethod(~showErrorToast=false, ())
let fetchPostDetils = useUpdateMethod()
- let (paymentLogsData, setPaymentLogsData) = React.useState(_ => [])
- let (sdkLogsData, setSdkLogsData) = React.useState(_ => [])
- let (allLogsData, setAllLogsData) = React.useState(_ => [])
- let (responseObject, setResponseObject) = React.useState(_ => "")
- let (requestObject, setRequestObject) = React.useState(_ => "")
- let (currentSelected, setCurrentSelected) = React.useState(_ => "")
- let (currentSelectedType, setCurrentSelectedType) = React.useState(_ => Payment)
- let (screenState1, setScreenState1) = React.useState(_ => PageLoaderWrapper.Loading)
- let (screenState2, setScreenState2) = React.useState(_ => PageLoaderWrapper.Loading)
+ let logs = React.useMemo0(() => {ref([])})
+ let (logDetails, setLogDetails) = React.useState(_ => {
+ response: "",
+ request: "",
+ })
+ let (selectedOption, setSelectedOption) = React.useState(_ => {
+ value: 0,
+ optionType: PAYMENTS,
+ })
+ let (screenState, setScreenState) = React.useState(_ => PageLoaderWrapper.Loading)
let fetchPaymentLogsData = async _ => {
try {
- setScreenState1(_ => PageLoaderWrapper.Loading)
- let paymentLogsUrl = APIUtils.getURL(
+ let paymentLogsUrl = getURL(
~entityName=PAYMENT_LOGS,
~methodType=Get,
~id=Some(paymentId),
(),
)
let paymentLogsArray = (await fetchDetails(paymentLogsUrl))->getArrayFromJson([])
- setPaymentLogsData(_ => paymentLogsArray)
-
- // setting initial data
- let initialData =
- paymentLogsArray
- ->Belt.Array.get(0)
- ->Option.getWithDefault(Js.Json.null)
- ->getDictFromJsonObject
- let intialValueRequest = initialData->getString("request", "")
-
- let intialValueResponse = initialData->getString("response", "")
- setRequestObject(_ => intialValueRequest)
- setResponseObject(_ => intialValueResponse)
- setCurrentSelected(_ => initialData->getString("request_id", ""))
-
- setScreenState1(_ => PageLoaderWrapper.Success)
+ logs.contents = logs.contents->Array.concat(paymentLogsArray)
+
+ PageLoaderWrapper.Success
} catch {
| Js.Exn.Error(e) =>
let err = Js.Exn.message(e)->Option.getWithDefault("Failed to Fetch!")
- setScreenState1(_ => PageLoaderWrapper.Error(err))
+ PageLoaderWrapper.Error(err)
}
}
- let sourceMapper = source => {
- switch source {
- | "ORCA-LOADER" => "HYPERLOADER"
- | "ORCA-PAYMENT-PAGE"
- | "STRIPE_PAYMENT_SHEET" => "PAYMENT_SHEET"
- | other => other
+ let fetchWebhooksLogsData = async _ => {
+ try {
+ let webhooksLogsUrl = getURL(
+ ~entityName=WEBHOOKS_EVENT_LOGS,
+ ~methodType=Get,
+ ~id=Some(paymentId),
+ (),
+ )
+ let webhooksLogsArray = (await fetchDetails(webhooksLogsUrl))->getArrayFromJson([])
+ switch webhooksLogsArray->Array.get(0) {
+ | Some(val) => logs.contents = logs.contents->Array.concat([val])
+ | _ => ()
+ }
+
+ PageLoaderWrapper.Success
+ } catch {
+ | Js.Exn.Error(e) =>
+ let err = Js.Exn.message(e)->Option.getWithDefault("Failed to Fetch!")
+ PageLoaderWrapper.Error(err)
}
}
- let fetchSdkLogsData = async _ => {
+ let fetchConnectorLogsData = async _ => {
try {
- setScreenState2(_ => PageLoaderWrapper.Loading)
- let url = APIUtils.getURL(
- ~entityName=SDK_EVENT_LOGS,
- ~methodType=Post,
+ let connectorLogsUrl = getURL(
+ ~entityName=CONNECTOR_EVENT_LOGS,
+ ~methodType=Get,
~id=Some(paymentId),
(),
)
+ let connectorLogsArray = (await fetchDetails(connectorLogsUrl))->getArrayFromJson([])
+ logs.contents = logs.contents->Array.concat(connectorLogsArray)
+
+ PageLoaderWrapper.Success
+ } catch {
+ | Js.Exn.Error(e) =>
+ let err = Js.Exn.message(e)->Option.getWithDefault("Failed to Fetch!")
+ PageLoaderWrapper.Error(err)
+ }
+ }
+
+ let fetchSdkLogsData = async _ => {
+ let sourceMapper = source => {
+ switch source {
+ | "ORCA-LOADER" => "HYPERLOADER"
+ | "ORCA-PAYMENTS-PAGE"
+ | "STRIPE_PAYMENT_SHEET" => "PAYMENT_SHEET"
+ | other => other
+ }
+ }
+
+ try {
+ let url = getURL(~entityName=SDK_EVENT_LOGS, ~methodType=Post, ~id=Some(paymentId), ())
let startTime = createdAt->Js.Date.fromString->Js.Date.getTime -. 1000. *. 60. *. 5.
let startTime = startTime->Js.Date.fromFloat->Js.Date.toISOString
@@ -323,87 +410,180 @@ let make = (~paymentId, ~createdAt) => {
eventDict->Dict.set("created_at", timestamp->Js.Json.string)
eventDict->Js.Json.object_
})
- setSdkLogsData(_ =>
- sdkLogsArray->Array.filter(sdkLog => {
- let eventDict = sdkLog->getDictFromJsonObject
- let eventName = eventDict->getString("event_name", "")
- let filteredEventNames = ["StripeElementsCalled"]
- filteredEventNames->Array.includes(eventName)->not
- })
- )
-
- // setting initial data
- let initialData =
- sdkLogsArray->Belt.Array.get(0)->Option.getWithDefault(Js.Json.null)->getDictFromJsonObject
- let intialValueRequest = initialData->getString("event_name", "")
-
- let intialValueResponse = initialData->getString("response", "")
- setRequestObject(_ => intialValueRequest)
- setResponseObject(_ => intialValueResponse)
- setCurrentSelected(_ => initialData->getString("event_id", ""))
+ let logsArr = sdkLogsArray->Array.filter(sdkLog => {
+ let eventDict = sdkLog->getDictFromJsonObject
+ let eventName = eventDict->getString("event_name", "")
+ let filteredEventNames = ["StripeElementsCalled"]
+ filteredEventNames->Array.includes(eventName)->not
+ })
+ logs.contents = logs.contents->Array.concat(logsArr)
- setScreenState2(_ => PageLoaderWrapper.Success)
+ PageLoaderWrapper.Success
} catch {
| Js.Exn.Error(e) =>
let err = Js.Exn.message(e)->Option.getWithDefault("Failed to Fetch!")
- setScreenState2(_ => PageLoaderWrapper.Error(err))
+ PageLoaderWrapper.Error(err)
}
}
+
let getDetails = async () => {
- try {
- let _ = await Window.connectorWasmInit()
- if !(paymentId->HSwitchOrderUtils.isTestPayment) {
- fetchPaymentLogsData()->ignore
- fetchSdkLogsData()->ignore
- } else {
- setScreenState1(_ => PageLoaderWrapper.Success)
- setScreenState2(_ => PageLoaderWrapper.Success)
- }
- } catch {
- | Js.Exn.Error(e) => {
- let err = Js.Exn.message(e)->Option.getWithDefault("Something went wrong")
- setScreenState1(_ => PageLoaderWrapper.Error(err))
- setScreenState2(_ => PageLoaderWrapper.Error(err))
- }
- }
- }
+ if !(paymentId->HSwitchOrderUtils.isTestPayment) {
+ let apiLogsStatus = await fetchPaymentLogsData()
+ let sdkLogsStatus = await fetchSdkLogsData()
+ let webhooksStatus = await fetchWebhooksLogsData()
+ let connectorStatus = await fetchConnectorLogsData()
- let sortByCreatedAt = (log1: Js.Json.t, log2: Js.Json.t) => {
- let keyA = log1->getDictFromJsonObject->getString("created_at", "")->Js.Date.fromString
- let keyB = log2->getDictFromJsonObject->getString("created_at", "")->Js.Date.fromString
- if keyA < keyB {
- 1
- } else if keyA > keyB {
- -1
+ let screenState = switch (apiLogsStatus, sdkLogsStatus, webhooksStatus, connectorStatus) {
+ | (
+ PageLoaderWrapper.Error(_),
+ PageLoaderWrapper.Error(_),
+ PageLoaderWrapper.Error(_),
+ PageLoaderWrapper.Error(_),
+ ) =>
+ PageLoaderWrapper.Error("Failed to Fetch!")
+ | _ => PageLoaderWrapper.Success
+ }
+ setScreenState(_ => screenState)
} else {
- 0
+ setScreenState(_ => PageLoaderWrapper.Custom)
}
}
- let screenState = React.useMemo2(() => {
- setAllLogsData(_ =>
- sdkLogsData->Array.concat(paymentLogsData)->Js.Array2.sortInPlaceWith(sortByCreatedAt)
- )
- switch (screenState1, screenState2) {
- | (PageLoaderWrapper.Success, _)
- | (_, PageLoaderWrapper.Success) =>
- PageLoaderWrapper.Success
- | (PageLoaderWrapper.Loading, _)
- | (_, PageLoaderWrapper.Loading) =>
- PageLoaderWrapper.Loading
- | (PageLoaderWrapper.Error(err), PageLoaderWrapper.Error(_)) => PageLoaderWrapper.Error(err)
- | _ => PageLoaderWrapper.Loading
+ let screenState = React.useMemo1(() => {
+ logs.contents = logs.contents->Js.Array2.sortInPlaceWith(sortByCreatedAt)
+
+ switch logs.contents->Array.get(0) {
+ | Some(value) => {
+ let initialData = value->getDictFromJsonObject
+ switch initialData->getLogType {
+ | PAYMENTS => {
+ let request = initialData->getString("request", "")
+ let response = initialData->getString("response", "")
+ setLogDetails(_ => {
+ response,
+ request,
+ })
+ setSelectedOption(_ => {
+ value: 0,
+ optionType: PAYMENTS,
+ })
+ }
+ | SDK => {
+ let request =
+ initialData
+ ->Dict.toArray
+ ->Array.filter(entry => {
+ let (key, _) = entry
+ filteredKeys->Array.includes(key)->not
+ })
+ ->getJsonFromArrayOfJson
+ ->Js.Json.stringify
+ let response =
+ initialData->getString("log_type", "") === "ERROR"
+ ? initialData->getString("value", "")
+ : ""
+ setLogDetails(_ => {
+ response,
+ request,
+ })
+ setSelectedOption(_ => {
+ value: 0,
+ optionType: SDK,
+ })
+ }
+ | CONNECTOR => {
+ let request = initialData->getString("request", "")
+ let response = initialData->getString("response", "")
+ setLogDetails(_ => {
+ response,
+ request,
+ })
+ setSelectedOption(_ => {
+ value: 0,
+ optionType: CONNECTOR,
+ })
+ }
+ | WEBHOOKS => {
+ let request = initialData->getString("outgoing_webhook_event_type", "")
+ let response = initialData->getString("content", "")
+ setLogDetails(_ => {
+ response,
+ request,
+ })
+ setSelectedOption(_ => {
+ value: 0,
+ optionType: WEBHOOKS,
+ })
+ }
+ }
+ }
+ | _ => ()
}
- }, (screenState1, screenState2))
+
+ screenState
+ }, [screenState])
React.useEffect0(() => {
getDetails()->ignore
None
})
+ let headerText = switch selectedOption.optionType {
+ | PAYMENTS | CONNECTOR => "Response body"
+ | WEBHOOKS => "Request body"
+ | SDK => "Metadata"
+ }->Some
+
+ let timeLine =
+
+
+ {logs.contents
+ ->Array.mapWithIndex((paymentDetailsValue, index) => {
+
string_of_int}
+ paymentDetailsValue={paymentDetailsValue->getDictFromJsonObject}
+ setLogDetails
+ setSelectedOption
+ currentSelected=selectedOption.value
+ paymentId
+ index
+ logsDataLength={logs.contents->Array.length - 1}
+ />
+ })
+ ->React.array}
+
+
+
+ let requestHeader = switch selectedOption.optionType {
+ | PAYMENTS | CONNECTOR => "Request body"
+ | SDK => "Event"
+ | WEBHOOKS => ""
+ }
+
+ let codeBlock =
+
isNonEmptyString || logDetails.request->isNonEmptyString}>
+
+
isNonEmptyString &&
+ selectedOption.optionType !== WEBHOOKS}>
+ Some}
+ maxHeightClass={logDetails.response->String.length > 0 ? "max-h-25-rem" : ""}
+ />
+
+
isNonEmptyString}>
+
+
+
+
+
+ open OrderUtils
}>
- {if paymentId->HSwitchOrderUtils.isTestPayment {
+ {if paymentId->HSwitchOrderUtils.isTestPayment || logs.contents->Array.length === 0 {
@@ -413,49 +593,9 @@ let make = (~paymentId, ~createdAt) => {
} else {
-
-
- {"Audit Trail"->React.string}
-
-
- {allLogsData
- ->Array.mapWithIndex((paymentDetailsValue, index) => {
-
string_of_int}
- paymentDetailsValue={paymentDetailsValue->getDictFromJsonObject}
- setResponseObject
- setRequestObject
- currentSelected
- setCurrentSelected
- setCurrentSelectedType
- paymentId
- index
- logsDataLength={allLogsData->Array.length - 1}
- />
- })
- ->React.array}
-
-
- String.length > 0 || requestObject->String.length > 0}>
-
-
String.length > 0}>
- String.length > 0 ? "max-h-25-rem" : ""}
- />
-
-
String.length > 0}>
-
-
-
-
+ customCssClass={`bg-white dark:bg-jp-gray-lightgray_background rounded-md pt-2 pb-4 flex gap-7 justify-between h-48-rem !max-h-50-rem !min-w-[55rem] max-w-[72rem] overflow-scroll`}>
+ {timeLine}
+ {codeBlock}
}}
diff --git a/src/screens/HyperSwitch/PaymentLogs/PaymentLogsTypes.res b/src/screens/HyperSwitch/PaymentLogs/PaymentLogsTypes.res
new file mode 100644
index 000000000..433c8e72b
--- /dev/null
+++ b/src/screens/HyperSwitch/PaymentLogs/PaymentLogsTypes.res
@@ -0,0 +1,11 @@
+type logType = SDK | PAYMENTS | WEBHOOKS | CONNECTOR
+
+type logDetails = {
+ response: string,
+ request: string,
+}
+
+type selectedObj = {
+ value: int,
+ optionType: logType,
+}
diff --git a/src/screens/HyperSwitch/PaymentLogs/PaymentUtils.res b/src/screens/HyperSwitch/PaymentLogs/PaymentLogsUtils.res
similarity index 57%
rename from src/screens/HyperSwitch/PaymentLogs/PaymentUtils.res
rename to src/screens/HyperSwitch/PaymentLogs/PaymentLogsUtils.res
index c0b1be064..a5b5a3191 100644
--- a/src/screens/HyperSwitch/PaymentLogs/PaymentUtils.res
+++ b/src/screens/HyperSwitch/PaymentLogs/PaymentLogsUtils.res
@@ -10,3 +10,20 @@ let nameToURLMapper = (urlName, ~payment_id, ~merchant_id="", ()) => {
| _ => urlName
}
}
+
+let filteredKeys = [
+ "value",
+ "merchant_id",
+ "created_at_precise",
+ "component",
+ "platform",
+ "version",
+]
+
+let sortByCreatedAt = (log1: Js.Json.t, log2: Js.Json.t) => {
+ open LogicUtils
+ let getKey = dict => dict->getDictFromJsonObject->getString("created_at", "")->Js.Date.fromString
+ let keyA = log1->getKey
+ let keyB = log2->getKey
+ compareLogic(keyA, keyB)
+}
diff --git a/src/screens/HyperSwitch/SDKPayment/WebSDK.res b/src/screens/HyperSwitch/SDKPayment/WebSDK.res
index 1a40ef235..c9c4c0c3e 100644
--- a/src/screens/HyperSwitch/SDKPayment/WebSDK.res
+++ b/src/screens/HyperSwitch/SDKPayment/WebSDK.res
@@ -2,9 +2,6 @@ open HyperSwitch
open HyperSwitchTypes
open Promise
-@val external window: 'a = "window"
-@val @scope("window") external parent: 'a = "parent"
-
type configElements = {
appearanceElement: Js.Json.t,
paymentElement: Js.Json.t,
diff --git a/src/screens/HyperSwitch/Utils/HSSelfServeSidebar.res b/src/screens/HyperSwitch/Utils/HSSelfServeSidebar.res
index d1f2efd82..49c74a73f 100644
--- a/src/screens/HyperSwitch/Utils/HSSelfServeSidebar.res
+++ b/src/screens/HyperSwitch/Utils/HSSelfServeSidebar.res
@@ -1,6 +1,3 @@
-@val @scope(("window", "location"))
-external reload: unit => unit = "reload"
-
type status = COMPLETED | ONGOING | PENDING
type subOption = {
diff --git a/src/utils/LogicUtils.res b/src/utils/LogicUtils.res
index 617268ce6..7fbdc57a9 100644
--- a/src/utils/LogicUtils.res
+++ b/src/utils/LogicUtils.res
@@ -492,6 +492,8 @@ let isEmptyDict = dict => {
let isEmptyString = str => str->String.length === 0
+let isNonEmptyString = str => str->String.length > 0
+
let stringReplaceAll = (str, old, new) => {
str->String.split(old)->Array.joinWith(new)
}
@@ -587,8 +589,8 @@ let getJsonFromStr = data => {
external toExnJson: exn => Js.Json.t = "%identity"
let compareLogic = (firstValue, secondValue) => {
- let (temp1, _) = firstValue
- let (temp2, _) = secondValue
+ let temp1 = firstValue
+ let temp2 = secondValue
if temp1 == temp2 {
0
} else if temp1 > temp2 {
diff --git a/tailwindHyperSwitch.config.js b/tailwindHyperSwitch.config.js
index 3766ecf0b..b01ead6f6 100644
--- a/tailwindHyperSwitch.config.js
+++ b/tailwindHyperSwitch.config.js
@@ -413,6 +413,7 @@ module.exports = {
1000: "#A7A0A0",
failed_page_bg: "#FDEDE8",
},
+ "error-red": "#DA0E0F",
"status-green": "#36AF47",
"popover-background": "#334264",
"popover-background-hover": "#2E3B58",