Skip to content

Commit

Permalink
Merge branch 'main' into recovery-gateways
Browse files Browse the repository at this point in the history
  • Loading branch information
sagarnaikjuspay committed Jan 30, 2025
2 parents 6f04e32 + c13ac06 commit 436e5dc
Show file tree
Hide file tree
Showing 11 changed files with 1,390 additions and 2,162 deletions.
3,311 changes: 1,193 additions & 2,118 deletions public/hyperswitch/icons/solid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 7 additions & 2 deletions src/entryPoints/HyperSwitchApp.res
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ let make = () => {
setShowFeedbackModal,
dashboardPageState,
setDashboardPageState,
currentProduct,
setDefaultProductToSessionStorage,
} = React.useContext(GlobalProvider.defaultContext)
let (screenState, setScreenState) = React.useState(_ => PageLoaderWrapper.Loading)
let merchantDetailsTypedValue = Recoil.useRecoilValueFromAtom(merchantDetailsValueAtom)
Expand Down Expand Up @@ -43,14 +45,16 @@ let make = () => {
}, [merchantDetailsTypedValue.merchant_id])

let maintainenceAlert = featureFlagDetails.maintainenceAlert
let hyperSwitchAppSidebars = SidebarValues.useGetSidebarValues(~isReconEnabled)
let productSidebars = ProductsSidebarValues.useGetSideBarValues()
let hyperSwitchAppSidebars = SidebarValues.useGetSidebarValuesForCurrentActive(~isReconEnabled)
let productSidebars = ProductsSidebarValues.useGetProductSideBarValues(~currentProduct)
sessionExpired := false

let applyTheme = async () => {
if devThemeFeature || themeId->LogicUtils.isNonEmptyString {
let _ = await getThemesJson(themeId, JSON.Encode.null, devThemeFeature)
}
}

