Skip to content

Commit

Permalink
Merge pull request #55286 from callstack-internal/VickyStash/bugfix/5…
Browse files Browse the repository at this point in the history
…5103-broken-connection-error-display

Fix broken feed connection error display on the Company Cards page
  • Loading branch information
mountiny authored Jan 27, 2025
2 parents ba27d00 + d3d365d commit 9cadcd2
Show file tree
Hide file tree
Showing 18 changed files with 204 additions and 138 deletions.
9 changes: 9 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,15 @@ const ROUTES = {
return `settings/workspaces/${policyID}/company-cards` as const;
},
},
WORKSPACE_COMPANY_CARDS_BANK_CONNECTION: {
route: 'settings/workspaces/:policyID/company-cards/:bankName/bank-connection',
getRoute: (policyID: string | undefined, bankName: string, backTo: string) => {
if (!policyID) {
Log.warn('Invalid policyID is used to build the WORKSPACE_COMPANY_CARDS_BANK_CONNECTION route');
}
return getUrlWithBackToParam(`settings/workspaces/${policyID}/company-cards/${bankName}/bank-connection`, backTo);
},
},
WORKSPACE_COMPANY_CARDS_ADD_NEW: {
route: 'settings/workspaces/:policyID/company-cards/add-card-feed',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/company-cards/add-card-feed` as const,
Expand Down
1 change: 1 addition & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ const SCREENS = {
COMPANY_CARDS: 'Workspace_CompanyCards',
COMPANY_CARDS_ASSIGN_CARD: 'Workspace_CompanyCards_AssignCard',
COMPANY_CARDS_SELECT_FEED: 'Workspace_CompanyCards_Select_Feed',
COMPANY_CARDS_BANK_CONNECTION: 'Workspace_CompanyCards_BankConnection',
COMPANY_CARDS_ADD_NEW: 'Workspace_CompanyCards_New',
COMPANY_CARDS_TYPE: 'Workspace_CompanyCards_Type',
COMPANY_CARDS_INSTRUCTIONS: 'Workspace_CompanyCards_Instructions',
Expand Down
30 changes: 4 additions & 26 deletions src/components/DotIndicatorMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import {isReceiptError} from '@libs/ErrorUtils';
import fileDownload from '@libs/fileDownload';
import * as Localize from '@libs/Localize';
import CONST from '@src/CONST';
import {translateLocal} from '@libs/Localize';
import type {ReceiptError} from '@src/types/onyx/Transaction';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
Expand Down Expand Up @@ -61,38 +60,17 @@ function DotIndicatorMessage({messages = {}, style, type, textStyles}: DotIndica
key={index}
style={styles.offlineFeedback.text}
>
<Text style={[StyleUtils.getDotIndicatorTextStyles(isErrorMessage)]}>{Localize.translateLocal('iou.error.receiptFailureMessage')}</Text>
<Text style={[StyleUtils.getDotIndicatorTextStyles(isErrorMessage)]}>{translateLocal('iou.error.receiptFailureMessage')}</Text>
<TextLink
style={[StyleUtils.getDotIndicatorTextStyles(), styles.link]}
onPress={() => {
fileDownload(message.source, message.filename);
}}
>
{Localize.translateLocal('iou.error.saveFileMessage')}
{translateLocal('iou.error.saveFileMessage')}
</TextLink>

<Text style={[StyleUtils.getDotIndicatorTextStyles(isErrorMessage)]}>{Localize.translateLocal('iou.error.loseFileMessage')}</Text>
</Text>
);
}

if (message === CONST.COMPANY_CARDS.CONNECTION_ERROR) {
return (
<Text
key={index}
style={styles.offlineFeedback.text}
>
<Text style={[StyleUtils.getDotIndicatorTextStyles(isErrorMessage)]}>{Localize.translateLocal('workspace.companyCards.brokenConnectionErrorFirstPart')}</Text>
<TextLink
style={[StyleUtils.getDotIndicatorTextStyles(), styles.link]}
onPress={() => {
// TODO: re-navigate the user to the bank’s website to re-authenticate https://github.com/Expensify/App/issues/50448
}}
>
{Localize.translateLocal('workspace.companyCards.brokenConnectionErrorLink')}
</TextLink>

<Text style={[StyleUtils.getDotIndicatorTextStyles(isErrorMessage)]}>{Localize.translateLocal('workspace.companyCards.brokenConnectionErrorSecondPart')}</Text>
<Text style={[StyleUtils.getDotIndicatorTextStyles(isErrorMessage)]}>{translateLocal('iou.error.loseFileMessage')}</Text>
</Text>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,7 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
[SCREENS.WORKSPACE.INVOICES_COMPANY_WEBSITE]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/WorkspaceInvoicingDetailsWebsite').default,
[SCREENS.WORKSPACE.COMPANY_CARDS_ASSIGN_CARD]: () => require<ReactComponentModule>('../../../../pages/workspace/companyCards/assignCard/AssignCardFeedPage').default,
[SCREENS.WORKSPACE.COMPANY_CARDS_SELECT_FEED]: () => require<ReactComponentModule>('../../../../pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage').default,
[SCREENS.WORKSPACE.COMPANY_CARDS_BANK_CONNECTION]: () => require<ReactComponentModule>('../../../../pages/workspace/companyCards/addNew/BankConnection').default,
[SCREENS.WORKSPACE.COMPANY_CARDS_ADD_NEW]: () => require<ReactComponentModule>('../../../../pages/workspace/companyCards/addNew/AddNewCardPage').default,
[SCREENS.WORKSPACE.COMPANY_CARD_DETAILS]: () => require<ReactComponentModule>('../../../../pages/workspace/companyCards/WorkspaceCompanyCardDetailsPage').default,
[SCREENS.WORKSPACE.COMPANY_CARD_NAME]: () => require<ReactComponentModule>('../../../../pages/workspace/companyCards/WorkspaceCompanyCardEditCardNamePage').default,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ const FULL_SCREEN_TO_RHP_MAPPING: Partial<Record<FullScreenName, string[]>> = {
SCREENS.WORKSPACE.COMPANY_CARDS_NAME,
SCREENS.WORKSPACE.COMPANY_CARDS_DETAILS,
SCREENS.WORKSPACE.COMPANY_CARDS_SELECT_FEED,
SCREENS.WORKSPACE.COMPANY_CARDS_BANK_CONNECTION,
SCREENS.WORKSPACE.COMPANY_CARDS_SETTINGS,
SCREENS.WORKSPACE.COMPANY_CARDS_SETTINGS_FEED_NAME,
SCREENS.WORKSPACE.COMPANY_CARDS_SETTINGS,
Expand Down
3 changes: 3 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,9 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
[SCREENS.WORKSPACE.COMPANY_CARDS_SELECT_FEED]: {
path: ROUTES.WORKSPACE_COMPANY_CARDS_SELECT_FEED.route,
},
[SCREENS.WORKSPACE.COMPANY_CARDS_BANK_CONNECTION]: {
path: ROUTES.WORKSPACE_COMPANY_CARDS_BANK_CONNECTION.route,
},
[SCREENS.WORKSPACE.COMPANY_CARD_DETAILS]: {
path: ROUTES.WORKSPACE_COMPANY_CARD_DETAILS.route,
},
Expand Down
5 changes: 5 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,11 @@ type SettingsNavigatorParamList = {
[SCREENS.WORKSPACE.COMPANY_CARDS_SELECT_FEED]: {
policyID: string;
};
[SCREENS.WORKSPACE.COMPANY_CARDS_BANK_CONNECTION]: {
policyID: string;
bankName: string;
backTo: Routes;
};
[SCREENS.WORKSPACE.COMPANY_CARD_DETAILS]: {
policyID: string;
bank: CompanyCardFeed;
Expand Down
6 changes: 0 additions & 6 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import INPUT_IDS from '@src/types/form/NetSuiteCustomFieldForm';
import type {OnyxInputOrEntry, Policy, PolicyCategories, PolicyEmployeeList, PolicyTagLists, PolicyTags, Report, TaxRate} from '@src/types/onyx';
import type {CardFeedData} from '@src/types/onyx/CardFeeds';
import type {ErrorFields, PendingAction, PendingFields} from '@src/types/onyx/OnyxCommon';
import type {
ConnectionLastSync,
Expand Down Expand Up @@ -1146,10 +1145,6 @@ function getWorkflowApprovalsUnavailable(policy: OnyxEntry<Policy>) {
return policy?.approvalMode === CONST.POLICY.APPROVAL_MODE.OPTIONAL || !!policy?.errorFields?.approvalMode;
}

function hasPolicyFeedsError(feeds: Record<string, CardFeedData>, feedToSkip?: string): boolean {
return Object.entries(feeds).filter(([feedName, feedData]) => feedName !== feedToSkip && !!feedData.errors).length > 0;
}

function getAllPoliciesLength() {
return Object.keys(allPolicies ?? {}).length;
}
Expand Down Expand Up @@ -1233,7 +1228,6 @@ export {
goBackFromInvalidPolicy,
hasAccountingConnections,
shouldShowSyncError,
hasPolicyFeedsError,
shouldShowCustomUnitsError,
shouldShowEmployeeListError,
hasIntegrationAutoSync,
Expand Down
58 changes: 40 additions & 18 deletions src/libs/actions/CompanyCards.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx';
import type {OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import * as API from '@libs/API';
import type {
Expand All @@ -18,10 +18,11 @@ import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportUtils from '@libs/ReportUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Card, CardFeeds} from '@src/types/onyx';
import type {Card, CardFeeds, WorkspaceCardsList} from '@src/types/onyx';
import type {AssignCard, AssignCardData} from '@src/types/onyx/AssignCard';
import type {AddNewCardFeedData, AddNewCardFeedStep, CompanyCardFeed} from '@src/types/onyx/CardFeeds';
import type {OnyxData} from '@src/types/onyx/Request';
import {isEmptyObject} from '@src/types/utils/EmptyObject';

type AddNewCompanyCardFlowData = {
/** Step to be set in Onyx */
Expand Down Expand Up @@ -403,8 +404,6 @@ function unassignWorkspaceCompanyCard(workspaceAccountID: number, bankName: stri

function updateWorkspaceCompanyCard(workspaceAccountID: number, cardID: string, bankName: CompanyCardFeed) {
const authToken = NetworkStore.getAuthToken();
const optimisticFeedUpdates = {[bankName]: {errors: null}};
const failureFeedUpdates = {[bankName]: {errors: {error: CONST.COMPANY_CARDS.CONNECTION_ERROR}}};

const optimisticData: OnyxUpdate[] = [
{
Expand Down Expand Up @@ -437,13 +436,6 @@ function updateWorkspaceCompanyCard(workspaceAccountID: number, cardID: string,
},
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${workspaceAccountID}`,
value: {
settings: {companyCards: optimisticFeedUpdates},
},
},
];

