diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 65cef3f89e17..5d2d795be9df 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -5160,6 +5160,12 @@ function enablePolicyFeatureForConnection(policy: OnyxEntry, featureName if (!policy?.id || PolicyUtils.isPolicyFeatureEnabled(policy, featureName)) { return; } + // A workspace that is still being created has no connections to fetch. Without this, the open Connections page + // would be replaced by a loader while the fetch waits behind the create request. It's set first so the page never + // sees the feature on without it. + if (featureName === CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED && policy.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_HAS_CONNECTIONS_DATA_BEEN_FETCHED}${policy.id}`, true); + } ENABLE_CONNECTION_FEATURE[featureName](policy.id, true, false); } diff --git a/src/pages/workspace/WorkspaceMoreFeaturesPage/index.tsx b/src/pages/workspace/WorkspaceMoreFeaturesPage/index.tsx index 53afa54bbcea..28079f9de2bb 100644 --- a/src/pages/workspace/WorkspaceMoreFeaturesPage/index.tsx +++ b/src/pages/workspace/WorkspaceMoreFeaturesPage/index.tsx @@ -53,6 +53,7 @@ import { import {getIsTravelBillingEnabled, getTravelBillingCardSettingsKey} from '@libs/TravelBillingUtils'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; +import {getAccountingConnectionsRoute} from '@pages/workspace/connections/utils'; import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading'; import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading'; @@ -218,7 +219,7 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro if (action !== ModalActions.CONFIRM) { return; } - Navigation.navigate(ROUTES.POLICY_ACCOUNTING.getRoute(policyID)); + Navigation.navigate(getAccountingConnectionsRoute(isUnifiedConnectionsBetaEnabled, policyID)); }; const warnVendorsManagedByAccounting = async () => { diff --git a/src/pages/workspace/accounting/AccountingContext/index.tsx b/src/pages/workspace/accounting/AccountingContext/index.tsx index 613063ec86eb..90c22534e904 100644 --- a/src/pages/workspace/accounting/AccountingContext/index.tsx +++ b/src/pages/workspace/accounting/AccountingContext/index.tsx @@ -11,7 +11,7 @@ import useLocalize from '@hooks/useLocalize'; import {getAccountingIntegrationDisplayName} from '@libs/AccountingUtils'; import {removePolicyConnection} from '@libs/actions/connections'; import Navigation from '@libs/Navigation/Navigation'; -import {isControlPolicy, tryNavigateToSubmitWorkspaceUpgrade} from '@libs/PolicyUtils'; +import {isControlPolicy, isPolicyFeatureEnabled, tryNavigateToSubmitWorkspaceUpgrade} from '@libs/PolicyUtils'; import {getAccountingIntegrationData} from '@pages/workspace/accounting/utils'; @@ -158,7 +158,8 @@ function AccountingContextProvider({children, policy}: AccountingContextProvider ); // Connections has no feature toggle, so turn it on here. The Control upgrade only enables the integration's own feature. - if (isUnifiedConnectionsBetaEnabled) { + const shouldEnableConnections = isUnifiedConnectionsBetaEnabled && !isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED); + if (shouldEnableConnections) { enablePolicyFeatureForConnection(policy, CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED); } @@ -169,10 +170,16 @@ function AccountingContextProvider({children, policy}: AccountingContextProvider ); return; } - setActiveIntegration({ + const activeIntegrationToStart = { ...newActiveIntegration, key: Math.random(), - }); + }; + // The setup pages redirect to More features while Connections is off, so they open a frame later, once the policy shows it on + if (shouldEnableConnections) { + requestAnimationFrame(() => setActiveIntegration(activeIntegrationToStart)); + } else { + setActiveIntegration(activeIntegrationToStart); + } const integrationToDisconnect = newActiveIntegration.integrationToDisconnect; if (!newActiveIntegration.shouldDisconnectIntegrationBeforeConnecting || !integrationToDisconnect) { diff --git a/src/pages/workspace/accounting/businessCentral/advanced/BusinessCentralAdvancedPage.tsx b/src/pages/workspace/accounting/businessCentral/advanced/BusinessCentralAdvancedPage.tsx index e91c73e7e4ed..da34005bf9be 100644 --- a/src/pages/workspace/accounting/businessCentral/advanced/BusinessCentralAdvancedPage.tsx +++ b/src/pages/workspace/accounting/businessCentral/advanced/BusinessCentralAdvancedPage.tsx @@ -6,6 +6,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useExpensifyCardFeeds from '@hooks/useExpensifyCardFeeds'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -22,6 +23,7 @@ import {getLatestErrorField} from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -39,6 +41,7 @@ function BusinessCentralAdvancedPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const businessCentralConfig = policy?.connections?.businessCentral?.config; const bankAccounts = policy?.connections?.businessCentral?.data?.bankAccounts; const autoSync = businessCentralConfig?.autoSync?.enabled ?? false; @@ -61,6 +64,7 @@ function BusinessCentralAdvancedPage({policy}: WithPolicyConnectionsProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="BusinessCentralAdvancedPage" headerTitle="workspace.accounting.advanced" accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]} diff --git a/src/pages/workspace/accounting/businessCentral/export/BusinessCentralExportPage.tsx b/src/pages/workspace/accounting/businessCentral/export/BusinessCentralExportPage.tsx index 1399630bb069..f65a3833ab92 100644 --- a/src/pages/workspace/accounting/businessCentral/export/BusinessCentralExportPage.tsx +++ b/src/pages/workspace/accounting/businessCentral/export/BusinessCentralExportPage.tsx @@ -8,6 +8,7 @@ import Text from '@components/Text'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useCardFeeds from '@hooks/useCardFeeds'; import useCardsLists from '@hooks/useCardsLists'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -17,6 +18,7 @@ import {getLatestErrorField} from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -46,6 +48,7 @@ function BusinessCentralExportPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const [cardFeeds] = useCardFeeds(policyID); const [cardLists] = useCardsLists(); const businessCentralConfig = policy?.connections?.businessCentral?.config; @@ -185,6 +188,7 @@ function BusinessCentralExportPage({policy}: WithPolicyConnectionsProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="BusinessCentralExportPage" headerTitle="workspace.accounting.export" accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]} diff --git a/src/pages/workspace/accounting/businessCentral/import/BusinessCentralImportPage.tsx b/src/pages/workspace/accounting/businessCentral/import/BusinessCentralImportPage.tsx index e9410ef2b8f9..423b0ae41ebb 100644 --- a/src/pages/workspace/accounting/businessCentral/import/BusinessCentralImportPage.tsx +++ b/src/pages/workspace/accounting/businessCentral/import/BusinessCentralImportPage.tsx @@ -6,6 +6,7 @@ import ConnectionLayout from '@components/ConnectionLayout'; import Text from '@components/Text'; import useConfirmModal from '@hooks/useConfirmModal'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -18,8 +19,10 @@ import { updateBusinessCentralSyncTaxRates, } from '@libs/actions/connections/BusinessCentral'; import {getLatestErrorField} from '@libs/ErrorUtils'; +import Navigation from '@libs/Navigation/Navigation'; import {settingsPendingAction} from '@libs/PolicyUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -75,6 +78,7 @@ function BusinessCentralImportPage({policy}: WithPolicyConnectionsProps) { const {showConfirmModal} = useConfirmModal(); const styles = useThemeStyles(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const businessCentralConfig = policy?.connections?.businessCentral?.config; const businessCentralData = policy?.connections?.businessCentral?.data; @@ -104,6 +108,7 @@ function BusinessCentralImportPage({policy}: WithPolicyConnectionsProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="BusinessCentralImportPage" headerTitle="workspace.accounting.import" accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]} diff --git a/src/pages/workspace/accounting/campfire/advanced/CampfireAdvancedPage.tsx b/src/pages/workspace/accounting/campfire/advanced/CampfireAdvancedPage.tsx index 7d90488fbd88..39b72b1f3893 100644 --- a/src/pages/workspace/accounting/campfire/advanced/CampfireAdvancedPage.tsx +++ b/src/pages/workspace/accounting/campfire/advanced/CampfireAdvancedPage.tsx @@ -5,6 +5,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useExpensifyCardFeeds from '@hooks/useExpensifyCardFeeds'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -23,6 +24,7 @@ import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; import {getIsTravelBillingEnabled, getTravelBillingCardSettingsKey} from '@libs/TravelBillingUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -38,6 +40,7 @@ function CampfireAdvancedPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const campfireConfig = policy?.connections?.campfire?.config; const campfireData = policy?.connections?.campfire?.data; const autoSync = campfireConfig?.autoSync?.enabled ?? false; @@ -66,6 +69,7 @@ function CampfireAdvancedPage({policy}: WithPolicyConnectionsProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="CampfireAdvancedPage" headerTitle="workspace.accounting.advanced" accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]} diff --git a/src/pages/workspace/accounting/campfire/export/CampfireExportPage.tsx b/src/pages/workspace/accounting/campfire/export/CampfireExportPage.tsx index 08423428d65d..1a6ad429d275 100644 --- a/src/pages/workspace/accounting/campfire/export/CampfireExportPage.tsx +++ b/src/pages/workspace/accounting/campfire/export/CampfireExportPage.tsx @@ -9,6 +9,7 @@ import Text from '@components/Text'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useCardFeeds from '@hooks/useCardFeeds'; import useCardsLists from '@hooks/useCardsLists'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -18,6 +19,7 @@ import {getLatestErrorField} from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -32,6 +34,7 @@ function CampfireExportPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const [cardFeeds] = useCardFeeds(policyID); const [cardLists] = useCardsLists(); const policyOwner = policy?.owner; @@ -57,6 +60,7 @@ function CampfireExportPage({policy}: WithPolicyConnectionsProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="CampfireExportPage" headerTitle="workspace.accounting.export" accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]} diff --git a/src/pages/workspace/accounting/campfire/import/CampfireImportPage.tsx b/src/pages/workspace/accounting/campfire/import/CampfireImportPage.tsx index 87422746ba73..e41ffb7b4c23 100644 --- a/src/pages/workspace/accounting/campfire/import/CampfireImportPage.tsx +++ b/src/pages/workspace/accounting/campfire/import/CampfireImportPage.tsx @@ -1,13 +1,16 @@ import ConnectionLayout from '@components/ConnectionLayout'; import Text from '@components/Text'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import {clearCampfireErrorField, updateCampfireEnableNewCategories, updateCampfireFieldMapping, updateCampfireSyncTaxRates} from '@libs/actions/connections/Campfire'; import {getLatestErrorField} from '@libs/ErrorUtils'; +import Navigation from '@libs/Navigation/Navigation'; import {settingsPendingAction} from '@libs/PolicyUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -21,6 +24,7 @@ function CampfireImportPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const campfireConfig = policy?.connections?.campfire?.config; const campfireData = policy?.connections?.campfire?.data; const enableNewCategories = campfireConfig?.enableNewCategories ?? false; @@ -30,6 +34,7 @@ function CampfireImportPage({policy}: WithPolicyConnectionsProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="CampfireImportPage" headerTitle="workspace.accounting.import" accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]} diff --git a/src/pages/workspace/accounting/certinia/import/CertiniaImportPage.tsx b/src/pages/workspace/accounting/certinia/import/CertiniaImportPage.tsx index 123cfa2ca67f..a2d6db80522f 100644 --- a/src/pages/workspace/accounting/certinia/import/CertiniaImportPage.tsx +++ b/src/pages/workspace/accounting/certinia/import/CertiniaImportPage.tsx @@ -3,6 +3,7 @@ import MenuItem from '@components/MenuItem'; import MenuItemField from '@components/MenuItem/presets/MenuItemField'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -12,6 +13,7 @@ import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; import {CERTINIA_DIMENSION_PARAMS, getDimensionLabel, getDisplayTypeLabel, getParentTagMappingLabel} from '@pages/workspace/accounting/certinia/utils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -26,12 +28,14 @@ function CertiniaImportPage({policy}: WithPolicyConnectionsProps) { const styles = useThemeStyles(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const config = policy?.connections?.[CONST.POLICY.CONNECTIONS.NAME.CERTINIA]?.config; const coding = config?.coding; const hasPSA = !!config?.hasPSA; return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="CertiniaImportPage" headerTitle="workspace.accounting.import" accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]} diff --git a/src/pages/workspace/accounting/dualentry/advanced/DualEntryAdvancedPage.tsx b/src/pages/workspace/accounting/dualentry/advanced/DualEntryAdvancedPage.tsx index 31f0b589c4dd..4c3d95d80d0e 100644 --- a/src/pages/workspace/accounting/dualentry/advanced/DualEntryAdvancedPage.tsx +++ b/src/pages/workspace/accounting/dualentry/advanced/DualEntryAdvancedPage.tsx @@ -7,6 +7,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useCanConfigureCurrencyConversionFees from '@hooks/useCanConfigureCurrencyConversionFees'; import useExpensifyCardFeeds from '@hooks/useExpensifyCardFeeds'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -25,6 +26,7 @@ import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; import {getIsTravelBillingEnabled, getTravelBillingCardSettingsKey} from '@libs/TravelBillingUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -42,6 +44,7 @@ function DualEntryAdvancedPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const dualentryConfig = policy?.connections?.dualEntry?.config; const dualentryData = policy?.connections?.dualEntry?.data; const autoSync = dualentryConfig?.autoSync?.enabled ?? false; @@ -72,6 +75,7 @@ function DualEntryAdvancedPage({policy}: WithPolicyConnectionsProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="DualEntryAdvancedPage" headerTitle="workspace.accounting.advanced" accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]} diff --git a/src/pages/workspace/accounting/dualentry/export/DualEntryExportPage.tsx b/src/pages/workspace/accounting/dualentry/export/DualEntryExportPage.tsx index ef836006d27b..79f3970f9014 100644 --- a/src/pages/workspace/accounting/dualentry/export/DualEntryExportPage.tsx +++ b/src/pages/workspace/accounting/dualentry/export/DualEntryExportPage.tsx @@ -8,6 +8,7 @@ import Text from '@components/Text'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useCardFeeds from '@hooks/useCardFeeds'; import useCardsLists from '@hooks/useCardsLists'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -17,6 +18,7 @@ import {getLatestErrorField} from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -31,6 +33,7 @@ function DualEntryExportPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const [cardFeeds] = useCardFeeds(policyID); const [cardLists] = useCardsLists(); const policyOwner = policy?.owner; @@ -56,6 +59,7 @@ function DualEntryExportPage({policy}: WithPolicyConnectionsProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="DualEntryExportPage" headerTitle="workspace.accounting.export" accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]} diff --git a/src/pages/workspace/accounting/dualentry/import/DualEntryImportPage.tsx b/src/pages/workspace/accounting/dualentry/import/DualEntryImportPage.tsx index 1ae94ff7499b..f0c78422b749 100644 --- a/src/pages/workspace/accounting/dualentry/import/DualEntryImportPage.tsx +++ b/src/pages/workspace/accounting/dualentry/import/DualEntryImportPage.tsx @@ -1,13 +1,16 @@ import ConnectionLayout from '@components/ConnectionLayout'; import Text from '@components/Text'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import {clearDualEntryErrorField, updateDualEntryEnableNewCategories, updateDualEntryFieldMapping, updateDualEntrySyncTaxRates} from '@libs/actions/connections/DualEntry'; import {getLatestErrorField} from '@libs/ErrorUtils'; +import Navigation from '@libs/Navigation/Navigation'; import {settingsPendingAction} from '@libs/PolicyUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -21,6 +24,7 @@ function DualEntryImportPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const dualentryConfig = policy?.connections?.dualEntry?.config; const dualentryData = policy?.connections?.dualEntry?.data; const enableNewCategories = dualentryConfig?.enableNewCategories ?? false; @@ -29,6 +33,7 @@ function DualEntryImportPage({policy}: WithPolicyConnectionsProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="DualEntryImportPage" headerTitle="workspace.accounting.import" accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]} diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 61e9cc8b3939..d739c638074c 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -6,6 +6,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useCanConfigureCurrencyConversionFees from '@hooks/useCanConfigureCurrencyConversionFees'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -15,6 +16,7 @@ import {areSettingsInErrorFields, getCurrentSageIntacctEntityName, settingsPendi import createDynamicRoute from '@navigation/helpers/dynamicRoutesUtils/createDynamicRoute'; import Navigation from '@navigation/Navigation'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicy from '@pages/workspace/withPolicy'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -44,6 +46,7 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { const {translate} = useLocalize(); const canConfigureCurrencyConversionFees = useCanConfigureCurrencyConversionFees(policy); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const styles = useThemeStyles(); const {importEmployees, sync, pendingFields, errorFields} = policy?.connections?.intacct?.config ?? {}; @@ -108,7 +111,7 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { contentContainerStyle={styles.pb2} titleStyle={styles.ph5} connectionName={CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT} - onBackButtonPress={() => Navigation.goBack()} + onBackButtonPress={() => Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} > Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_AUTO_SYNC.path)))}> diff --git a/src/pages/workspace/accounting/intacct/import/SageIntacctImportPage.tsx b/src/pages/workspace/accounting/intacct/import/SageIntacctImportPage.tsx index 3623440c9bbf..4c99a0f0a93e 100644 --- a/src/pages/workspace/accounting/intacct/import/SageIntacctImportPage.tsx +++ b/src/pages/workspace/accounting/intacct/import/SageIntacctImportPage.tsx @@ -3,6 +3,7 @@ import MenuItem from '@components/MenuItem'; import MenuItemField from '@components/MenuItem/presets/MenuItemField'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -11,6 +12,7 @@ import {getLatestErrorField} from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, getCurrentSageIntacctEntityName, settingsPendingAction} from '@libs/PolicyUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicy from '@pages/workspace/withPolicy'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -51,6 +53,7 @@ function SageIntacctImportPage({policy}: WithPolicyProps) { const styles = useThemeStyles(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const sageIntacctConfig = policy?.connections?.intacct?.config; const sageIntacctData = policy?.connections?.intacct?.data; @@ -72,6 +75,7 @@ function SageIntacctImportPage({policy}: WithPolicyProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="SageIntacctImportPage" headerTitle="workspace.accounting.import" headerSubtitle={getCurrentSageIntacctEntityName(policy, translate('workspace.common.topLevel'))} diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx index 9c91f4f919f8..5c668f21de14 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx @@ -5,6 +5,7 @@ import MenuItemField from '@components/MenuItem/presets/MenuItemField'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useCanConfigureCurrencyConversionFees from '@hooks/useCanConfigureCurrencyConversionFees'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -30,6 +31,7 @@ import { shouldHideReimbursedReportsSection, shouldHideReportsExportTo, } from '@pages/workspace/accounting/netsuite/utils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -50,6 +52,7 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { const styles = useThemeStyles(); const canConfigureCurrencyConversionFees = useCanConfigureCurrencyConversionFees(policy); const policyID = policy?.id ?? CONST.DEFAULT_NUMBER_ID.toString(); + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const config = policy?.connections?.netsuite?.options?.config; const autoSyncConfig = policy?.connections?.netsuite?.config; @@ -284,6 +287,7 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="NetSuiteAdvancedPage" headerTitle="workspace.accounting.advanced" headerSubtitle={config?.subsidiary ?? ''} diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportPage.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportPage.tsx index e2b4880f73f9..15272dcdecf5 100644 --- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportPage.tsx +++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportPage.tsx @@ -4,6 +4,7 @@ import MenuItemField from '@components/MenuItem/presets/MenuItemField'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import usePermissions from '@hooks/usePermissions'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -15,6 +16,7 @@ import {canUseTaxNetSuite, getCustomersOrJobsLabelNetSuite, getNetSuiteImportCus import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; import {getImportCustomFieldsSettings} from '@pages/workspace/accounting/netsuite/utils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -32,12 +34,14 @@ function NetSuiteImportPage({policy}: WithPolicyConnectionsProps) { const {isBetaEnabled} = usePermissions(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const config = policy?.connections?.netsuite?.options?.config; const {subsidiaryList} = policy?.connections?.netsuite?.options?.data ?? {}; const selectedSubsidiary = useMemo(() => (subsidiaryList ?? []).find((subsidiary) => subsidiary.internalID === config?.subsidiaryID), [subsidiaryList, config?.subsidiaryID]); return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="NetSuiteImportPage" headerTitle="workspace.accounting.import" headerSubtitle={config?.subsidiary ?? ''} diff --git a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopImportPage.tsx b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopImportPage.tsx index 080d2da301b3..c4b5c44c6cf4 100644 --- a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopImportPage.tsx +++ b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopImportPage.tsx @@ -3,6 +3,7 @@ import MenuItem from '@components/MenuItem'; import MenuItemField from '@components/MenuItem/presets/MenuItemField'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -10,6 +11,7 @@ import * as PolicyUtils from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; @@ -29,6 +31,7 @@ function QuickbooksDesktopImportPage({policy}: WithPolicyProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id ?? '-1'; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const {mappings, pendingFields, errorFields} = policy?.connections?.quickbooksDesktop?.config ?? {}; const sections: QBDSectionType[] = [ @@ -68,7 +71,7 @@ function QuickbooksDesktopImportPage({policy}: WithPolicyProps) { contentContainerStyle={styles.pb2} titleStyle={styles.ph5} connectionName={CONST.POLICY.CONNECTIONS.NAME.QBD} - onBackButtonPress={() => Navigation.goBack()} + onBackButtonPress={() => Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} > {sections.map((section) => ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="QuickbooksAdvancedPage" headerTitle="workspace.accounting.advanced" accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]} diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx index a8b8595c95bb..8e0e488a99a9 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx @@ -3,6 +3,7 @@ import MenuItem from '@components/MenuItem'; import MenuItemField from '@components/MenuItem/presets/MenuItemField'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -13,6 +14,7 @@ import Navigation from '@navigation/Navigation'; import {shouldSwitchLocationsToReportFields} from '@pages/workspace/accounting/qbo/utils'; import {getQuickbooksOnlineIntegrationName, isIntuitEnterpriseSuiteConnection} from '@pages/workspace/accounting/utils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; @@ -34,6 +36,7 @@ function QuickbooksImportPage({policy}: WithPolicyProps) { const integrationName = getQuickbooksOnlineIntegrationName(policy, translate); const styles = useThemeStyles(); const policyID = policy?.id ?? '-1'; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const qboConfig = policy?.connections?.quickbooksOnline?.config; const {syncClasses, syncCustomers, syncLocations, syncItems, syncTax, syncCustomDimensions, pendingFields, errorFields} = qboConfig ?? {}; const isIntuitEnterpriseSuite = isIntuitEnterpriseSuiteConnection(policy); @@ -106,6 +109,7 @@ function QuickbooksImportPage({policy}: WithPolicyProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="QuickbooksImportPage" headerTitle="workspace.accounting.import" title="workspace.qbo.importDescription" diff --git a/src/pages/workspace/accounting/rillet/advanced/RilletAdvancedPage.tsx b/src/pages/workspace/accounting/rillet/advanced/RilletAdvancedPage.tsx index b4f2fb2248f4..68fa9671ae52 100644 --- a/src/pages/workspace/accounting/rillet/advanced/RilletAdvancedPage.tsx +++ b/src/pages/workspace/accounting/rillet/advanced/RilletAdvancedPage.tsx @@ -7,6 +7,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useCanConfigureCurrencyConversionFees from '@hooks/useCanConfigureCurrencyConversionFees'; import useExpensifyCardFeeds from '@hooks/useExpensifyCardFeeds'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -25,6 +26,7 @@ import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; import {getIsTravelBillingEnabled, getTravelBillingCardSettingsKey} from '@libs/TravelBillingUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -42,6 +44,7 @@ function RilletAdvancedPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const rilletConfig = policy?.connections?.rillet?.config; const rilletData = policy?.connections?.rillet?.data; const autoSync = rilletConfig?.autoSync?.enabled ?? true; @@ -71,6 +74,7 @@ function RilletAdvancedPage({policy}: WithPolicyConnectionsProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="RilletAdvancedPage" headerTitle="workspace.accounting.advanced" accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]} diff --git a/src/pages/workspace/accounting/rillet/export/RilletExportPage.tsx b/src/pages/workspace/accounting/rillet/export/RilletExportPage.tsx index a4ad95b60ae4..4f2182c02874 100644 --- a/src/pages/workspace/accounting/rillet/export/RilletExportPage.tsx +++ b/src/pages/workspace/accounting/rillet/export/RilletExportPage.tsx @@ -8,6 +8,7 @@ import Text from '@components/Text'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useCardFeeds from '@hooks/useCardFeeds'; import useCardsLists from '@hooks/useCardsLists'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -17,6 +18,7 @@ import {getLatestErrorField} from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -32,6 +34,7 @@ function RilletExportPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const [cardFeeds] = useCardFeeds(policyID); const [cardLists] = useCardsLists(); const policyOwner = policy?.owner; @@ -56,6 +59,7 @@ function RilletExportPage({policy}: WithPolicyConnectionsProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="RilletExportPage" headerTitle="workspace.accounting.export" accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]} diff --git a/src/pages/workspace/accounting/rillet/import/RilletImportPage.tsx b/src/pages/workspace/accounting/rillet/import/RilletImportPage.tsx index 8d88050ba609..a246e41caa3d 100644 --- a/src/pages/workspace/accounting/rillet/import/RilletImportPage.tsx +++ b/src/pages/workspace/accounting/rillet/import/RilletImportPage.tsx @@ -1,13 +1,16 @@ import ConnectionLayout from '@components/ConnectionLayout'; import Text from '@components/Text'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import {clearRilletErrorField, updateRilletEnableNewCategories, updateRilletFieldMapping, updateRilletSyncTaxRates} from '@libs/actions/connections/Rillet'; import {getLatestErrorField} from '@libs/ErrorUtils'; +import Navigation from '@libs/Navigation/Navigation'; import {settingsPendingAction} from '@libs/PolicyUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -21,6 +24,7 @@ function RilletImportPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const rilletConfig = policy?.connections?.rillet?.config; const rilletData = policy?.connections?.rillet?.data; const enableNewCategories = rilletConfig?.enableNewCategories ?? false; @@ -29,6 +33,7 @@ function RilletImportPage({policy}: WithPolicyConnectionsProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="RilletImportPage" headerTitle="workspace.accounting.import" accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]} diff --git a/src/pages/workspace/accounting/useConnectedAccountingIntegration.tsx b/src/pages/workspace/accounting/useConnectedAccountingIntegration.tsx index 6e65bd66bf51..0e0b442f15b9 100644 --- a/src/pages/workspace/accounting/useConnectedAccountingIntegration.tsx +++ b/src/pages/workspace/accounting/useConnectedAccountingIntegration.tsx @@ -64,8 +64,8 @@ type UseConnectedAccountingIntegrationOptions = { /** Style applied to the settings rows, which the Accounting page lays out as cards */ menuItemWrapperStyle?: StyleProp; - /** Runs once the user confirms disconnecting, before the connection is removed */ - onDisconnectConfirmed?: () => void; + /** Runs once the user confirms disconnecting and takes over calling `disconnect`, so the panel can close before the connection is removed */ + onDisconnectConfirmed?: (disconnect: () => void) => void; }; /** @@ -241,8 +241,12 @@ function useConnectedAccountingIntegration(policy: OnyxEntry, {menuItemW if (action !== ModalActions.CONFIRM || !connectedIntegration || !policyID) { return; } - onDisconnectConfirmed?.(); - removePolicyConnection(policy, connectedIntegration); + const disconnect = () => removePolicyConnection(policy, connectedIntegration); + if (onDisconnectConfirmed) { + onDisconnectConfirmed(disconnect); + return; + } + disconnect(); }); }, shouldCallAfterModalHide: true, diff --git a/src/pages/workspace/accounting/xero/XeroImportPage.tsx b/src/pages/workspace/accounting/xero/XeroImportPage.tsx index 819f94371c93..2480cf38eb6b 100644 --- a/src/pages/workspace/accounting/xero/XeroImportPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroImportPage.tsx @@ -4,6 +4,7 @@ import MenuItemField from '@components/MenuItem/presets/MenuItemField'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import Text from '@components/Text'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -11,6 +12,7 @@ import Navigation from '@libs/Navigation/Navigation'; import {getCurrentXeroOrganizationName} from '@libs/PolicyUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import withPolicy from '@pages/workspace/withPolicy'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; @@ -26,6 +28,7 @@ function XeroImportPage({policy}: WithPolicyProps) { const styles = useThemeStyles(); const policyID = policy?.id ?? '-1'; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const {importCustomers, importTaxRates, importTrackingCategories, pendingFields, errorFields} = policy?.connections?.xero?.config ?? {}; const currentXeroOrganizationName = useMemo(() => getCurrentXeroOrganizationName(policy ?? undefined), [policy]); @@ -67,6 +70,7 @@ function XeroImportPage({policy}: WithPolicyProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="XeroImportPage" headerTitle="workspace.accounting.import" headerSubtitle={currentXeroOrganizationName} diff --git a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx index ab0ff226bd49..7476bd10da6a 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx @@ -7,6 +7,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useCanConfigureCurrencyConversionFees from '@hooks/useCanConfigureCurrencyConversionFees'; +import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBetaEnabled'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -15,6 +16,7 @@ import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/crea import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, getCurrentXeroOrganizationName, settingsPendingAction} from '@libs/PolicyUtils'; +import {getAccountingSettingsRoute} from '@pages/workspace/connections/utils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -35,6 +37,7 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { const canConfigureCurrencyConversionFees = useCanConfigureCurrencyConversionFees(policy); const policyID = policy?.id; + const isUnifiedConnectionsBetaEnabled = useIsUnifiedConnectionsBetaEnabled(); const xeroConfig = policy?.connections?.xero?.config; const {pendingFields, errorFields, sync} = xeroConfig ?? {}; const {bankAccounts, expenseAccounts} = policy?.connections?.xero?.data ?? {}; @@ -63,6 +66,7 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { return ( Navigation.goBack(getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled, policyID))} displayName="XeroAdvancedPage" headerTitle="workspace.accounting.advanced" headerSubtitle={currentXeroOrganizationName} diff --git a/src/pages/workspace/connections/ConnectionsAccountingPage.tsx b/src/pages/workspace/connections/ConnectionsAccountingPage.tsx index a2a1a7f2bf2d..73f45a49a233 100644 --- a/src/pages/workspace/connections/ConnectionsAccountingPage.tsx +++ b/src/pages/workspace/connections/ConnectionsAccountingPage.tsx @@ -53,7 +53,7 @@ function ConnectionsAccountingPage({policy}: PolicyAccountingPageProps) { oldDotPolicyConnectionsURL, } = useConnectedAccountingIntegration(policy, { // These settings have nothing to show once the integration is gone - onDisconnectConfirmed: () => Navigation.goBack(ROUTES.WORKSPACE_CONNECTIONS.getRoute(policyID)), + onDisconnectConfirmed: (disconnect) => Navigation.goBack(ROUTES.WORKSPACE_CONNECTIONS.getRoute(policyID), {afterTransition: disconnect}), }); const connectionsMenuItems = connectionDetails?.settingsMenuItems ?? []; diff --git a/src/pages/workspace/connections/ConnectionsMergePageBase.tsx b/src/pages/workspace/connections/ConnectionsMergePageBase.tsx index 6d9d785f3bb2..77565ccd0547 100644 --- a/src/pages/workspace/connections/ConnectionsMergePageBase.tsx +++ b/src/pages/workspace/connections/ConnectionsMergePageBase.tsx @@ -114,7 +114,7 @@ function ConnectionsMergePageBaseContent({policyID, category, cards}: Connection card={connectedCard} policy={policy} handleConnect={() => handleReconnect(connectedCard)} - onDisconnect={() => Navigation.goBack(ROUTES.WORKSPACE_CONNECTIONS.getRoute(policyID))} + onDisconnect={(disconnect) => Navigation.goBack(ROUTES.WORKSPACE_CONNECTIONS.getRoute(policyID), {afterTransition: disconnect})} onBackButtonPress={() => Navigation.goBack(ROUTES.WORKSPACE_CONNECTIONS.getRoute(policyID))} canWriteMoreFeatures={canWriteMoreFeatures} showReadOnlyModal={showReadOnlyModal} diff --git a/src/pages/workspace/connections/ConnectionsMergeProviderCard.tsx b/src/pages/workspace/connections/ConnectionsMergeProviderCard.tsx index f5c53f726f37..09d904901708 100644 --- a/src/pages/workspace/connections/ConnectionsMergeProviderCard.tsx +++ b/src/pages/workspace/connections/ConnectionsMergeProviderCard.tsx @@ -35,8 +35,8 @@ type ConnectionsMergeProviderCardProps = { /** Callback invoked when the user taps the "Connect" or "Reconnect" button. */ handleConnect: () => void; - /** Called once the user confirms disconnecting, right before the connection is removed */ - onDisconnect?: () => void; + /** Called once the user confirms disconnecting and takes over calling `disconnect` */ + onDisconnect?: (disconnect: () => void) => void; /** Called when the header's back button is pressed. */ onBackButtonPress: () => void; diff --git a/src/pages/workspace/connections/ConnectionsReceiptPartnersPage.tsx b/src/pages/workspace/connections/ConnectionsReceiptPartnersPage.tsx index 5024beb810e2..56e25c7d6f53 100644 --- a/src/pages/workspace/connections/ConnectionsReceiptPartnersPage.tsx +++ b/src/pages/workspace/connections/ConnectionsReceiptPartnersPage.tsx @@ -56,7 +56,7 @@ function ConnectionsReceiptPartnersPage({route}: ConnectionsReceiptPartnersPageP getOverflowMenu, } = useReceiptPartnersSettings(policyID, { // These settings have nothing to show once Uber is disconnected - onDisconnectConfirmed: () => Navigation.goBack(ROUTES.WORKSPACE_CONNECTIONS.getRoute(policyID)), + onDisconnectConfirmed: (disconnect) => Navigation.goBack(ROUTES.WORKSPACE_CONNECTIONS.getRoute(policyID), {afterTransition: disconnect}), }); useWorkspaceDocumentTitle(policy?.name, 'workspace.common.receiptPartners'); const isLoading = policy?.isLoading; diff --git a/src/pages/workspace/connections/WorkspaceConnectionsPage.tsx b/src/pages/workspace/connections/WorkspaceConnectionsPage.tsx index ea73b8b996d4..be3e2eb8eea6 100644 --- a/src/pages/workspace/connections/WorkspaceConnectionsPage.tsx +++ b/src/pages/workspace/connections/WorkspaceConnectionsPage.tsx @@ -22,7 +22,6 @@ import useIsUnifiedConnectionsBetaEnabled from '@hooks/useIsUnifiedConnectionsBe import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; -import useOnyx from '@hooks/useOnyx'; import useOpenConciergeAnywhere from '@hooks/useOpenConciergeAnywhere'; import usePermissions from '@hooks/usePermissions'; import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess'; @@ -32,7 +31,7 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWorkspaceDocumentTitle from '@hooks/useWorkspaceDocumentTitle'; -import {openPolicyHRPage, openPolicyRecruitingPage} from '@libs/actions/PolicyConnections'; +import {openPolicyAccountingPage, openPolicyHRPage, openPolicyRecruitingPage} from '@libs/actions/PolicyConnections'; import Navigation from '@libs/Navigation/Navigation'; import {isControlPolicy} from '@libs/PolicyUtils'; import tokenizedSearch from '@libs/tokenizedSearch'; @@ -50,12 +49,8 @@ import variables from '@styles/variables'; import {openPolicyReceiptPartnersPage} from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import type {Account} from '@src/types/onyx'; import type {ConnectionName} from '@src/types/onyx/Policy'; -import type {OnyxEntry} from 'react-native-onyx'; - import {useFocusEffect, useRoute} from '@react-navigation/native'; import React, {useEffect, useRef, useState} from 'react'; import {View} from 'react-native'; @@ -82,15 +77,17 @@ type MergeSetupFlow = { key: number; }; -/** HR and recruiting providers are Control-only, so their data is only requested for Control workspaces */ -const accountManagerReportIDSelector = (account: OnyxEntry) => (account?.accountManagerAccountID ? account.accountManagerReportID : undefined); - +/** + * HR and recruiting providers are Control-only, so their data is only requested for Control workspaces. Other workspaces + * fetch the accounting data here instead, so connecting an integration doesn't replace the page with a loader. + */ function fetchConnectionsData(policyID: string | undefined, canUseMergeConnections: boolean, isRecruitingBetaEnabled: boolean) { if (!policyID) { return; } openPolicyReceiptPartnersPage(policyID); if (!canUseMergeConnections) { + openPolicyAccountingPage(policyID); return; } openPolicyHRPage(policyID); @@ -111,7 +108,6 @@ function WorkspaceConnectionsPage({policy}: WithPolicyConnectionsProps) { const [isSearchFocused, setIsSearchFocused] = useState(false); const {isBetaEnabled} = usePermissions(); const {openConciergeAnywhere} = useOpenConciergeAnywhere(); - const [accountManagerReportID] = useOnyx(ONYXKEYS.ACCOUNT, {selector: accountManagerReportIDSelector}); const {startIntegrationFlow} = useAccountingActions(); const {canWrite: canWriteAccounting} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.ACCOUNTING); const [lastSelectedTab, setLastSelectedTab] = useState(CONST.TAB.CONNECTIONS.ALL); @@ -160,18 +156,7 @@ function WorkspaceConnectionsPage({policy}: WithPolicyConnectionsProps) { // A tab also ends up empty once everything in it is connected const shouldShowEmptyState = !visibleListings.length; - // Suggestions go to the person who looks after this workspace, like the old Accounting page did - const openSuggestIntegration = () => { - if (policy?.chatReportIDAdmins) { - openConciergeAnywhere({reportID: String(policy.chatReportIDAdmins)}); - return; - } - if (accountManagerReportID) { - openConciergeAnywhere({reportID: accountManagerReportID}); - return; - } - openConciergeAnywhere({forceConcierge: true}); - }; + const openSuggestIntegration = () => openConciergeAnywhere({forceConcierge: true}); // Upgrade and setup flows that leave the app come back here with the integration to connect in the route params. // `startIntegrationFlow` changes identity whenever `policy` does, and the params are only cleared in a later render, diff --git a/src/pages/workspace/connections/utils.ts b/src/pages/workspace/connections/utils.ts index 225087142eaa..eba5318849b9 100644 --- a/src/pages/workspace/connections/utils.ts +++ b/src/pages/workspace/connections/utils.ts @@ -53,7 +53,7 @@ function getAccountingConnectionsRoute(isUnifiedConnectionsBetaEnabled: boolean, } /** The page an accounting integration's settings open from, which is the Connections accounting panel while the unified Connections beta is on */ -function getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled: boolean, policyID: string) { +function getAccountingSettingsRoute(isUnifiedConnectionsBetaEnabled: boolean, policyID: string | undefined) { if (isUnifiedConnectionsBetaEnabled) { return ROUTES.WORKSPACE_CONNECTIONS_ACCOUNTING.getRoute(policyID); } diff --git a/src/pages/workspace/merge/useMergeProviderCardDetails.tsx b/src/pages/workspace/merge/useMergeProviderCardDetails.tsx index e9300582f215..831157a088a6 100644 --- a/src/pages/workspace/merge/useMergeProviderCardDetails.tsx +++ b/src/pages/workspace/merge/useMergeProviderCardDetails.tsx @@ -28,8 +28,8 @@ type UseMergeProviderCardDetailsParams = { canWriteMoreFeatures: boolean; showReadOnlyModal: () => void; - /** Runs once the user confirms disconnecting, before the connection is removed */ - onDisconnect?: () => void; + /** Runs once the user confirms disconnecting and takes over calling `disconnect`, so the panel can close before the connection is removed */ + onDisconnect?: (disconnect: () => void) => void; }; /** The status text, sync error and overflow menu of a Merge provider, shared by the HR and Recruiting cards and their Connections panel */ @@ -148,8 +148,12 @@ function useMergeProviderCardDetails({card, policy, handleConnect, canWriteMoreF if (result?.action !== ModalActions.CONFIRM || !policy) { return; } - onDisconnect?.(); - removePolicyConnection(policy, card.connectionName); + const disconnect = () => removePolicyConnection(policy, card.connectionName); + if (onDisconnect) { + onDisconnect(disconnect); + return; + } + disconnect(); }); }, shouldCallAfterModalHide: true, diff --git a/src/pages/workspace/receiptPartners/useReceiptPartnersSettings.ts b/src/pages/workspace/receiptPartners/useReceiptPartnersSettings.ts index 278d2114752b..8198698fb49f 100644 --- a/src/pages/workspace/receiptPartners/useReceiptPartnersSettings.ts +++ b/src/pages/workspace/receiptPartners/useReceiptPartnersSettings.ts @@ -19,8 +19,8 @@ import type {ValueOf} from 'type-fest'; import {useEffect} from 'react'; type UseReceiptPartnersSettingsOptions = { - /** Runs once the user confirms disconnecting, before the connection is removed */ - onDisconnectConfirmed?: () => void; + /** Runs once the user confirms disconnecting and takes over calling `disconnect`, so the panel can close before the connection is removed */ + onDisconnectConfirmed?: (disconnect: () => void) => void; }; /** State and actions for the workspace's receipt partner connections, shared by the Receipt partners page and its Connections panel */ @@ -107,8 +107,12 @@ function useReceiptPartnersSettings(policyID: string, {onDisconnectConfirmed}: U if (action !== ModalActions.CONFIRM) { return; } - onDisconnectConfirmed?.(); - disconnectPartner(CONST.POLICY.RECEIPT_PARTNERS.NAME.UBER); + const disconnect = () => disconnectPartner(CONST.POLICY.RECEIPT_PARTNERS.NAME.UBER); + if (onDisconnectConfirmed) { + onDisconnectConfirmed(disconnect); + return; + } + disconnect(); }); }, shouldCallAfterModalHide: true, diff --git a/tests/actions/PolicyTest.ts b/tests/actions/PolicyTest.ts index ecfce48824e5..c92e4b0260c6 100644 --- a/tests/actions/PolicyTest.ts +++ b/tests/actions/PolicyTest.ts @@ -5861,6 +5861,39 @@ describe('actions/Policy', () => { expect(apiWriteSpy).not.toHaveBeenCalled(); apiWriteSpy.mockRestore(); }); + + it('should mark the connections as fetched when it turns Connections on for a workspace that is still being created', async () => { + // Given a workspace whose create request hasn't finished, so it can't have connections yet + const policy: PolicyType = { + ...createRandomPolicy(20, CONST.POLICY.TYPE.CORPORATE), + areConnectionsEnabled: false, + connections: undefined, + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }; + await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); + + // When connecting an integration from the Connections page turns Connections on + Policy.enablePolicyFeatureForConnection(policy, CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED); + await waitForBatchedUpdates(); + + // Then the open Connections page has nothing to fetch, so it keeps showing instead of a loader + expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.POLICY_HAS_CONNECTIONS_DATA_BEEN_FETCHED}${policy.id}`)).toBe(true); + expect((await getOnyxValue(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`))?.areConnectionsEnabled).toBe(true); + }); + + it('should leave the connections to be fetched for an existing workspace', async () => { + // Given an existing workspace with Connections off, which can still hold connections that haven't loaded, + // like an integration only supported on OldDot + const policy: PolicyType = {...createRandomPolicy(21, CONST.POLICY.TYPE.CORPORATE), areConnectionsEnabled: false, connections: undefined, pendingAction: undefined}; + await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); + + // When connecting an integration from the Connections page turns Connections on + Policy.enablePolicyFeatureForConnection(policy, CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED); + await waitForBatchedUpdates(); + + // Then the connections are not marked as fetched, so the page still loads any that exist + expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.POLICY_HAS_CONNECTIONS_DATA_BEEN_FETCHED}${policy.id}`)).toBeUndefined(); + }); }); describe('enablePolicyTaxes', () => { diff --git a/tests/unit/AccountingConnectionConfirmationTest.tsx b/tests/unit/AccountingConnectionConfirmationTest.tsx index eaa05033e0a0..b592efb347ad 100644 --- a/tests/unit/AccountingConnectionConfirmationTest.tsx +++ b/tests/unit/AccountingConnectionConfirmationTest.tsx @@ -53,6 +53,7 @@ jest.mock('@libs/actions/connections', () => ({ jest.mock('@libs/PolicyUtils', () => ({ __esModule: true, isControlPolicy: () => true, + isPolicyFeatureEnabled: (policyToCheck: Policy | undefined) => !!policyToCheck?.areConnectionsEnabled, tryNavigateToSubmitWorkspaceUpgrade: () => false, })); @@ -380,5 +381,43 @@ describe('AccountingContextProvider connect-confirmation prompt', () => { // Then the feature is turned on without navigating away, so the integration can be used once it connects expect(mockEnablePolicyFeatureForConnection).toHaveBeenCalledWith(POLICY_ID, CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED); }); + + it('should open the setup flow a frame after turning the Accounting feature on', async () => { + // Given a workspace with the Accounting feature off + const ref = renderProvider({...policy, areConnectionsEnabled: false}); + + // When a connect flow is started + act(() => { + ref.current?.startIntegrationFlow({name: CONST.POLICY.CONNECTIONS.NAME.QBO}); + }); + + // Then the setup flow waits, because its pages redirect to More features if they render before the feature is on + expect(mockEnablePolicyFeatureForConnection).toHaveBeenCalledWith(POLICY_ID, CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED); + expect(screen.queryByTestId(SETUP_FLOW_TEST_ID)).not.toBeOnTheScreen(); + + // When the next frame runs + await act(async () => { + await new Promise((resolve) => { + requestAnimationFrame(resolve); + }); + }); + + // Then the setup flow opens + expect(screen.getByTestId(SETUP_FLOW_TEST_ID)).toBeOnTheScreen(); + }); + + it('should open the setup flow right away when the Accounting feature is already on', () => { + // Given a workspace with the Accounting feature already on + const ref = renderProvider({...policy, areConnectionsEnabled: true}); + + // When a connect flow is started + act(() => { + ref.current?.startIntegrationFlow({name: CONST.POLICY.CONNECTIONS.NAME.QBO}); + }); + + // Then setup opens without waiting a frame, because there is nothing to turn on first + expect(mockEnablePolicyFeatureForConnection).not.toHaveBeenCalled(); + expect(screen.getByTestId(SETUP_FLOW_TEST_ID)).toBeOnTheScreen(); + }); }); }); diff --git a/tests/unit/WorkspaceConnectionsPageAutoStartFlowTest.tsx b/tests/unit/WorkspaceConnectionsPageAutoStartFlowTest.tsx index c4dec08dde9f..ae56b376e691 100644 --- a/tests/unit/WorkspaceConnectionsPageAutoStartFlowTest.tsx +++ b/tests/unit/WorkspaceConnectionsPageAutoStartFlowTest.tsx @@ -1,5 +1,6 @@ import {render} from '@testing-library/react-native'; +import {openPolicyAccountingPage, openPolicyHRPage} from '@libs/actions/PolicyConnections'; import Navigation from '@libs/Navigation/Navigation'; import WorkspaceConnectionsPage from '@pages/workspace/connections/WorkspaceConnectionsPage'; @@ -101,14 +102,15 @@ jest.mock('@pages/workspace/connections/useAccountingConnectionListings', () => jest.mock('@pages/workspace/connections/useMergeConnectionListings', () => ({__esModule: true, default: () => []})); jest.mock('@pages/workspace/connections/useReceiptPartnerConnectionListings', () => ({__esModule: true, default: () => []})); jest.mock('@pages/workspace/connections/useMCPConnectionListings', () => ({__esModule: true, default: () => []})); -jest.mock('@libs/actions/PolicyConnections', () => ({openPolicyHRPage: jest.fn(), openPolicyRecruitingPage: jest.fn()})); +jest.mock('@libs/actions/PolicyConnections', () => ({openPolicyAccountingPage: jest.fn(), openPolicyHRPage: jest.fn(), openPolicyRecruitingPage: jest.fn()})); jest.mock('@userActions/Policy/Policy', () => ({openPolicyReceiptPartnersPage: jest.fn()})); +let mockIsControlPolicy = true; jest.mock('@libs/PolicyUtils', () => { const actual = jest.requireActual>('@libs/PolicyUtils'); return { ...actual, - isControlPolicy: () => true, + isControlPolicy: () => mockIsControlPolicy, }; }); @@ -184,3 +186,35 @@ describe('WorkspaceConnectionsPage auto-started connect flow', () => { expect(mockStartIntegrationFlow).toHaveBeenCalledTimes(2); }); }); +describe('WorkspaceConnectionsPage data fetched on open', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockRouteParams = {}; + mockIsControlPolicy = true; + }); + + it('should fetch the accounting data for a workspace that is not on Control', async () => { + // Given a Collect workspace, which has no HR request to set the connections fetched flag + mockIsControlPolicy = false; + + // When the page opens + render(); + await waitForBatchedUpdates(); + + // Then the accounting data is fetched up front, so connecting an integration later doesn't swap the page for a loader + expect(openPolicyAccountingPage).toHaveBeenCalledWith(POLICY_ID); + expect(openPolicyHRPage).not.toHaveBeenCalled(); + }); + + it('should fetch the HR data instead for a Control workspace', async () => { + // Given a Control workspace, whose HR request already sets the connections fetched flag + + // When the page opens + render(); + await waitForBatchedUpdates(); + + // Then only the HR data is fetched, so the page doesn't send a second request for the same flag + expect(openPolicyHRPage).toHaveBeenCalledWith(POLICY_ID); + expect(openPolicyAccountingPage).not.toHaveBeenCalled(); + }); +});