let setUpDashboard = async () => {
try {
// NOTE: Treat groupACL map similar to screenstate
Expand All @@ -59,6 +63,7 @@ let make = () => {
Window.connectorWasmInit()->ignore
let _ = await fetchMerchantSpecificConfig()
let _ = await fetchUserGroupACL()
setDefaultProductToSessionStorage()
switch url.path->urlPath {
| list{"unauthorized"} => RescriptReactRouter.push(appendDashboardPath(~url="/home"))
| _ => ()
Expand Down
1 change: 1 addition & 0 deletions src/entryPoints/ProductTypes.res
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
type productTypes = Orchestrator | Recon | Recovery
14 changes: 14 additions & 0 deletions src/entryPoints/ProductUtils.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
open ProductTypes
let getVariantFromString = product =>
switch product {
| "Recon" => Recon
| "Recovery" => Recovery
| _ => Orchestrator
}

let getStringFromVariant = product =>
switch product {
| Recon => "Recon"
| Recovery => "Recovery"
| Orchestrator => "Orchestrator"
}
47 changes: 47 additions & 0 deletions src/entryPoints/ProductsSidebarValues.res
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,50 @@ let useGetSideBarValues = () => {

sideBarValues
}

let useGetProductSideBarValues = (~currentProduct: ProductTypes.productTypes) => {
open ProductUtils
let {devReconv2Product, devRecoveryV2Product} =
HyperswitchAtom.featureFlagAtom->Recoil.useRecoilValueFromAtom

let sideBarValues = [
Link({
name: Orchestrator->getStringFromVariant,
icon: "home",
link: "/home",
access: Access,
}),
]

if devReconv2Product {
sideBarValues->Array.push(
Link({
name: Recon->getStringFromVariant,
icon: "recon-home",
link: "/v2/recon/onboarding",
access: Access,
}),
)
}

if devRecoveryV2Product {
sideBarValues->Array.push(
Link({
name: Recovery->getStringFromVariant,
icon: "recovery-home",
link: "/v2/recovery",
access: Access,
}),
)
}

let productName = currentProduct->ProductUtils.getStringFromVariant

sideBarValues->Array.filter(topLevelItem =>
switch topLevelItem {
| Link(optionType) => optionType.name != productName

| _ => true
}
)
}
26 changes: 25 additions & 1 deletion src/entryPoints/Provider/GlobalProvider.res
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ let defaultValue = {
setPermissionInfo: _ => (),
isProdIntentCompleted: None,
setIsProdIntentCompleted: _ => (),
currentProduct: Orchestrator,
setCurrentProductValue: _ => (),
setDefaultProductToSessionStorage: _ => (),
}

let defaultContext = React.createContext(defaultValue)
Expand All @@ -25,16 +28,34 @@ module Provider = {

@react.component
let make = (~children) => {
open SessionStorage
open ProductTypes
let (showFeedbackModal, setShowFeedbackModal) = React.useState(_ => false)
let (showProdIntentForm, setShowProdIntentForm) = React.useState(_ => false)
let (dashboardPageState, setDashboardPageState) = React.useState(_ => #DEFAULT)
let (permissionInfo, setPermissionInfo) = React.useState(_ => [])
let (isProdIntentCompleted, setIsProdIntentCompleted) = React.useState(_ => None)

let (currentProduct, setCurrentProduct) = React.useState(_ => Orchestrator)
let (integrationDetails, setIntegrationDetails) = React.useState(_ =>
Dict.make()->JSON.Encode.object->ProviderHelper.getIntegrationDetails
)

let setCurrentProductValue = product => {
setCurrentProduct(_ => product)
sessionStorage.setItem("product", product->ProductUtils.getStringFromVariant)
}

let setDefaultProductToSessionStorage = () => {
open ProductUtils
let currentSessionData = sessionStorage.getItem("product")->Nullable.toOption
let data = switch currentSessionData {
| Some(sessionData) => sessionData->getVariantFromString
| None => Orchestrator
}

setCurrentProductValue(data)
}

<Provider
value={
showFeedbackModal,
Expand All @@ -49,6 +70,9 @@ let make = (~children) => {
setPermissionInfo,
isProdIntentCompleted,
setIsProdIntentCompleted,
currentProduct,
setCurrentProductValue,
setDefaultProductToSessionStorage,
}>
children
</Provider>
Expand Down
4 changes: 4 additions & 0 deletions src/entryPoints/Provider/ProviderTypes.res
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type integrationDetailsType = {
integration_checklist: integration,
account_activation: integration,
}

type contextType = {
showFeedbackModal: bool,
setShowFeedbackModal: (bool => bool) => unit,
Expand All @@ -30,6 +31,9 @@ type contextType = {
) => unit,
isProdIntentCompleted: option<bool>,
setIsProdIntentCompleted: (option<bool> => option<bool>) => unit,
currentProduct: ProductTypes.productTypes,
setCurrentProductValue: ProductTypes.productTypes => unit,
setDefaultProductToSessionStorage: unit => unit,
}

type sidebarContextType = {
Expand Down
51 changes: 40 additions & 11 deletions src/entryPoints/SidebarValues.res
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module GetProductionAccess = {
switch isProdIntentCompleted {
| Some(_) =>
<div
className={`flex items-center gap-2 ${backgroundColor} ${cursorStyles} px-4 py-3 m-2 ml-2 mb-3 !mx-4 whitespace-nowrap rounded`}
className={`flex items-center gap-2 ${backgroundColor} ${cursorStyles} px-4 py-3 whitespace-nowrap rounded`}
onClick={_ => {
isProdIntent
? ()
Expand All @@ -45,6 +45,16 @@ module GetProductionAccess = {
}
}

module ProductHeaderComponent = {
@react.component
let make = () => {
let {currentProduct} = React.useContext(GlobalProvider.defaultContext)

<div className={`text-sm font-semibold px-3 pt-6 pb-2 text-nd_gray-400`}>
{React.string(currentProduct->ProductUtils.getStringFromVariant->String.toUpperCase)}
</div>
}
}
let emptyComponent = CustomComponent({
component: React.null,
})
Expand All @@ -67,7 +77,7 @@ let home = isHomeEnabled =>
isHomeEnabled
? Link({
name: "Home",
icon: "hswitch-home",
icon: "nd-home",
link: "/home",
access: Access,
})
Expand Down Expand Up @@ -138,7 +148,7 @@ let operations = (isOperationsEnabled, ~userHasResourceAccess, ~isPayoutsEnabled
isOperationsEnabled
? Section({
name: "Operations",
icon: "hswitch-operations",
icon: "nd-operations",
showSection: true,
links,
})
Expand Down Expand Up @@ -250,7 +260,7 @@ let connectors = (
isConnectorsEnabled
? Section({
name: "Connectors",
icon: "connectors",
icon: "nd-connectors",
showSection: true,
links: connectorLinkArray,
})
Expand Down Expand Up @@ -327,7 +337,7 @@ let analytics = (
isAnalyticsEnabled
? Section({
name: "Analytics",
icon: "analytics",
icon: "nd-analytics",
showSection: userHasResourceAccess(~resourceAccess=Analytics) === CommonAuthTypes.Access,
links,
})
Expand Down Expand Up @@ -406,7 +416,7 @@ let workflow = (
isWorkflowEnabled
? Section({
name: "Workflow",
icon: "3ds",
icon: "nd-workflow",
showSection: true,
links: defaultWorkFlow,
})
Expand Down Expand Up @@ -476,7 +486,7 @@ let settings = (~isConfigurePmtsEnabled, ~userHasResourceAccess, ~complianceCert

Section({
name: "Settings",
icon: "hswitch-settings",
icon: "nd-settings",
showSection: true,
links: settingsLinkArray,
})
Expand Down Expand Up @@ -514,7 +524,7 @@ let developers = (isDevelopersEnabled, ~userHasResourceAccess, ~checkUserEntity)
isDevelopersEnabled
? Section({
name: "Developers",
icon: "developer",
icon: "nd-developers",
showSection: true,
links: defaultDevelopersOptions,
})
Expand Down Expand Up @@ -618,9 +628,8 @@ let reconAndSettlement = (recon, isReconEnabled, checkUserEntity, userHasResourc
}
}

let useGetSidebarValues = (~isReconEnabled: bool) => {
let useGetHsSidebarValues = (~isReconEnabled: bool) => {
let featureFlagDetails = HyperswitchAtom.featureFlagAtom->Recoil.useRecoilValueFromAtom
let {userHasAccess, hasAnyGroupAccess} = GroupACLHooks.useUserGroupACLHook()
let {userHasResourceAccess} = GroupACLHooks.useUserGroupACLHook()
let {userInfo: {userEntity}, checkUserEntity} = React.useContext(UserInfoProvider.defaultContext)
let {
Expand All @@ -647,7 +656,6 @@ let useGetSidebarValues = (~isReconEnabled: bool) => {
let isNewAnalyticsEnable =
newAnalytics && useIsFeatureEnabledForMerchant(merchantSpecificConfig.newAnalytics)
let sidebar = [
productionAccessComponent(!isLiveMode, userHasAccess, hasAnyGroupAccess),
default->home,
default->operations(~userHasResourceAccess, ~isPayoutsEnabled=payOut, ~userEntity),
default->connectors(
Expand Down Expand Up @@ -679,3 +687,24 @@ let useGetSidebarValues = (~isReconEnabled: bool) => {

sidebar
}

let useGetSidebarValuesForCurrentActive = (~isReconEnabled) => {
let {currentProduct} = React.useContext(GlobalProvider.defaultContext)
let featureFlagDetails = HyperswitchAtom.featureFlagAtom->Recoil.useRecoilValueFromAtom
let {userHasAccess, hasAnyGroupAccess} = GroupACLHooks.useUserGroupACLHook()
let {isLiveMode} = featureFlagDetails

let hsSidebars = useGetHsSidebarValues(~isReconEnabled)
let defaultSidebar = [
productionAccessComponent(!isLiveMode, userHasAccess, hasAnyGroupAccess),
CustomComponent({
component: <ProductHeaderComponent />,
}),
]
let sidebarValuesForProduct = switch currentProduct {
| Orchestrator => hsSidebars
| Recon => [ReconSidebarValues.reconSidebars]
| Recovery => [RevenueRecoverySidebarValues.recoverySidebars]
}
defaultSidebar->Array.concat(sidebarValuesForProduct)
}
2 changes: 1 addition & 1 deletion src/screens/Analytics/GlobalSearch/GlobalSearchBar.res
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ let make = () => {
let (searchResults, setSearchResults) = React.useState(_ => [])
let merchentDetails = HSwitchUtils.useMerchantDetailsValue()
let isReconEnabled = merchentDetails.recon_status === Active
let hswitchTabs = SidebarValues.useGetSidebarValues(~isReconEnabled)
let hswitchTabs = SidebarValues.useGetHsSidebarValues(~isReconEnabled)
let loader = LottieFiles.useLottieJson("loader-circle.json")
let {globalSearch, globalSearchFilters} =
HyperswitchAtom.featureFlagAtom->Recoil.useRecoilValueFromAtom
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ let make = () => {
let globalSearchResult = HyperswitchAtom.globalSeacrchAtom->Recoil.useRecoilValueFromAtom
let merchentDetails = HSwitchUtils.useMerchantDetailsValue()
let isReconEnabled = merchentDetails.recon_status === Active
let hswitchTabs = SidebarValues.useGetSidebarValues(~isReconEnabled)
let hswitchTabs = SidebarValues.useGetHsSidebarValues(~isReconEnabled)
let query = UrlUtils.useGetFilterDictFromUrl("")->getString("query", "")
let {globalSearch} = HyperswitchAtom.featureFlagAtom->Recoil.useRecoilValueFromAtom
let {userHasAccess} = GroupACLHooks.useUserGroupACLHook()
Expand Down
Loading

0 comments on commit 436e5dc

Please sign in to comment.