const finallyData: OnyxUpdate[] = [
Expand Down Expand Up @@ -504,13 +496,6 @@ function updateWorkspaceCompanyCard(workspaceAccountID: number, cardID: string,
},
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${workspaceAccountID}`,
value: {
settings: {companyCards: failureFeedUpdates},
},
},
];

const parameters = {
Expand Down Expand Up @@ -740,6 +725,41 @@ function openPolicyCompanyCardsFeed(policyID: string, feed: CompanyCardFeed) {
API.read(READ_COMMANDS.OPEN_POLICY_COMPANY_CARDS_FEED, parameters);
}

/**
* Takes the list of cards divided by workspaces and feeds and returns the flattened non-Expensify cards related to the provided workspace
*
* @param allCardsList the list where cards split by workspaces and feeds and stored under `card_${workspaceAccountID}_${feedName}` keys
* @param workspaceAccountID the workspace account id we want to get cards for
*/
function flatAllCardsList(allCardsList: OnyxCollection<WorkspaceCardsList>, workspaceAccountID: number): Record<string, Card> | undefined {
if (!allCardsList) {
return;
}

return Object.entries(allCardsList).reduce((acc, [key, allCards]) => {
if (!key.includes(workspaceAccountID.toString()) || key.includes(CONST.EXPENSIFY_CARD.BANK)) {
return acc;
}
const {cardList, ...feedCards} = allCards ?? {};
Object.assign(acc, feedCards);
return acc;
}, {});
}

/**
* Check if any feed card has a broken connection
*
* @param feedCards the list of the cards, related to one or several feeds
* @param [feedToExclude] the feed to ignore during the check, it's useful for checking broken connection error only in the feeds other than the selected one
*/
function checkIfFeedConnectionIsBroken(feedCards: Record<string, Card> | undefined, feedToExclude?: string): boolean {
if (!feedCards || isEmptyObject(feedCards)) {
return false;
}

return Object.values(feedCards).some((card) => card.bank !== feedToExclude && card.lastScrapeResult !== 200);
}

export {
setWorkspaceCompanyCardFeedName,
deleteWorkspaceCompanyCardFeed,
Expand All @@ -757,4 +777,6 @@ export {
clearAddNewCardFlow,
setAssignCardStepAndData,
clearAssignCardStepAndData,
checkIfFeedConnectionIsBroken,
flatAllCardsList,
};
4 changes: 2 additions & 2 deletions src/libs/actions/getCompanyCardBankConnection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type CompanyCardBankConnection = {
isNewDot: string;
};

export default function getCompanyCardBankConnection(policyID?: string, bankName?: string, scrapeMinDate?: string) {
export default function getCompanyCardBankConnection(policyID?: string, bankName?: string) {
const bankConnection = Object.keys(CONST.COMPANY_CARDS.BANKS).find((key) => CONST.COMPANY_CARDS.BANKS[key as keyof typeof CONST.COMPANY_CARDS.BANKS] === bankName);

if (!bankName || !bankConnection || !policyID) {
Expand All @@ -23,7 +23,7 @@ export default function getCompanyCardBankConnection(policyID?: string, bankName
isNewDot: 'true',
domainName: PolicyUtils.getDomainNameForPolicy(policyID),
isCorporate: 'true',
scrapeMinDate: scrapeMinDate ?? '',
scrapeMinDate: '',
};
const commandURL = getApiRoot({
shouldSkipWebProxy: true,
Expand Down
Loading

0 comments on commit 9cadcd2

Please sign in to comment.