From 740484c622ae1f56393c372741106b1af1d197dc Mon Sep 17 00:00:00 2001 From: daledah Date: Sat, 7 Sep 2024 15:46:44 +0700 Subject: [PATCH 1/4] fix: show an error for integrations that aren't configurable via NewDot --- src/languages/en.ts | 2 + src/languages/es.ts | 2 + src/libs/PolicyUtils.ts | 5 ++ .../accounting/PolicyAccountingPage.tsx | 59 ++++++++++++++----- 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 7a745bbd00c0..6865887afb70 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -3272,6 +3272,8 @@ export default { } } }, + errorODIntegration: "There's an error with a connection that's been set up in Expensify Classic. ", + goToODToFix: 'Go to Expensiy Classic to fix this issue.', setup: 'Connect', lastSync: (relativeDate: string) => `Last synced ${relativeDate}`, import: 'Import', diff --git a/src/languages/es.ts b/src/languages/es.ts index ecdd1f5f4c04..95e76c3923f7 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -3256,6 +3256,8 @@ export default { } } }, + errorODIntegration: 'Hay un error con una conexión que se ha configurado en Expensify Classic. ', + goToODToFix: 'Ve a Expensify Classic para solucionar este problema.', setup: 'Configurar', lastSync: (relativeDate: string) => `Recién sincronizado ${relativeDate}`, import: 'Importar', diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index f9acb67a1efb..0474105e708f 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -945,6 +945,10 @@ function hasIntegrationAutoSync(policy: Policy | undefined, connectedIntegration return (connectedIntegration && policy?.connections?.[connectedIntegration]?.config?.autoSync?.enabled) ?? false; } +function hasUnsupportedIntegration(policy: Policy | undefined, accountingIntegrations?: ConnectionName[]) { + return !(accountingIntegrations ?? Object.values(CONST.POLICY.CONNECTIONS.NAME)).some((integration) => !!policy?.connections?.[integration]); +} + function getCurrentConnectionName(policy: Policy | undefined): string | undefined { const accountingIntegrations = Object.values(CONST.POLICY.CONNECTIONS.NAME); const connectionKey = accountingIntegrations.find((integration) => !!policy?.connections?.[integration]); @@ -1093,6 +1097,7 @@ export { getAllTaxRatesNamesAndKeys as getAllTaxRates, getTagNamesFromTagsLists, getDomainNameForPolicy, + hasUnsupportedIntegration, }; export type {MemberEmailsToAccountIDs}; diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index c125052c6935..161083d81d71 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -4,6 +4,7 @@ import {useOnyx} from 'react-native-onyx'; import Button from '@components/Button'; import CollapsibleSection from '@components/CollapsibleSection'; import ConfirmModal from '@components/ConfirmModal'; +import FormHelpMessage from '@components/FormHelpMessage'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; import * as Illustrations from '@components/Icon/Illustrations'; @@ -13,6 +14,8 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; import Section from '@components/Section'; +import Text from '@components/Text'; +import TextLink from '@components/TextLink'; import ThreeDotsMenu from '@components/ThreeDotsMenu'; import type ThreeDotsMenuProps from '@components/ThreeDotsMenu/types'; import useLocalize from '@hooks/useLocalize'; @@ -23,6 +26,7 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import {isAuthenticationError, isConnectionInProgress, isConnectionUnverified, removePolicyConnection, syncConnection} from '@libs/actions/connections'; +import * as PolicyUtils from '@libs/PolicyUtils'; import { areSettingsInErrorFields, findCurrentXeroOrganization, @@ -37,6 +41,7 @@ import Navigation from '@navigation/Navigation'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {AnchorPosition} from '@styles/index'; +import * as Link from '@userActions/Link'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -78,6 +83,9 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { connectedIntegration === connectionSyncProgress?.connectionName ? connectionSyncProgress : undefined, ); + const hasSyncError = PolicyUtils.hasSyncError(policy, isSyncInProgress); + const hasUnsupportedNDIntegration = PolicyUtils.hasUnsupportedIntegration(policy, accountingIntegrations); + const tenants = useMemo(() => getXeroTenants(policy), [policy]); const currentXeroOrganization = findCurrentXeroOrganization(tenants, policy?.connections?.xero?.config?.tenantID); @@ -339,7 +347,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { ]); const otherIntegrationsItems = useMemo(() => { - if (isEmptyObject(policy?.connections) && !isSyncInProgress) { + if (isEmptyObject(policy?.connections) && !isSyncInProgress && !(hasUnsupportedNDIntegration && hasSyncError)) { return; } const otherIntegrations = accountingIntegrations.filter( @@ -390,6 +398,8 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { isOffline, startIntegrationFlow, popoverAnchorRefs, + hasUnsupportedNDIntegration, + hasSyncError, ]); return ( @@ -419,20 +429,41 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { titleStyles={styles.accountSettingsSectionTitle} childrenStyles={styles.pt5} > - {connectionsMenuItems.map((menuItem) => ( - - ( + - - ))} + shouldDisableStrikeThrough + > + + + ))} + {hasUnsupportedNDIntegration && hasSyncError && ( + + {translate('workspace.accounting.errorODIntegration')} + { + // Go to Expensify Classic. + Link.openOldDotLink(CONST.OLDDOT_URLS.INBOX); + }} + > + {translate('workspace.accounting.goToODToFix')} + + + } + style={styles.menuItemError} + /> + )} {otherIntegrationsItems && ( Date: Mon, 9 Sep 2024 18:09:56 +0700 Subject: [PATCH 2/4] fix: use children instead of message --- .../accounting/PolicyAccountingPage.tsx | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index 65d07dca1952..b137cc892627 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -477,21 +477,20 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { - {translate('workspace.accounting.errorODIntegration')} - { - // Go to Expensify Classic. - Link.openOldDotLink(CONST.OLDDOT_URLS.INBOX); - }} - > - {translate('workspace.accounting.goToODToFix')} - - - } style={styles.menuItemError} - /> + > + + {translate('workspace.accounting.errorODIntegration')} + { + // Go to Expensify Classic. + Link.openOldDotLink(CONST.OLDDOT_URLS.INBOX); + }} + > + {translate('workspace.accounting.goToODToFix')} + + + )} {otherIntegrationsItems && ( Date: Tue, 10 Sep 2024 18:46:34 +0700 Subject: [PATCH 3/4] feat: go to policy page in OD --- src/pages/workspace/accounting/PolicyAccountingPage.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index b137cc892627..7ff943f09992 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -484,7 +484,8 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { { // Go to Expensify Classic. - Link.openOldDotLink(CONST.OLDDOT_URLS.INBOX); + const policyURL = `policy?param={"policyID":"${policyID}"}`; + Link.openOldDotLink(policyURL); }} > {translate('workspace.accounting.goToODToFix')} From b6460f300e8790673765d679ad74f3f048682a6b Mon Sep 17 00:00:00 2001 From: daledah Date: Mon, 16 Sep 2024 14:14:48 +0700 Subject: [PATCH 4/4] refactor: update build olddot url to handle anchors --- src/CONST.ts | 1 + src/libs/actions/Link.ts | 11 +++++++++-- .../workspace/accounting/PolicyAccountingPage.tsx | 3 +-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index d0695b1e285f..6167d92514d3 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -722,6 +722,7 @@ const CONST = { ADMIN_POLICIES_URL: 'admin_policies', ADMIN_DOMAINS_URL: 'admin_domains', INBOX: 'inbox', + POLICY_CONNECTIONS_URL: (policyID: string) => `policy?param={"policyID":"${policyID}"}#connections`, }, EXPENSIFY_POLICY_DOMAIN: 'expensify-policy', diff --git a/src/libs/actions/Link.ts b/src/libs/actions/Link.ts index 50a4582dffc1..886f8b06fc6f 100644 --- a/src/libs/actions/Link.ts +++ b/src/libs/actions/Link.ts @@ -39,8 +39,15 @@ Onyx.connect({ }); function buildOldDotURL(url: string, shortLivedAuthToken?: string): Promise { - const hasHashParams = url.indexOf('#') !== -1; + const hashIndex = url.lastIndexOf('#'); + const hasHashParams = hashIndex !== -1; const hasURLParams = url.indexOf('?') !== -1; + let originURL = url; + let hashParams = ''; + if (hasHashParams) { + originURL = url.substring(0, hashIndex); + hashParams = url.substring(hashIndex); + } const authTokenParam = shortLivedAuthToken ? `authToken=${shortLivedAuthToken}` : ''; const emailParam = `email=${encodeURIComponent(currentUserEmail)}`; @@ -51,7 +58,7 @@ function buildOldDotURL(url: string, shortLivedAuthToken?: string): Promise { // Go to Expensify Classic. - const policyURL = `policy?param={"policyID":"${policyID}"}`; - Link.openOldDotLink(policyURL); + Link.openOldDotLink(CONST.OLDDOT_URLS.POLICY_CONNECTIONS_URL(policyID)); }} > {translate('workspace.accounting.goToODToFix')}