diff --git a/CHANGELOG.md b/CHANGELOG.md index 014233db3..9fdb4c62c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. See [conven - - - +## 2024.10.08.1 + +### Features + +- Tooltip fix and enhancement ([#1571](https://github.com/juspay/hyperswitch-control-center/pull/1571)) ([`0cda40b`](https://github.com/juspay/hyperswitch-control-center/commit/0cda40b243acab3bbbcfa0f8488389c642e67785)) +- Failed payment distribution graph ([#1528](https://github.com/juspay/hyperswitch-control-center/pull/1528)) ([`470b582`](https://github.com/juspay/hyperswitch-control-center/commit/470b582b5da77abb9a00a42948451d00942be62c)) +- Graphs legends display ([#1574](https://github.com/juspay/hyperswitch-control-center/pull/1574)) ([`233b192`](https://github.com/juspay/hyperswitch-control-center/commit/233b1922ada5018ee92847fc5b859d63d5246d03)) + +### Bug Fixes + +- Selected item displays on top of list ([#1560](https://github.com/juspay/hyperswitch-control-center/pull/1560)) ([`5e36d6f`](https://github.com/juspay/hyperswitch-control-center/commit/5e36d6fac432d33e57313d4f058925a8b414665e)) +- UI connector preview ([#1538](https://github.com/juspay/hyperswitch-control-center/pull/1538)) ([`d32e536`](https://github.com/juspay/hyperswitch-control-center/commit/d32e5366d751505afb1264ea4ad3724cf9ffd808)) +- Update status of connector ( Disable / Enable ) ([#1575](https://github.com/juspay/hyperswitch-control-center/pull/1575)) ([`b5c14dd`](https://github.com/juspay/hyperswitch-control-center/commit/b5c14ddc588b2fa1939591b7bcccc43f7ff883a2)) + +**Full Changelog:** [`2024.10.08.0...2024.10.08.1`](https://github.com/juspay/hyperswitch-control-center/compare/2024.10.08.0...2024.10.08.1) + +- - - + ## 2024.10.08.0 ### Features diff --git a/src/components/SelectBox.res b/src/components/SelectBox.res index 707983493..6bf6ba731 100644 --- a/src/components/SelectBox.res +++ b/src/components/SelectBox.res @@ -1105,6 +1105,20 @@ module RenderListItemInBaseRadio = { ~selectClass="", ~customScrollStyle=?, ) => { + let decodedValue = value->JSON.Decode.string + switch decodedValue { + | Some(str) => + newOptions->Array.sort((item1, item2) => { + if item1.value == str { + -1. + } else if item2.value == str { + 1. + } else { + 0. + } + }) + | None => () + } let dropdownList = newOptions ->Array.mapWithIndex((option, i) => { diff --git a/src/container/AnalyticsContainser.res b/src/container/AnalyticsContainer.res similarity index 100% rename from src/container/AnalyticsContainser.res rename to src/container/AnalyticsContainer.res diff --git a/src/entryPoints/HyperSwitchApp.res b/src/entryPoints/HyperSwitchApp.res index 611faad4f..61bbcdc8c 100644 --- a/src/entryPoints/HyperSwitchApp.res +++ b/src/entryPoints/HyperSwitchApp.res @@ -188,7 +188,7 @@ let make = () => { | list{"performance-monitor"} | list{"analytics-refunds"} | list{"analytics-disputes"} => - + | list{"new-analytics-payment"} => { if uri->String.includes("lottie-files") || uri->String.includes("config/merchant-access") { headers->Dict.set("Content-Type", `application/json`) } else { - headers->Dict.set("x-feature", "router-custom") + headers->Dict.set("x-feature", "integ-custom") } } diff --git a/src/screens/Connectors/ConnectPayPalFlow/MenuOptionForPayPal.res b/src/screens/Connectors/ConnectPayPalFlow/MenuOptionForPayPal.res index 473d29933..a5db78724 100644 --- a/src/screens/Connectors/ConnectPayPalFlow/MenuOptionForPayPal.res +++ b/src/screens/Connectors/ConnectPayPalFlow/MenuOptionForPayPal.res @@ -85,7 +85,15 @@ let make = ( handleCancel: {text: "Cancel"}, }) } - + let authType = switch connectorInfo.connector_account_details { + | HeaderKey(authKeys) => authKeys.auth_type + | BodyKey(bodyKey) => bodyKey.auth_type + | SignatureKey(signatureKey) => signatureKey.auth_type + | MultiAuthKey(multiAuthKey) => multiAuthKey.auth_type + | CertificateAuth(certificateAuth) => certificateAuth.auth_type + | CurrencyAuthKey(currencyAuthKey) => currencyAuthKey.auth_type + | UnKnownAuthType(_) => "" + } {_popoverProps => <> {_ => } @@ -95,9 +103,7 @@ let make = ( id="neglectTopbarTheme" className="relative flex flex-col bg-white py-3 overflow-hidden rounded ring-1 ring-black ring-opacity-5 w-max"> {<> - ConnectorUtils.mapAuthType === - #SignatureKey}> + ConnectorUtils.mapAuthType === #SignatureKey}> { @@ -113,9 +119,7 @@ let make = ( setSetupAccountStatus(_ => PayPalFlowTypes.Connect_paypal_landing) }} /> - ConnectorUtils.mapAuthType === - #BodyKey}> + ConnectorUtils.mapAuthType === #BodyKey}> { @@ -124,9 +128,7 @@ let make = ( }} /> - ConnectorUtils.mapAuthType === - #SignatureKey}> + ConnectorUtils.mapAuthType === #SignatureKey}> { diff --git a/src/screens/Connectors/ConnectorHome.res b/src/screens/Connectors/ConnectorHome.res index 982d5a088..2440c07f0 100644 --- a/src/screens/Connectors/ConnectorHome.res +++ b/src/screens/Connectors/ConnectorHome.res @@ -266,7 +266,6 @@ let make = (~isPayoutFlow=false, ~showStepIndicator=true, ~showBreadCrumb=true) currentStep setCurrentStep isUpdateFlow - isPayoutFlow setInitialValues getPayPalStatus getConnectorDetails={Some(getConnectorDetails)} diff --git a/src/screens/Connectors/ConnectorPreview.res b/src/screens/Connectors/ConnectorPreview.res index 37d9b2fba..95ec1e831 100644 --- a/src/screens/Connectors/ConnectorPreview.res +++ b/src/screens/Connectors/ConnectorPreview.res @@ -21,7 +21,7 @@ module KeyAndCopyArea = { {copyValue->React.string}

{ Clipboard.writeText(copyValue) showToast(~message="Copied to Clipboard!", ~toastType=ToastSuccess) @@ -127,8 +127,6 @@ module ConnectorSummaryGrid = { let make = ( ~connectorInfo: ConnectorTypes.connectorPayload, ~connector, - ~isPayoutFlow, - ~setScreenState, ~setCurrentStep, ~updateStepValue=None, ~getConnectorDetails=None, @@ -148,26 +146,32 @@ module ConnectorSummaryGrid = { ~connectorName={connectorInfo.merchant_connector_id}, ~merchantId, ) + let (processorType, _) = connectorInfo.connector_type->ConnectorUtils.connectorTypeTuple + let {connector_name: connectorName} = connectorInfo + let connectorDetails = React.useMemo(() => { try { - if connector->LogicUtils.isNonEmptyString { - let dict = isPayoutFlow - ? Window.getPayoutConnectorConfig(connector) - : Window.getConnectorConfig(connector) - + if connectorName->LogicUtils.isNonEmptyString { + let dict = switch processorType { + | PaymentProcessor => Window.getConnectorConfig(connectorName) + | PayoutProcessor => Window.getPayoutConnectorConfig(connectorName) + | AuthenticationProcessor => Window.getAuthenticationConnectorConfig(connectorName) + | PMAuthProcessor => Window.getPMAuthenticationProcessorConfig(connectorName) + | TaxProcessor => Window.getTaxProcessorConfig(connectorName) + | PaymentVas => JSON.Encode.null + } dict } else { - Dict.make()->JSON.Encode.object + JSON.Encode.null } } catch { | Exn.Error(e) => { Js.log2("FAILED TO LOAD CONNECTOR CONFIG", e) - let err = Exn.message(e)->Option.getOr("Something went wrong") - setScreenState(_ => PageLoaderWrapper.Error(err)) - Dict.make()->JSON.Encode.object + let _ = Exn.message(e)->Option.getOr("Something went wrong") + JSON.Encode.null } } - }, [connector]) + }, [connectorInfo.merchant_connector_id]) let (_, connectorAccountFields, _, _, _, _, _) = ConnectorUtils.getConnectorFields( connectorDetails, ) @@ -176,8 +180,8 @@ module ConnectorSummaryGrid = { | _ => true } -
-
+ <> +

{"Integration status"->React.string}

String.toLowerCase)]>
-
+

{"Webhook Endpoint"->React.string}

-
+

{"Profile"->React.string}

{`${currentProfileName.profile_name} - ${connectorInfo.profile_id}`->React.string}
-
+
-

{"API Keys"->React.string}

+

{"Creds"->React.string}

-
+
- {connectorAccountFields - ->Dict.keysToArray - ->Array.mapWithIndex((field, index) => { - open LogicUtils - let label = connectorAccountFields->getString(field, "") - Int.toString} - label={label} - render={connectorInfo->ConnectorUtils.getConnectorDetailsValue(field)} - /> - }) - ->React.array} +
@@ -236,7 +229,7 @@ module ConnectorSummaryGrid = {
{switch updateStepValue { | Some(state) => -
+

{"PMTs"->React.string}

@@ -302,7 +295,7 @@ module ConnectorSummaryGrid = { | None => React.null }} -
+ } } @@ -312,7 +305,6 @@ let make = ( ~currentStep: ConnectorTypes.steps, ~setCurrentStep, ~isUpdateFlow, - ~isPayoutFlow, ~showMenuOption=true, ~setInitialValues, ~getPayPalStatus, @@ -327,6 +319,7 @@ let make = ( let updateDetails = useUpdateMethod() let showToast = ToastState.useShowToast() let mixpanelEvent = MixpanelHook.useSendEvent() + let fetchConnectorListResponse = ConnectorListHook.useFetchConnectorList() let connector = UrlUtils.useGetFilterDictFromUrl("")->LogicUtils.getString("name", "") let {setShowFeedbackModal} = React.useContext(GlobalProvider.defaultContext) let (screenState, setScreenState) = React.useState(_ => PageLoaderWrapper.Success) @@ -354,9 +347,10 @@ let make = ( isConnectorDisabled, ) let url = getURL(~entityName=CONNECTOR, ~methodType=Post, ~id=Some(connectorID)) - let _ = await updateDetails(url, disableConnectorPayload->JSON.Encode.object, Post) + let res = await updateDetails(url, disableConnectorPayload->JSON.Encode.object, Post) + fetchConnectorListResponse()->ignore + setInitialValues(_ => res) showToast(~message=`Successfully Saved the Changes`, ~toastType=ToastSuccess) - RescriptReactRouter.push(GlobalVars.appendDashboardPath(~url=redirectPath)) } catch { | Exn.Error(_) => showToast(~message=`Failed to Disable connector!`, ~toastType=ToastError) } @@ -432,8 +426,6 @@ let make = ( { +
+

{label->React.string}

+

{str->React.string}

+
+ } +} + +module CredsInfoField = { + @react.component + let make = (~authKeys, ~connectorAccountFields) => { + open LogicUtils + let dict = authKeys->Identity.genericTypeToDictOfJson + dict + ->Dict.keysToArray + ->Array.filter(ele => ele !== "auth_type") + ->Array.map(field => { + let value = dict->getString(field, "") + let label = connectorAccountFields->getString(field, "") + + }) + ->React.array + } +} + +module CashtoCodeCredsInfo = { + @react.component + let make = (~authKeys: ConnectorTypes.currencyAuthKey) => { + open LogicUtils + let dict = authKeys.auth_key_map->Identity.genericTypeToDictOfJson + dict + ->Dict.keysToArray + ->Array.map(ele => { + let data = dict->getDictfromDict(ele) + let keys = data->Dict.keysToArray + + { + <> + + {keys + ->Array.map(ele => { + let value = data->getString(ele, "") + snakeToTitle} str=value /> + }) + ->React.array} + + } + }) + ->React.array + } +} + +module PreviewCreds = { + @react.component + let make = (~connectorAccountFields, ~connectorInfo: ConnectorTypes.connectorPayload) => { + switch connectorInfo.connector_account_details { + | HeaderKey(authKeys) => + | BodyKey(bodyKey) => + | SignatureKey(signatureKey) => + | MultiAuthKey(multiAuthKey) => + | CertificateAuth(certificateAuth) => + + | CurrencyAuthKey(currencyAuthKey) => + | UnKnownAuthType(_) => React.null + } + } +} diff --git a/src/screens/Connectors/ConnectorTypes.res b/src/screens/Connectors/ConnectorTypes.res index 6d39546b4..ca56e3ae9 100644 --- a/src/screens/Connectors/ConnectorTypes.res +++ b/src/screens/Connectors/ConnectorTypes.res @@ -214,6 +214,56 @@ type wasmExtraPayload = { // This type are used for FRM configuration which need to moved to wasm +type headerKey = {auth_type: string, api_key: string} +type bodyKey = { + auth_type: string, + api_key: string, + key1: string, +} +type signatureKey = { + auth_type: string, + api_key: string, + key1: string, + api_secret: string, +} +type multiAuthKey = { + auth_type: string, + api_key: string, + key1: string, + api_secret: string, + key2: string, +} +type currencyKey = { + auth_type: string, + merchant_id_classic: string, + password_classic: string, + username_classic: string, +} +type currencyAuthKey = {auth_key_map: Js.Dict.t, auth_type: string} +type certificateAuth = { + auth_type: string, + certificate: string, + private_key: string, +} + +type connectorAuthType = + | HeaderKey + | BodyKey + | SignatureKey + | MultiAuthKey + | CurrencyAuthKey + | CertificateAuth + | UnKnownAuthType + +type connectorAuthTypeObj = + | HeaderKey(headerKey) + | BodyKey(bodyKey) + | SignatureKey(signatureKey) + | MultiAuthKey(multiAuthKey) + | CurrencyAuthKey(currencyAuthKey) + | CertificateAuth(certificateAuth) + | UnKnownAuthType(JSON.t) + type connectorAccountDetails = { auth_type: string, api_secret?: string, @@ -250,7 +300,7 @@ type connectorPayload = { connector_type: string, connector_name: string, connector_label: string, - connector_account_details: connectorAccountDetails, + connector_account_details: connectorAuthTypeObj, test_mode: bool, disabled: bool, payment_methods_enabled: payment_methods_enabled, diff --git a/src/screens/Connectors/ConnectorUpdateAuthCreds.res b/src/screens/Connectors/ConnectorUpdateAuthCreds.res index 47d7ec823..d3e0828a9 100644 --- a/src/screens/Connectors/ConnectorUpdateAuthCreds.res +++ b/src/screens/Connectors/ConnectorUpdateAuthCreds.res @@ -37,7 +37,7 @@ let make = (~connectorInfo: ConnectorTypes.connectorPayload, ~getConnectorDetail JSON.Encode.null } } - }, [connectorName]) + }, [connectorInfo.merchant_connector_id]) let ( _, connectorAccountFields, @@ -49,11 +49,20 @@ let make = (~connectorInfo: ConnectorTypes.connectorPayload, ~getConnectorDetail ) = getConnectorFields(connectorDetails) let initialValues = React.useMemo(() => { + let authType = switch connectorInfo.connector_account_details { + | HeaderKey(authKeys) => authKeys.auth_type + | BodyKey(bodyKey) => bodyKey.auth_type + | SignatureKey(signatureKey) => signatureKey.auth_type + | MultiAuthKey(multiAuthKey) => multiAuthKey.auth_type + | CertificateAuth(certificateAuth) => certificateAuth.auth_type + | CurrencyAuthKey(currencyAuthKey) => currencyAuthKey.auth_type + | UnKnownAuthType(_) => "" + } [ ("connector_type", connectorInfo.connector_type->JSON.Encode.string), ( "connector_account_details", - [("auth_type", connectorInfo.connector_account_details.auth_type->JSON.Encode.string)] + [("auth_type", authType->JSON.Encode.string)] ->Dict.fromArray ->JSON.Encode.object, ), diff --git a/src/screens/Connectors/ConnectorUtils.res b/src/screens/Connectors/ConnectorUtils.res index 18deeb04b..fb66b51f4 100644 --- a/src/screens/Connectors/ConnectorUtils.res +++ b/src/screens/Connectors/ConnectorUtils.res @@ -1248,16 +1248,6 @@ let getPlaceHolder = label => { `Enter ${label->LogicUtils.snakeToTitle}` } -let getConnectorDetailsValue = (connectorInfo: connectorPayload, str) => { - switch str { - | "api_key" => connectorInfo.connector_account_details.api_key - | "api_secret" => connectorInfo.connector_account_details.api_secret - | "key1" => connectorInfo.connector_account_details.key1 - | "key2" => connectorInfo.connector_account_details.key2 - | "auth_type" => Some(connectorInfo.connector_account_details.auth_type) - | _ => Some("") - } -} let connectorLabelDetailField = Dict.fromArray([ ("connector_label", "Connector label"->JSON.Encode.string), ]) diff --git a/src/screens/NewAnalytics/Graphs/LineGraph/LineGraphTypes.res b/src/screens/NewAnalytics/Graphs/LineGraph/LineGraphTypes.res index 483c8915b..6c578fb19 100644 --- a/src/screens/NewAnalytics/Graphs/LineGraph/LineGraphTypes.res +++ b/src/screens/NewAnalytics/Graphs/LineGraph/LineGraphTypes.res @@ -2,7 +2,8 @@ type \"type" = string type spacingLeft = int type spacingRight = int -type point = {color: string, x: string, y: float} +type info = {index: int} +type point = {color: string, x: string, y: float, point: info} type pointFormatter = {points: array} external asTooltipPointFormatter: Js_OO.Callback.arity1<'a> => pointFormatter => string = @@ -73,6 +74,7 @@ type xAxis = { lineWidth: lineWidth, tickWidth: tickWidth, labels: labels, + tickInterval: int, gridLineWidth: gridLineWidth, gridLineColor: gridLineColor, tickmarkPlacement: tickmarkPlacement, @@ -109,4 +111,9 @@ type lineGraphOptions = { tooltip: tooltip, } -type lineGraphPayload = {categories: categories, data: data, title: title} +type lineGraphPayload = { + categories: categories, + data: data, + title: title, + tooltipFormatter: pointFormatter => string, +} diff --git a/src/screens/NewAnalytics/Graphs/LineGraph/LineGraphUtils.res b/src/screens/NewAnalytics/Graphs/LineGraph/LineGraphUtils.res index f0beec7da..08103d41f 100644 --- a/src/screens/NewAnalytics/Graphs/LineGraph/LineGraphUtils.res +++ b/src/screens/NewAnalytics/Graphs/LineGraph/LineGraphUtils.res @@ -1,55 +1,13 @@ open LineGraphTypes -let tooltipFormatter = (~title: LineGraphTypes.title) => - ( - @this - (this: pointFormatter) => { - let title = `
${title.text}
` - let tableItems = - this.points - ->Array.map(point => - `
-
-
${point.x}
-
${point.y->Float.toString} USD
-
` - ) - ->Array.joinWith("") - - let content = ` -
- ${title} -
- ${tableItems} -
-
` +let getLineGraphOptions = (lineGraphOptions: lineGraphPayload) => { + let {categories, data, title, tooltipFormatter} = lineGraphOptions - `
- ${content} -
` - } - )->asTooltipPointFormatter + let stepInterval = Js.Math.max_int( + Js.Math.ceil_int(categories->Array.length->Int.toFloat /. 20.0), + 1, + ) -let getLineGraphOptions = (lineGraphOptions: lineGraphPayload) => { - let {categories, data, title} = lineGraphOptions { chart: { \"type": "line", @@ -71,6 +29,7 @@ let getLineGraphOptions = (lineGraphOptions: lineGraphPayload) => { }, y: 35, }, + tickInterval: stepInterval, gridLineWidth: 1, gridLineColor: "#e6e6e6", tickmarkPlacement: "on", @@ -88,7 +47,7 @@ let getLineGraphOptions = (lineGraphOptions: lineGraphPayload) => { backgroundColor: "transparent", borderColor: "transparent", borderWidth: 0.0, - formatter: tooltipFormatter(~title), + formatter: tooltipFormatter, useHTML: true, shared: true, // Allows multiple series' data to be shown in a single tooltip }, diff --git a/src/screens/NewAnalytics/NewAnalyticsHelper.res b/src/screens/NewAnalytics/NewAnalyticsHelper.res index 731267c00..3b49aab76 100644 --- a/src/screens/NewAnalytics/NewAnalyticsHelper.res +++ b/src/screens/NewAnalytics/NewAnalyticsHelper.res @@ -83,6 +83,7 @@ module Tabs = { {options ->Array.mapWithIndex((tabValue, index) =>
Int.toString} className={`px-3 py-2 ${tabValue.value->getStyle(index)} selection:bg-white`} onClick={_ => setOption(tabValue)}> {tabValue.label->React.string} @@ -172,6 +173,7 @@ module StatisticsCard = { let (bgColor, textColor) = switch direction { | Upward => ("bg-green-light", "text-green-dark") | Downward => ("bg-red-light", "text-red-dark") + | No_Change => ("bg-gray-100", "text-gray-500") }
diff --git a/src/screens/NewAnalytics/NewAnalyticsTypes.res b/src/screens/NewAnalytics/NewAnalyticsTypes.res index 7ce136704..229217cfd 100644 --- a/src/screens/NewAnalytics/NewAnalyticsTypes.res +++ b/src/screens/NewAnalytics/NewAnalyticsTypes.res @@ -1,6 +1,6 @@ type analyticsPages = Payment type viewType = Graph | Table -type statisticsDirection = Upward | Downward +type statisticsDirection = Upward | Downward | No_Change type analyticsPagesRoutes = | @as("new-analytics-payment") NewAnalyticsPayment @@ -23,10 +23,12 @@ type metrics = [ | #payment_method_type | #card_network | #authentication_type + | #payments_distribution | #smart_retried_amount | #payments_success_rate | #refund_success_count | #dispute_status_metric + | #payment_failed_rate ] type granularity = [ | #G_ONEDAY diff --git a/src/screens/NewAnalytics/NewAnalyticsUtils.res b/src/screens/NewAnalytics/NewAnalyticsUtils.res index 0c808f2a2..df5994073 100644 --- a/src/screens/NewAnalytics/NewAnalyticsUtils.res +++ b/src/screens/NewAnalytics/NewAnalyticsUtils.res @@ -55,6 +55,7 @@ let requestBody = ( ~applyFilterFor as _: option>=None, ~delta: option=None, ~granularity: option=None, + ~distributionValues: option=None, ) => { let metrics = metrics->Array.map(v => (v: metrics :> string)) let filter = Dict.make()->JSON.Encode.object->Some @@ -68,6 +69,7 @@ let requestBody = ( ~startDateTime=startTime, ~endDateTime=endTime, ~granularity, + ~distributionValues, )->JSON.Encode.object, ]->JSON.Encode.array } @@ -98,3 +100,73 @@ let getComparisionTimePeriod = (~startDate, ~endDate) => { (startTimeValue, endTimeVal) } + +let getMonthName = month => { + switch month { + | 0 => "Jan" + | 1 => "Feb" + | 2 => "Mar" + | 3 => "Apr" + | 4 => "May" + | 5 => "Jun" + | 6 => "Jul" + | 7 => "Aug" + | 8 => "Sep" + | 9 => "Oct" + | 10 => "Nov" + | 11 => "Dec" + | _ => "" + } +} + +let getLabelName = (~key, ~index, ~points) => { + open LogicUtils + let getDateObject = (array, index) => { + array + ->getValueFromArray(index, Dict.make()->JSON.Encode.object) + ->getDictFromJsonObject + ->getString(key, "") + ->DayJs.getDayJsForString + } + + if key === "time_bucket" { + let pointsArray = points->getArrayFromJson([]) + let startPoint = pointsArray->getDateObject(0) + let endPoint = pointsArray->getDateObject(1) + + let startDate = `${startPoint.month()->getMonthName} ${startPoint.format("DD")}` + let endDate = `${endPoint.month()->getMonthName} ${endPoint.format("DD")}` + + `${startDate}-${endDate}` + } else { + `Series ${(index + 1)->Int.toString}` + } +} +let calculatePercentageChange = (~primaryValue, ~secondaryValue) => { + open NewAnalyticsTypes + let change = secondaryValue -. primaryValue + + if primaryValue === 0.0 || change === 0.0 { + (0.0, No_Change) + } else if change > 0.0 { + let diff = change /. primaryValue + let percentage = diff *. 100.0 + (percentage, Upward) + } else { + let diff = change *. -1.0 /. primaryValue + let percentage = diff *. 100.0 + (percentage, Downward) + } +} + +let getToolTipConparision = (~primaryValue, ~secondaryValue) => { + let (value, direction) = calculatePercentageChange(~primaryValue, ~secondaryValue) + + let (textColor, icon) = switch direction { + | Upward => ("#12B76A", "▲") + | Downward => ("#F04E42", "▼") + | No_Change => ("#A0A0A0", "") + } + + `${icon}${value->valueFormatter(Rate)}` +} diff --git a/src/screens/NewAnalytics/PaymentAnalytics/FailedPaymentsDistribution/FailedPaymentsDistribution.res b/src/screens/NewAnalytics/PaymentAnalytics/FailedPaymentsDistribution/FailedPaymentsDistribution.res new file mode 100644 index 000000000..5c5f6609b --- /dev/null +++ b/src/screens/NewAnalytics/PaymentAnalytics/FailedPaymentsDistribution/FailedPaymentsDistribution.res @@ -0,0 +1,155 @@ +open NewAnalyticsTypes +open NewAnalyticsHelper +open NewPaymentAnalyticsEntity +open BarGraphTypes +open FailedPaymentsDistributionUtils + +module TableModule = { + @react.component + let make = (~data, ~className="", ~selectedTab: string) => { + let (offset, setOffset) = React.useState(_ => 0) + let defaultSort: Table.sortedObject = { + key: "", + order: Table.INC, + } + let tableBorderClass = "border-2 border-solid border-jp-gray-940 border-collapse border-opacity-30 dark:border-jp-gray-dark_table_border_color dark:border-opacity-30" + let visibleColumns = visibleColumns->Array.concat([selectedTab->getDimentionType]) + let tableData = getTableData(data) + +
+ Array.length} + offset + setOffset + defaultSort + currrentFetchCount={tableData->Array.length} + tableLocalFilter=false + tableheadingClass=tableBorderClass + tableBorderClass + ignoreHeaderBg=true + tableDataBorderClass=tableBorderClass + isAnalyticsModule=true + /> +
+ } +} + +module FailedPaymentsDistributionHeader = { + @react.component + let make = (~viewType, ~setViewType, ~groupBy, ~setGroupBy) => { + let setViewType = value => { + setViewType(_ => value) + } + + let setGroupBy = value => { + setGroupBy(_ => value) + } + +
+ +
+ +
+
+ } +} + +@react.component +let make = ( + ~entity: moduleEntity, + ~chartEntity: chartEntity, +) => { + open LogicUtils + open APIUtils + let getURL = useGetURL() + let updateDetails = useUpdateMethod() + let {filterValueJson} = React.useContext(FilterContext.filterContext) + let (screenState, setScreenState) = React.useState(_ => PageLoaderWrapper.Success) + let (failedPaymentsDistribution, setfailedPaymentsDistribution) = React.useState(_ => + JSON.Encode.array([]) + ) + let (viewType, setViewType) = React.useState(_ => Graph) + let (groupBy, setGroupBy) = React.useState(_ => defaulGroupBy) + let startTimeVal = filterValueJson->getString("startTime", "") + let endTimeVal = filterValueJson->getString("endTime", "") + + let getFailedPaymentsDistribution = async () => { + try { + setScreenState(_ => PageLoaderWrapper.Loading) + let url = getURL( + ~entityName=ANALYTICS_PAYMENTS, + ~methodType=Post, + ~id=Some((entity.domain: domain :> string)), + ) + + let body = NewAnalyticsUtils.requestBody( + ~dimensions=[], + ~startTime=startTimeVal, + ~endTime=endTimeVal, + ~delta=entity.requestBodyConfig.delta, + ~filters=entity.requestBodyConfig.filters, + ~metrics=entity.requestBodyConfig.metrics, + ~groupByNames=[groupBy.value]->Some, + ~customFilter=entity.requestBodyConfig.customFilter, + ~applyFilterFor=entity.requestBodyConfig.applyFilterFor, + ) + + let response = await updateDetails(url, body, Post) + let responseData = response->getDictFromJsonObject->getArrayFromDict("queryData", []) + let arr = + response + ->getDictFromJsonObject + ->getArrayFromDict("queryData", []) + + if arr->Array.length > 0 { + setfailedPaymentsDistribution(_ => responseData->JSON.Encode.array) + setScreenState(_ => PageLoaderWrapper.Success) + } else { + setScreenState(_ => PageLoaderWrapper.Custom) + } + } catch { + | _ => setScreenState(_ => PageLoaderWrapper.Custom) + } + } + + React.useEffect(() => { + if startTimeVal->isNonEmptyString && endTimeVal->isNonEmptyString { + getFailedPaymentsDistribution()->ignore + } + None + }, [startTimeVal, endTimeVal, groupBy.value]) + +
+ + + } customUI={}> + +
+ {switch viewType { + | Graph => + + | Table => + + }} +
+
+
+
+} diff --git a/src/screens/NewAnalytics/PaymentAnalytics/FailedPaymentsDistribution/FailedPaymentsDistributionTypes.res b/src/screens/NewAnalytics/PaymentAnalytics/FailedPaymentsDistribution/FailedPaymentsDistributionTypes.res new file mode 100644 index 000000000..4dc451670 --- /dev/null +++ b/src/screens/NewAnalytics/PaymentAnalytics/FailedPaymentsDistribution/FailedPaymentsDistributionTypes.res @@ -0,0 +1,5 @@ +type failedPaymentsDistributionObject = { + payments_failure_rate_distribution: int, + connector: string, + payment_method: string, +} diff --git a/src/screens/NewAnalytics/PaymentAnalytics/FailedPaymentsDistribution/FailedPaymentsDistributionUtils.res b/src/screens/NewAnalytics/PaymentAnalytics/FailedPaymentsDistribution/FailedPaymentsDistributionUtils.res new file mode 100644 index 000000000..cc457f7f5 --- /dev/null +++ b/src/screens/NewAnalytics/PaymentAnalytics/FailedPaymentsDistribution/FailedPaymentsDistributionUtils.res @@ -0,0 +1,117 @@ +open NewPaymentAnalyticsUtils +open FailedPaymentsDistributionTypes +open LogicUtils + +let getDimentionType = string => { + switch string { + | "connector" => #connector + | "payment_method" => #payment_method + | "payment_method_type" => #payment_method_type + | "card_network" => #card_network + | "authentication_type" | _ => #authentication_type + } +} + +let getXKey = (~isSmartRetry) => { + switch isSmartRetry { + | true => "payments_failure_rate_distribution" + | false => "payments_failure_rate_distribution_without_smart_retries" + } +} + +let failedPaymentsDistributionMapper = ( + ~data: JSON.t, + ~xKey: string, + ~yKey: string, +): BarGraphTypes.barGraphPayload => { + open BarGraphTypes + let categories = [data]->JSON.Encode.array->getCategories(0, yKey) + let barGraphData = getBarGraphObj( + ~array=data->getArrayFromJson([]), + ~key=xKey, + ~name=xKey->snakeToTitle, + ~color="#BA3535", + ) + let title = { + text: "", + } + {categories, data: [barGraphData], title} +} + +open NewAnalyticsTypes +let visibleColumns: array = [#payment_failed_rate] + +let tableItemToObjMapper: Dict.t => failedPaymentsDistributionObject = dict => { + { + payments_failure_rate_distribution: dict->getInt("payments_failure_rate_distribution", 0), + connector: dict->getString((#connector: metrics :> string), ""), + payment_method: dict->getString((#payment_method: metrics :> string), ""), + } +} + +let getObjects: JSON.t => array = json => { + json + ->LogicUtils.getArrayFromJson([]) + ->Array.map(item => { + tableItemToObjMapper(item->getDictFromJsonObject) + }) +} + +let getHeading = (colType: metrics) => { + switch colType { + | #payment_failed_rate => + Table.makeHeaderInfo( + ~key=(#payment_failed_rate: metrics :> string), + ~title="Payments Failed Rate", + ~dataType=TextType, + ) + | #connector => + Table.makeHeaderInfo( + ~key=(#connector: metrics :> string), + ~title="Connector", + ~dataType=TextType, + ) + | #payment_method | _ => + Table.makeHeaderInfo( + ~key=(#payment_method: metrics :> string), + ~title="Payment Method", + ~dataType=TextType, + ) + } +} + +let getCell = (obj, colType: metrics): Table.cell => { + switch colType { + | #payment_failed_rate => Text(obj.payments_failure_rate_distribution->Int.toString) + | #connector => Text(obj.connector) + | #payment_method | _ => Text(obj.payment_method) + } +} + +let getTableData = json => { + json->getArrayDataFromJson(tableItemToObjMapper)->Array.map(Nullable.make) +} + +let tabs = [ + { + label: "Connector", + value: (#connector: dimension :> string), + }, + { + label: "Payment Method", + value: (#payment_method: dimension :> string), + }, + { + label: "Payment Method Type", + value: (#payment_method_type: dimension :> string), + }, + { + label: "Authentication Type", + value: (#authentication_type: dimension :> string), + }, +] + +let defaulGroupBy = { + label: "Connector", + value: (#connector: dimension :> string), +} diff --git a/src/screens/NewAnalytics/PaymentAnalytics/NewPaymentAnalytics.res b/src/screens/NewAnalytics/PaymentAnalytics/NewPaymentAnalytics.res index 2c741f08d..792161264 100644 --- a/src/screens/NewAnalytics/PaymentAnalytics/NewPaymentAnalytics.res +++ b/src/screens/NewAnalytics/PaymentAnalytics/NewPaymentAnalytics.res @@ -17,5 +17,8 @@ let make = () => { entity={successfulPaymentsDistributionEntity} chartEntity={successfulPaymentsDistributionChartEntity} /> +
} diff --git a/src/screens/NewAnalytics/PaymentAnalytics/NewPaymentAnalyticsEntity.res b/src/screens/NewAnalytics/PaymentAnalytics/NewPaymentAnalyticsEntity.res index b5117cd2f..76dbc3a6e 100644 --- a/src/screens/NewAnalytics/PaymentAnalytics/NewPaymentAnalyticsEntity.res +++ b/src/screens/NewAnalytics/PaymentAnalytics/NewPaymentAnalyticsEntity.res @@ -80,13 +80,13 @@ let paymentsSuccessRateChartEntity: chartEntity< getChatOptions: LineGraphUtils.getLineGraphOptions, } -// Payments Distribution +// Successful Payments Distribution let successfulPaymentsDistributionEntity: moduleEntity = { requestBodyConfig: { delta: false, - metrics: [#payment_success_rate], + metrics: [#payments_distribution], }, - title: "Payments Distribution", + title: "Successful Payments Distribution", domain: #payments, } @@ -112,3 +112,36 @@ let successfulPaymentsDistributionTableEntity = { ~getHeading, ) } + +// Failed Payments Distribution +let failedPaymentsDistributionEntity: moduleEntity = { + requestBodyConfig: { + delta: false, + metrics: [#payments_distribution], + }, + title: "Failed Payments Distribution", + domain: #payments, +} + +let failedPaymentsDistributionChartEntity: chartEntity< + BarGraphTypes.barGraphPayload, + BarGraphTypes.barGraphOptions, + JSON.t, +> = { + getObjects: FailedPaymentsDistributionUtils.failedPaymentsDistributionMapper, + getChatOptions: BarGraphUtils.getBarGraphOptions, +} + +let failedPaymentsDistributionTableEntity = { + open FailedPaymentsDistributionUtils + EntityType.makeEntity( + ~uri=``, + ~getObjects, + ~dataKey="queryData", + ~defaultColumns=visibleColumns, + ~requiredSearchFieldsList=[], + ~allColumns=visibleColumns, + ~getCell, + ~getHeading, + ) +} diff --git a/src/screens/NewAnalytics/PaymentAnalytics/NewPaymentAnalyticsUtils.res b/src/screens/NewAnalytics/PaymentAnalytics/NewPaymentAnalyticsUtils.res index c4ebedb1b..38e49e26d 100644 --- a/src/screens/NewAnalytics/PaymentAnalytics/NewPaymentAnalyticsUtils.res +++ b/src/screens/NewAnalytics/PaymentAnalytics/NewPaymentAnalyticsUtils.res @@ -1,30 +1,16 @@ open LogicUtils -let getMonthName = month => { - switch month { - | 0 => "Jan" - | 1 => "Feb" - | 2 => "Mar" - | 3 => "Apr" - | 4 => "May" - | 5 => "Jun" - | 6 => "Jul" - | 7 => "Aug" - | 8 => "Sep" - | 9 => "Oct" - | 10 => "Nov" - | 11 => "Dec" - | _ => "" - } -} - -let getCategories = (data: array, key: string) => { - data->Array.map(item => { +let getCategories = (data: JSON.t, index: int, key: string) => { + data + ->getArrayFromJson([]) + ->getValueFromArray(index, []->JSON.Encode.array) + ->getArrayFromJson([]) + ->Array.map(item => { let value = item->getDictFromJsonObject->getString(key, "") if value->isNonEmptyString && key == "time_bucket" { let dateObj = value->DayJs.getDayJsForString - `${dateObj.month()->getMonthName} ${dateObj.format("DD")}` + `${dateObj.month()->NewAnalyticsUtils.getMonthName} ${dateObj.format("DD")}` } else { value } @@ -45,7 +31,7 @@ let getLineGraphObj = ( item->getDictFromJsonObject->getInt(key, 0) }) let dataObj: LineGraphTypes.dataObj = { - showInLegend: false, + showInLegend: true, name, data, color, @@ -71,7 +57,7 @@ let getBarGraphObj = ( dataObj } -let getBarGraphData = (json: JSON.t, key: string): BarGraphTypes.data => { +let getBarGraphData = (json: JSON.t, key: string, barColor: string): BarGraphTypes.data => { json ->getArrayFromJson([]) ->Array.mapWithIndex((item, index) => { @@ -86,7 +72,7 @@ let getBarGraphData = (json: JSON.t, key: string): BarGraphTypes.data => { showInLegend: false, name: `Series ${(index + 1)->Int.toString}`, data, - color: "#7CC88F", + color: barColor, } dataObj }) @@ -127,19 +113,71 @@ let getMetaDataValue = (~data, ~index, ~key) => { ->getFloat(key, 0.0) } -let calculatePercentageChange = (~primaryValue, ~secondaryValue) => { - open NewAnalyticsTypes - let change = secondaryValue -. primaryValue +open LineGraphTypes +let tooltipFormatter = (~secondaryCategories, ~title, ~metricType) => { + open NewAnalyticsUtils - if primaryValue === 0.0 || change === 0.0 { - (0.0, Upward) - } else if change > 0.0 { - let diff = change /. primaryValue - let percentage = diff *. 100.0 - (percentage, Upward) - } else { - let diff = change *. -1.0 /. primaryValue - let percentage = diff *. 100.0 - (percentage, Downward) - } + ( + @this + (this: pointFormatter) => { + let title = `
${title}
` + + let defaultValue = {color: "", x: "", y: 0.0, point: {index: 0}} + let primartPoint = this.points->getValueFromArray(0, defaultValue) + let secondaryPoint = this.points->getValueFromArray(1, defaultValue) + + let getRowsHtml = (~iconColor, ~date, ~value, ~comparisionComponent="") => { + let valueString = valueFormatter(value, metricType) + `
+
+
${date}${comparisionComponent}
+
${valueString}
+
` + } + + let tableItems = + [ + getRowsHtml(~iconColor=primartPoint.color, ~date=primartPoint.x, ~value=primartPoint.y), + getRowsHtml( + ~iconColor=secondaryPoint.color, + ~date=secondaryCategories->getValueFromArray(secondaryPoint.point.index, ""), + ~value=secondaryPoint.y, + ~comparisionComponent=getToolTipConparision( + ~primaryValue=primartPoint.y, + ~secondaryValue=secondaryPoint.y, + ), + ), + ]->Array.joinWith("") + + let content = ` +
+ ${title} +
+ ${tableItems} +
+
` + + `
+ ${content} +
` + } + )->asTooltipPointFormatter } diff --git a/src/screens/NewAnalytics/PaymentAnalytics/PaymentsLifeCycle/PaymentsLifeCycleUtils.res b/src/screens/NewAnalytics/PaymentAnalytics/PaymentsLifeCycle/PaymentsLifeCycleUtils.res index 1da581b6c..da5e98053 100644 --- a/src/screens/NewAnalytics/PaymentAnalytics/PaymentsLifeCycle/PaymentsLifeCycleUtils.res +++ b/src/screens/NewAnalytics/PaymentAnalytics/PaymentsLifeCycle/PaymentsLifeCycleUtils.res @@ -34,7 +34,7 @@ let paymentsLifeCycleMapper = ( let customerAwaited = data.customerAwaited // DropOff2 let attemptedPayments = pending + customerAwaited + success + failure let pmAwaited = data.pmAwaited // Dropoff1 - let totalPayment = pmAwaited + attemptedPayments + cancelled + let _totalPayment = pmAwaited + attemptedPayments + cancelled let disputed = data.disputed diff --git a/src/screens/NewAnalytics/PaymentAnalytics/PaymentsOverviewSection/NewPaymentsOverviewSection.res b/src/screens/NewAnalytics/PaymentAnalytics/PaymentsOverviewSection/NewPaymentsOverviewSection.res index 74c2ed387..c5b2abd54 100644 --- a/src/screens/NewAnalytics/PaymentAnalytics/PaymentsOverviewSection/NewPaymentsOverviewSection.res +++ b/src/screens/NewAnalytics/PaymentAnalytics/PaymentsOverviewSection/NewPaymentsOverviewSection.res @@ -4,7 +4,6 @@ module SmartRetryCard = { open NewAnalyticsHelper open NewPaymentsOverviewSectionTypes open NewPaymentsOverviewSectionUtils - open NewPaymentAnalyticsUtils open NewAnalyticsUtils @react.component let make = (~metric, ~data) => { @@ -38,7 +37,6 @@ module SmartRetryCard = { module OverViewStat = { open NewAnalyticsHelper open NewAnalyticsUtils - open NewPaymentAnalyticsUtils open NewPaymentsOverviewSectionTypes open NewPaymentsOverviewSectionUtils @react.component diff --git a/src/screens/NewAnalytics/PaymentAnalytics/PaymentsProcessed/PaymentsProcessed.res b/src/screens/NewAnalytics/PaymentAnalytics/PaymentsProcessed/PaymentsProcessed.res index af930d7b1..c0074d531 100644 --- a/src/screens/NewAnalytics/PaymentAnalytics/PaymentsProcessed/PaymentsProcessed.res +++ b/src/screens/NewAnalytics/PaymentAnalytics/PaymentsProcessed/PaymentsProcessed.res @@ -47,6 +47,7 @@ module TableModule = { module PaymentsProcessedHeader = { open NewAnalyticsTypes + open NewAnalyticsUtils open NewPaymentAnalyticsUtils @react.component let make = ( diff --git a/src/screens/NewAnalytics/PaymentAnalytics/PaymentsProcessed/PaymentsProcessedUtils.res b/src/screens/NewAnalytics/PaymentAnalytics/PaymentsProcessed/PaymentsProcessedUtils.res index de1fc8321..4eae44ca4 100644 --- a/src/screens/NewAnalytics/PaymentAnalytics/PaymentsProcessed/PaymentsProcessedUtils.res +++ b/src/screens/NewAnalytics/PaymentAnalytics/PaymentsProcessed/PaymentsProcessedUtils.res @@ -8,25 +8,30 @@ let paymentsProcessedMapper = ( ~yKey: string, ): LineGraphTypes.lineGraphPayload => { open LineGraphTypes - let categories = - data - ->getArrayFromJson([]) - ->getValueFromArray(0, []->JSON.Encode.array) - ->getArrayFromJson([]) - ->getCategories(yKey) + let primaryCategories = data->getCategories(0, yKey) + let secondaryCategories = data->getCategories(1, yKey) let lineGraphData = data ->getArrayFromJson([]) ->Array.mapWithIndex((item, index) => { - let name = `Series ${(index + 1)->Int.toString}` + let name = NewAnalyticsUtils.getLabelName(~key=yKey, ~index, ~points=item) let color = index->getColor getLineGraphObj(~array=item->getArrayFromJson([]), ~key=xKey, ~name, ~color) }) let title = { text: "Payments Processed", } - {categories, data: lineGraphData, title} + { + categories: primaryCategories, + data: lineGraphData, + title, + tooltipFormatter: tooltipFormatter( + ~secondaryCategories, + ~title="Payments Processed", + ~metricType=Amount, + ), + } } // Need to modify let getMetaData = json => diff --git a/src/screens/NewAnalytics/PaymentAnalytics/PaymentsSuccessRate/PaymentsSuccessRate.res b/src/screens/NewAnalytics/PaymentAnalytics/PaymentsSuccessRate/PaymentsSuccessRate.res index 919d02308..273b20b75 100644 --- a/src/screens/NewAnalytics/PaymentAnalytics/PaymentsSuccessRate/PaymentsSuccessRate.res +++ b/src/screens/NewAnalytics/PaymentAnalytics/PaymentsSuccessRate/PaymentsSuccessRate.res @@ -5,6 +5,7 @@ open PaymentsSuccessRateUtils module PaymentsSuccessRateHeader = { open NewPaymentAnalyticsUtils + open NewAnalyticsUtils @react.component let make = (~data, ~keyValue, ~granularity, ~setGranularity) => { let setGranularity = value => { diff --git a/src/screens/NewAnalytics/PaymentAnalytics/PaymentsSuccessRate/PaymentsSuccessRateUtils.res b/src/screens/NewAnalytics/PaymentAnalytics/PaymentsSuccessRate/PaymentsSuccessRateUtils.res index 32df32822..07db96e7b 100644 --- a/src/screens/NewAnalytics/PaymentAnalytics/PaymentsSuccessRate/PaymentsSuccessRateUtils.res +++ b/src/screens/NewAnalytics/PaymentAnalytics/PaymentsSuccessRate/PaymentsSuccessRateUtils.res @@ -19,25 +19,30 @@ let paymentsSuccessRateMapper = ( ~yKey: string, ): LineGraphTypes.lineGraphPayload => { open LineGraphTypes - let categories = - data - ->getArrayFromJson([]) - ->getValueFromArray(0, []->JSON.Encode.array) - ->getArrayFromJson([]) - ->getCategories(yKey) + let primaryCategories = data->getCategories(0, yKey) + let secondaryCategories = data->getCategories(1, yKey) let lineGraphData = data ->getArrayFromJson([]) ->Array.mapWithIndex((item, index) => { - let name = `Series ${(index + 1)->Int.toString}` + let name = NewAnalyticsUtils.getLabelName(~key=yKey, ~index, ~points=item) let color = index->getColor getLineGraphObj(~array=item->getArrayFromJson([]), ~key=xKey, ~name, ~color) }) let title = { text: "Payments Success Rate", } - {categories, data: lineGraphData, title} + { + categories: primaryCategories, + data: lineGraphData, + title, + tooltipFormatter: tooltipFormatter( + ~secondaryCategories, + ~title="Payments Success Rate", + ~metricType=Rate, + ), + } } open NewAnalyticsTypes diff --git a/src/screens/NewAnalytics/PaymentAnalytics/SuccessfulPaymentsDistribution/SuccessfulPaymentsDistribution.res b/src/screens/NewAnalytics/PaymentAnalytics/SuccessfulPaymentsDistribution/SuccessfulPaymentsDistribution.res index a727add6a..1fa98cb51 100644 --- a/src/screens/NewAnalytics/PaymentAnalytics/SuccessfulPaymentsDistribution/SuccessfulPaymentsDistribution.res +++ b/src/screens/NewAnalytics/PaymentAnalytics/SuccessfulPaymentsDistribution/SuccessfulPaymentsDistribution.res @@ -137,7 +137,7 @@ let make = ( entity={chartEntity} object={chartEntity.getObjects( ~data=paymentsDistribution, - ~xKey=(#payment_success_rate: metrics :> string), + ~xKey=getXKey(~isSmartRetry=true), ~yKey=groupBy.value, )} className="mr-3" diff --git a/src/screens/NewAnalytics/PaymentAnalytics/SuccessfulPaymentsDistribution/SuccessfulPaymentsDistributionUtils.res b/src/screens/NewAnalytics/PaymentAnalytics/SuccessfulPaymentsDistribution/SuccessfulPaymentsDistributionUtils.res index c7d1f9770..8f084c3fb 100644 --- a/src/screens/NewAnalytics/PaymentAnalytics/SuccessfulPaymentsDistribution/SuccessfulPaymentsDistributionUtils.res +++ b/src/screens/NewAnalytics/PaymentAnalytics/SuccessfulPaymentsDistribution/SuccessfulPaymentsDistributionUtils.res @@ -12,16 +12,20 @@ let getDimentionType = string => { } } +let getXKey = (~isSmartRetry) => { + switch isSmartRetry { + | true => "payments_success_rate_distribution" + | false => "payments_success_rate_distribution_without_smart_retries" + } +} + let successfulPaymentsDistributionMapper = ( ~data: JSON.t, ~xKey: string, ~yKey: string, ): BarGraphTypes.barGraphPayload => { open BarGraphTypes - let categories = - data - ->getArrayFromJson([]) - ->getCategories(yKey) + let categories = [data]->JSON.Encode.array->getCategories(0, yKey) let barGraphData = getBarGraphObj( ~array=data->getArrayFromJson([]), @@ -32,6 +36,7 @@ let successfulPaymentsDistributionMapper = ( let title = { text: "", } + {categories, data: [barGraphData], title} } @@ -40,7 +45,7 @@ let visibleColumns: array = [#payment_success_rate] let tableItemToObjMapper: Dict.t => successfulPaymentsDistributionObject = dict => { { - payments_success_rate: dict->getInt((#payment_success_rate: metrics :> string), 0), + payments_success_rate: dict->getInt("payments_success_rate_distribution", 0), connector: dict->getString((#connector: metrics :> string), ""), payment_method: dict->getString((#payment_method: metrics :> string), ""), } @@ -85,15 +90,9 @@ let getCell = (obj, colType: metrics): Table.cell => { } } -let getTableData = json => - json - ->getArrayFromJson([]) - ->getValueFromArray(0, []->JSON.Encode.array) - ->getDictFromJsonObject - ->getArrayFromDict("queryData", []) - ->JSON.Encode.array - ->getArrayDataFromJson(tableItemToObjMapper) - ->Array.map(Nullable.make) +let getTableData = json => { + json->getArrayDataFromJson(tableItemToObjMapper)->Array.map(Nullable.make) +} let tabs = [ { diff --git a/src/screens/PMAuthenticationProcessor/PMAuthenticationHome.res b/src/screens/PMAuthenticationProcessor/PMAuthenticationHome.res index da6e8b5de..e6003ea34 100644 --- a/src/screens/PMAuthenticationProcessor/PMAuthenticationHome.res +++ b/src/screens/PMAuthenticationProcessor/PMAuthenticationHome.res @@ -326,8 +326,6 @@ let make = () => { ()} - isPayoutFlow=false getConnectorDetails={Some(getConnectorDetails)} setCurrentStep={_ => ()} /> diff --git a/src/screens/TaxProcessor/TaxProcessorHome.res b/src/screens/TaxProcessor/TaxProcessorHome.res index 0b3a1c981..3e90e8ad1 100644 --- a/src/screens/TaxProcessor/TaxProcessorHome.res +++ b/src/screens/TaxProcessor/TaxProcessorHome.res @@ -344,8 +344,6 @@ let make = () => { ->LogicUtils.getDictFromJsonObject ->ConnectorListMapper.getProcessorPayloadType} connector=connectorName - setScreenState={_ => ()} - isPayoutFlow=false setCurrentStep getConnectorDetails={Some(getConnectorDetails)} /> diff --git a/src/screens/ThreeDsProcessors/ThreeDsProcessorHome.res b/src/screens/ThreeDsProcessors/ThreeDsProcessorHome.res index a66723bc6..a0fd3ac06 100644 --- a/src/screens/ThreeDsProcessors/ThreeDsProcessorHome.res +++ b/src/screens/ThreeDsProcessors/ThreeDsProcessorHome.res @@ -106,8 +106,6 @@ let make = () => { React.useEffect(() => { if connectorName->LogicUtils.isNonEmptyString { getDetails()->ignore - } else { - setScreenState(_ => Error("Connector name not found")) } None }, [connectorName]) @@ -241,8 +239,6 @@ let make = () => { ->LogicUtils.getDictFromJsonObject ->ConnectorListMapper.getProcessorPayloadType} connector=connectorName - setScreenState={_ => ()} - isPayoutFlow=false setCurrentStep={_ => ()} getConnectorDetails={Some(getConnectorDetails)} /> diff --git a/src/utils/Mappers/ConnectorListMapper.res b/src/utils/Mappers/ConnectorListMapper.res index f71ba5d1e..94a07dc20 100644 --- a/src/utils/Mappers/ConnectorListMapper.res +++ b/src/utils/Mappers/ConnectorListMapper.res @@ -1,7 +1,6 @@ open ConnectorTypes +open LogicUtils let parsePaymentMethodType = paymentMethodType => { - open LogicUtils - let paymentMethodTypeDict = paymentMethodType->getDictFromJsonObject { payment_method_type: paymentMethodTypeDict->getString("payment_method_type", ""), @@ -10,8 +9,6 @@ let parsePaymentMethodType = paymentMethodType => { } } let parsePaymentMethodResponse = paymentMethod => { - open LogicUtils - let paymentMethodDict = paymentMethod->getDictFromJsonObject let payment_method_types = paymentMethodDict @@ -28,8 +25,6 @@ let parsePaymentMethodResponse = paymentMethod => { } let parsePaymentMethod = paymentMethod => { - open LogicUtils - let paymentMethodDict = paymentMethod->getDictFromJsonObject let flow = paymentMethodDict->getString("flow", "") @@ -40,8 +35,6 @@ let parsePaymentMethod = paymentMethod => { } let convertFRMConfigJsonToObjResponse = json => { - open LogicUtils - json->Array.map(config => { let configDict = config->getDictFromJsonObject let payment_methods = @@ -55,8 +48,6 @@ let convertFRMConfigJsonToObjResponse = json => { } let convertFRMConfigJsonToObj = json => { - open LogicUtils - json->Array.map(config => { let configDict = config->getDictFromJsonObject let payment_methods = @@ -70,7 +61,6 @@ let convertFRMConfigJsonToObj = json => { } let getPaymentMethodTypes = dict => { - open LogicUtils open ConnectorUtils { payment_method_type: dict->getString("payment_method_type", ""), @@ -86,7 +76,6 @@ let getPaymentMethodTypes = dict => { } let getPaymentMethodsEnabled: Dict.t => paymentMethodEnabledType = dict => { - open LogicUtils { payment_method: dict->getString("payment_method", ""), payment_method_types: dict @@ -97,7 +86,6 @@ let getPaymentMethodsEnabled: Dict.t => paymentMethodEnabledType = dict } let getConnectorAccountDetails = dict => { - open LogicUtils { auth_type: dict->getString("auth_type", ""), api_secret: dict->getString("api_secret", ""), @@ -106,15 +94,73 @@ let getConnectorAccountDetails = dict => { } } +let connectorAuthTypeMapper = (str): connectorAuthType => { + switch str->String.toLowerCase { + | "headerkey" => HeaderKey + | "bodykey" => BodyKey + | "signaturekey" => SignatureKey + | "multiauthkey" => MultiAuthKey + | "currencyauthkey" => CurrencyAuthKey + | "certificateauth" => CertificateAuth + | _ => UnKnownAuthType + } +} + +let getHeaderAuth = (dict): headerKey => { + auth_type: dict->getString("auth_type", ""), + api_key: dict->getString("api_key", ""), +} +let getBodyKeyAuth = (dict): bodyKey => { + auth_type: dict->getString("auth_type", ""), + api_key: dict->getString("api_key", ""), + key1: dict->getString("key1", ""), +} +let getSignatureKeyAuth = (dict): signatureKey => { + auth_type: dict->getString("auth_type", ""), + api_key: dict->getString("api_key", ""), + key1: dict->getString("key1", ""), + api_secret: dict->getString("api_secret", ""), +} +let getMultiAuthKeyAuth = (dict): multiAuthKey => { + auth_type: dict->getString("auth_type", ""), + api_key: dict->getString("api_key", ""), + key1: dict->getString("key1", ""), + api_secret: dict->getString("api_secret", ""), + key2: dict->getString("key2", ""), +} + +let getCurrencyAuthKey = (dict): currencyAuthKey => { + auth_type: dict->getString("auth_type", ""), + auth_key_map: dict->getDictfromDict("auth_key_map"), +} +let getCertificateAuth = (dict): certificateAuth => { + auth_type: dict->getString("auth_type", ""), + certificate: dict->getString("certificate", ""), + private_key: dict->getString("private_key", ""), +} + +let getAccountDetails = (dict): connectorAuthTypeObj => { + let authType = dict->getString("auth_type", "")->connectorAuthTypeMapper + let d = switch authType { + | HeaderKey => HeaderKey(dict->getHeaderAuth) + | BodyKey => BodyKey(dict->getBodyKeyAuth) + | SignatureKey => SignatureKey(dict->getSignatureKeyAuth) + | MultiAuthKey => MultiAuthKey(dict->getMultiAuthKeyAuth) + | CurrencyAuthKey => CurrencyAuthKey(dict->getCurrencyAuthKey) + | CertificateAuth => CertificateAuth(dict->getCertificateAuth) + | UnKnownAuthType => UnKnownAuthType(JSON.Encode.null) + } + d +} + let getProcessorPayloadType = dict => { - open LogicUtils { connector_type: dict->getString("connector_type", ""), connector_name: dict->getString("connector_name", ""), connector_label: dict->getString("connector_label", ""), connector_account_details: dict ->getObj("connector_account_details", Dict.make()) - ->getConnectorAccountDetails, + ->getAccountDetails, test_mode: dict->getBool("test_mode", true), disabled: dict->getBool("disabled", true), payment_methods_enabled: dict @@ -136,7 +182,6 @@ let getProcessorPayloadType = dict => { } let getArrayOfConnectorListPayloadType = json => { - open LogicUtils json ->getArrayFromJson([]) ->Array.map(connectorJson => {