Skip to content

Commit

Permalink
Merge pull request Expensify#48759 from daledah/fix/47797
Browse files Browse the repository at this point in the history
fix: show an error for integrations that aren't configurable via NewDot
  • Loading branch information
puneetlath authored Sep 17, 2024
2 parents 7674e83 + b6460f3 commit f0f5f94
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,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,
Expand Down
2 changes: 2 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3351,6 +3351,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',
Expand Down
2 changes: 2 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3333,6 +3333,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',
Expand Down
5 changes: 5 additions & 0 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,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]);
Expand Down Expand Up @@ -1104,6 +1108,7 @@ export {
getAllTaxRatesNamesAndKeys as getAllTaxRates,
getTagNamesFromTagsLists,
getDomainNameForPolicy,
hasUnsupportedIntegration,
getWorkflowApprovalsUnavailable,
};

Expand Down
11 changes: 9 additions & 2 deletions src/libs/actions/Link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,15 @@ Onyx.connect({
});

function buildOldDotURL(url: string, shortLivedAuthToken?: string): Promise<string> {
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)}`;
Expand All @@ -51,7 +58,7 @@ function buildOldDotURL(url: string, shortLivedAuthToken?: string): Promise<stri
const oldDotDomain = Url.addTrailingForwardSlash(environmentURL);

// If the URL contains # or ?, we can assume they don't need to have the `?` token to start listing url parameters.
return `${oldDotDomain}${url}${hasHashParams || hasURLParams ? '&' : '?'}${params}`;
return `${oldDotDomain}${originURL}${hasURLParams ? '&' : '?'}${params}${hashParams}`;
});
}

Expand Down
58 changes: 44 additions & 14 deletions src/pages/workspace/accounting/PolicyAccountingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,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';
Expand All @@ -14,6 +15,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';
Expand All @@ -24,6 +27,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,
Expand All @@ -39,6 +43,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';
Expand Down Expand Up @@ -93,6 +98,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);

Expand Down Expand Up @@ -372,7 +380,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(
Expand Down Expand Up @@ -423,6 +431,8 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) {
isOffline,
startIntegrationFlow,
popoverAnchorRefs,
hasUnsupportedNDIntegration,
hasSyncError,
]);

return (
Expand Down Expand Up @@ -452,20 +462,40 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) {
titleStyles={styles.accountSettingsSectionTitle}
childrenStyles={styles.pt5}
>
{connectionsMenuItems.map((menuItem) => (
<OfflineWithFeedback
pendingAction={menuItem.pendingAction}
key={menuItem.title}
shouldDisableStrikeThrough
>
<MenuItem
brickRoadIndicator={menuItem.brickRoadIndicator}
{!(hasUnsupportedNDIntegration && hasSyncError) &&
connectionsMenuItems.map((menuItem) => (
<OfflineWithFeedback
pendingAction={menuItem.pendingAction}
key={menuItem.title}
// eslint-disable-next-line react/jsx-props-no-spreading
{...menuItem}
/>
</OfflineWithFeedback>
))}
shouldDisableStrikeThrough
>
<MenuItem
brickRoadIndicator={menuItem.brickRoadIndicator}
key={menuItem.title}
// eslint-disable-next-line react/jsx-props-no-spreading
{...menuItem}
/>
</OfflineWithFeedback>
))}
{hasUnsupportedNDIntegration && hasSyncError && (
<FormHelpMessage
isError
shouldShowRedDotIndicator
style={styles.menuItemError}
>
<Text style={[{color: theme.textError}]}>
{translate('workspace.accounting.errorODIntegration')}
<TextLink
onPress={() => {
// Go to Expensify Classic.
Link.openOldDotLink(CONST.OLDDOT_URLS.POLICY_CONNECTIONS_URL(policyID));
}}
>
{translate('workspace.accounting.goToODToFix')}
</TextLink>
</Text>
</FormHelpMessage>
)}
{otherIntegrationsItems && (
<CollapsibleSection
title={translate('workspace.accounting.other')}
Expand Down

0 comments on commit f0f5f94

Please sign in to comment.