diff --git a/config/config.toml b/config/config.toml index 7c9dca37c..667fba5b7 100644 --- a/config/config.toml +++ b/config/config.toml @@ -41,5 +41,6 @@ branding=false totp=false live_users_counter=false granularity=false -custom_webhook_headers=false +custom_webhook_headers=true +dynamic_custom_webhook_headers=false compliance_certificate=false diff --git a/src/entryPoints/FeatureFlagUtils.res b/src/entryPoints/FeatureFlagUtils.res index e70e869b2..f48c3d451 100644 --- a/src/entryPoints/FeatureFlagUtils.res +++ b/src/entryPoints/FeatureFlagUtils.res @@ -29,6 +29,7 @@ type featureFlag = { liveUsersCounter: bool, granularity: bool, customWebhookHeaders: bool, + dynamicCustomWebhookHeaders: bool, complianceCertificate: bool, } @@ -66,6 +67,7 @@ let featureFlagType = (featureFlags: JSON.t) => { liveUsersCounter: dict->getBool("live_users_counter", false), granularity: dict->getBool("granularity", false), customWebhookHeaders: dict->getBool("custom_webhook_headers", false), + dynamicCustomWebhookHeaders: dict->getBool("dynamic_custom_webhook_headers", false), complianceCertificate: dict->getBool("compliance_certificate", false), } typedFeatureFlag diff --git a/src/screens/Developer/PaymentSettings/PaymentSettings.res b/src/screens/Developer/PaymentSettings/PaymentSettings.res index 15e6d1b8a..f6867cfc1 100644 --- a/src/screens/Developer/PaymentSettings/PaymentSettings.res +++ b/src/screens/Developer/PaymentSettings/PaymentSettings.res @@ -26,99 +26,284 @@ module InfoViewForWebhooks = { } } -module AuthenticationInput = { - @react.component - let make = (~index) => { - open LogicUtils - open FormRenderer - let formState: ReactFinalForm.formState = ReactFinalForm.useFormState( - ReactFinalForm.useFormSubscription(["values"])->Nullable.make, - ) - let (key, setKey) = React.useState(_ => "") - let (metaValue, setValue) = React.useState(_ => "") - let getOutGoingWebhook = () => { +module DynamicWebHookAuthHeader = { + module AuthenticationInput = { + @react.component + let make = (~index, ~removeInput, ~webHookAuthInputs) => { + open LogicUtils + open FormRenderer + let formState: ReactFinalForm.formState = ReactFinalForm.useFormState( + ReactFinalForm.useFormSubscription(["values"])->Nullable.make, + ) let outGoingWebhookDict = formState.values ->getDictFromJsonObject ->getDictfromDict("outgoing_webhook_custom_http_headers") - let key = outGoingWebhookDict->Dict.keysToArray->LogicUtils.getValueFromArray(index, "") - let outGoingWebHookVal = outGoingWebhookDict->getOptionString(key) - switch outGoingWebHookVal { - | Some(value) => (key, value) - | _ => ("", "") - } - } - React.useEffect(() => { - let (outGoingWebhookKey, outGoingWebHookValue) = getOutGoingWebhook() - setValue(_ => outGoingWebHookValue) - setKey(_ => outGoingWebhookKey) - None - }, []) - let form = ReactFinalForm.useForm() - let keyInput: ReactFinalForm.fieldRenderPropsInput = { - name: "string", - onBlur: _ => (), - onChange: ev => { - let value = ReactEvent.Form.target(ev)["value"] - if value->String.length <= 0 { - let name = `outgoing_webhook_custom_http_headers.${key}` - form.change(name, JSON.Encode.null) - } - switch value->getOptionIntFromString->Option.isNone { - | true => setKey(_ => value) - | _ => () - } - }, - onFocus: _ => (), - value: key->JSON.Encode.string, - checked: true, - } - let valueInput: ReactFinalForm.fieldRenderPropsInput = { - name: "string", - onBlur: _ => { - if key->String.length > 0 { - let name = `outgoing_webhook_custom_http_headers.${key}` - form.change(name, metaValue->JSON.Encode.string) + let (key, setKey) = React.useState(_ => "") + let (metaValue, setValue) = React.useState(_ => "") + let getOutGoingWebhook = () => { + let key = outGoingWebhookDict->Dict.keysToArray->LogicUtils.getValueFromArray(index, "") + let outGoingWebHookVal = outGoingWebhookDict->getOptionString(key) + switch outGoingWebHookVal { + | Some(value) => (key, value) + | _ => ("", "") } - }, - onChange: ev => { - let value = ReactEvent.Form.target(ev)["value"] - setValue(_ => value) - }, - onFocus: _ => (), - value: metaValue->JSON.Encode.string, - checked: true, - } + } + React.useEffect(() => { + let (outGoingWebhookKey, outGoingWebHookValue) = getOutGoingWebhook() + setValue(_ => outGoingWebHookValue) + setKey(_ => outGoingWebhookKey) - -
- -
-
- + None + }, [webHookAuthInputs]) + let form = ReactFinalForm.useForm() + let keyInput: ReactFinalForm.fieldRenderPropsInput = { + name: "string", + onBlur: _ => { + if key->String.length > 0 { + let name = `outgoing_webhook_custom_http_headers.${key}` + form.change(name, metaValue->JSON.Encode.string) + } + }, + onChange: ev => { + let value = ReactEvent.Form.target(ev)["value"] + if value->String.length <= 0 { + let details = + formState.values + ->getDictFromJsonObject + ->getDictfromDict("outgoing_webhook_custom_http_headers") + ->Dict.toArray + ->Array.filter(((formKey, _)) => formKey != key) + ->Dict.fromArray + form.change("outgoing_webhook_custom_http_headers", details->Identity.genericTypeToJson) + setKey(_ => value) + } + switch value->getOptionIntFromString->Option.isNone { + | true => setKey(_ => value) + | _ => () + } + }, + onFocus: _ => (), + value: key->JSON.Encode.string, + checked: true, + } + let valueInput: ReactFinalForm.fieldRenderPropsInput = { + name: "string", + onBlur: _ => (), + onChange: ev => { + let value = ReactEvent.Form.target(ev)["value"] + if key->String.length > 0 { + let name = `outgoing_webhook_custom_http_headers.${key}` + form.change(name, value->JSON.Encode.string) + } + setValue(_ => value) + }, + onFocus: _ => (), + value: metaValue->JSON.Encode.string, + checked: true, + } + let showCloseIcon = () => { + outGoingWebhookDict->Dict.keysToArray->Array.length >= 1 && + webHookAuthInputs->Array.length > 1 + } +
+ +
+ +
+
+ +
+
+ +
+ removeInput(index, key)} /> +
+
- + } } -} -module WebHookAuthenticationHeaders = { - @react.component - let make = () => { -
-

- {"Custom HTTP Headers"->React.string} -

-
- {Array.fromInitializer(~length=4, i => i) + module WebHookAuthenticationHeaders = { + @react.component + let make = () => { + open LogicUtils + let form = ReactFinalForm.useForm() + let formState: ReactFinalForm.formState = ReactFinalForm.useFormState( + ReactFinalForm.useFormSubscription(["values"])->Nullable.make, + ) + let (webHookAuthInputs, setWebHookAuthInputs) = React.useState(_ => + Array.fromInitializer(~length=1, i => i) + ) + React.useEffect(() => { + let length = + formState.values + ->getDictFromJsonObject + ->getDictfromDict("outgoing_webhook_custom_http_headers") + ->Dict.toArray + ->Array.length + let arr = Array.fromInitializer(~length=length > 0 ? length : 1, i => i) + setWebHookAuthInputs(_ => arr) + None + }, []) + let removeInput = (removeIndex, removeKey) => { + let details = + formState.values + ->getDictFromJsonObject + ->getDictfromDict("outgoing_webhook_custom_http_headers") + ->Dict.toArray + ->Array.filter(((key, _)) => key != removeKey) + ->Dict.fromArray + form.change("outgoing_webhook_custom_http_headers", details->Identity.genericTypeToJson) + setWebHookAuthInputs(_ => + webHookAuthInputs->Array.filterWithIndex((_, index) => index != removeIndex) + ) + } + let addInput = () => { + setWebHookAuthInputs(_ => + Array.fromInitializer(~length=webHookAuthInputs->Array.length + 1, i => i) + ) + } + + let checkForEmpty = () => { + let arr = + formState.values + ->getDictFromJsonObject + ->getDictfromDict("outgoing_webhook_custom_http_headers") + ->Dict.toArray + ->Array.filter(((key, value)) => + key->String.length != 0 && value->getStringFromJson("")->String.length != 0 + ) + + arr->Array.length == webHookAuthInputs->Array.length ? true : false + } +
+

+ {"Custom HTTP Headers"->React.string} +

+ {webHookAuthInputs ->Array.mapWithIndex((_, index) => -
Int.toString} className="col-span-4"> - +
Int.toString} className="grid grid-cols-5 flex gap-4"> +
Int.toString} className="col-span-4"> + +
+ Array.length - 1 && + index != 3 && + checkForEmpty()}> +
+ addInput()} + /> +
+
) ->React.array}
-
+ } + } +} + +module WebHookAuthHeader = { + module AuthenticationInput = { + @react.component + let make = (~index) => { + open LogicUtils + open FormRenderer + let formState: ReactFinalForm.formState = ReactFinalForm.useFormState( + ReactFinalForm.useFormSubscription(["values"])->Nullable.make, + ) + let (key, setKey) = React.useState(_ => "") + let (metaValue, setValue) = React.useState(_ => "") + let getOutGoingWebhook = () => { + let outGoingWebhookDict = + formState.values + ->getDictFromJsonObject + ->getDictfromDict("outgoing_webhook_custom_http_headers") + let key = outGoingWebhookDict->Dict.keysToArray->LogicUtils.getValueFromArray(index, "") + let outGoingWebHookVal = outGoingWebhookDict->getOptionString(key) + switch outGoingWebHookVal { + | Some(value) => (key, value) + | _ => ("", "") + } + } + React.useEffect(() => { + let (outGoingWebhookKey, outGoingWebHookValue) = getOutGoingWebhook() + setValue(_ => outGoingWebHookValue) + setKey(_ => outGoingWebhookKey) + + None + }, []) + let form = ReactFinalForm.useForm() + let keyInput: ReactFinalForm.fieldRenderPropsInput = { + name: "string", + onBlur: _ => (), + onChange: ev => { + let value = ReactEvent.Form.target(ev)["value"] + if value->String.length <= 0 { + let name = `outgoing_webhook_custom_http_headers.${key}` + form.change(name, JSON.Encode.null) + } + switch value->getOptionIntFromString->Option.isNone { + | true => setKey(_ => value) + | _ => () + } + }, + onFocus: _ => (), + value: key->JSON.Encode.string, + checked: true, + } + let valueInput: ReactFinalForm.fieldRenderPropsInput = { + name: "string", + onBlur: _ => { + if key->String.length > 0 { + let name = `outgoing_webhook_custom_http_headers.${key}` + form.change(name, metaValue->JSON.Encode.string) + } + }, + onChange: ev => { + let value = ReactEvent.Form.target(ev)["value"] + setValue(_ => value) + }, + onFocus: _ => (), + value: metaValue->JSON.Encode.string, + checked: true, + } + + +
+ +
+
+ +
+
+ } + } + module WebHookAuthenticationHeaders = { + @react.component + let make = () => { +
+

+ {"Custom HTTP Headers"->React.string} +

+
+ {Array.fromInitializer(~length=4, i => i) + ->Array.mapWithIndex((_, index) => +
Int.toString} className="col-span-4"> + +
+ ) + ->React.array} +
+
+ } } } @@ -127,7 +312,8 @@ module WebHook = { let make = (~setCustomHttpHeaders, ~enableCustomHttpHeaders) => { open FormRenderer open LogicUtils - let {customWebhookHeaders} = HyperswitchAtom.featureFlagAtom->Recoil.useRecoilValueFromAtom + let {customWebhookHeaders, dynamicCustomWebhookHeaders} = + HyperswitchAtom.featureFlagAtom->Recoil.useRecoilValueFromAtom let form = ReactFinalForm.useForm() let formState: ReactFinalForm.formState = ReactFinalForm.useFormState( ReactFinalForm.useFormSubscription(["values"])->Nullable.make, @@ -173,7 +359,7 @@ module WebHook = { fieldWrapperClass="max-w-xl" />
- +
@@ -192,8 +378,11 @@ module WebHook = {
+ + + - + }