Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix GBR and error briefly show after connecting to QBO, Xero. #47483

Merged
merged 25 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/components/Indicator.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from 'react';
import {StyleSheet, View} from 'react-native';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import {useOnyx, withOnyx} from 'react-native-onyx';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import {isConnectionInProgress} from '@libs/actions/connections';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as SubscriptionUtils from '@libs/SubscriptionUtils';
import * as UserUtils from '@libs/UserUtils';
Expand Down Expand Up @@ -41,6 +42,7 @@ type IndicatorProps = IndicatorOnyxProps;
function Indicator({reimbursementAccount, policies, bankAccountList, fundList, userWallet, walletTerms, loginList}: IndicatorOnyxProps) {
const theme = useTheme();
const styles = useThemeStyles();
const [allConnectionSyncProgresses] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}`);

// If a policy was just deleted from Onyx, then Onyx will pass a null value to the props, and
// those should be cleaned out before doing any error checking
Expand All @@ -55,7 +57,13 @@ function Indicator({reimbursementAccount, policies, bankAccountList, fundList, u
() => Object.values(cleanPolicies).some(PolicyUtils.hasPolicyError),
() => Object.values(cleanPolicies).some(PolicyUtils.hasCustomUnitsError),
() => Object.values(cleanPolicies).some(PolicyUtils.hasEmployeeListError),
() => Object.values(cleanPolicies).some(PolicyUtils.hasSyncError),
() =>
Object.values(cleanPolicies).some((cleanPolicy) =>
PolicyUtils.hasSyncError(
cleanPolicy,
isConnectionInProgress(allConnectionSyncProgresses?.[`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${cleanPolicy?.id}`], cleanPolicy),
),
),
() => SubscriptionUtils.hasSubscriptionRedDotError(),
() => Object.keys(reimbursementAccount?.errors ?? {}).length > 0,
() => !!loginList && UserUtils.hasLoginListError(loginList),
Expand Down
8 changes: 4 additions & 4 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ function hasPolicyCategoriesError(policyCategories: OnyxEntry<PolicyCategories>)
/**
* Checks if the policy had a sync error.
*/
function hasSyncError(policy: OnyxEntry<Policy>): boolean {
return (Object.keys(policy?.connections ?? {}) as ConnectionName[]).some((connection) => !!getSynchronizationErrorMessage(policy, connection, false));
function hasSyncError(policy: OnyxEntry<Policy>, isSyncInProgress: boolean): boolean {
return (Object.keys(policy?.connections ?? {}) as ConnectionName[]).some((connection) => !!getSynchronizationErrorMessage(policy, connection, isSyncInProgress));
}

/**
Expand Down Expand Up @@ -152,8 +152,8 @@ function getUnitRateValue(toLocaleDigit: (arg: string) => string, customUnitRate
/**
* Get the brick road indicator status for a policy. The policy has an error status if there is a policy member error, a custom unit error or a field error.
*/
function getPolicyBrickRoadIndicatorStatus(policy: OnyxEntry<Policy>): ValueOf<typeof CONST.BRICK_ROAD_INDICATOR_STATUS> | undefined {
if (hasEmployeeListError(policy) || hasCustomUnitsError(policy) || hasPolicyErrorFields(policy) || hasSyncError(policy)) {
function getPolicyBrickRoadIndicatorStatus(policy: OnyxEntry<Policy>, isConnectionInProgress: boolean): ValueOf<typeof CONST.BRICK_ROAD_INDICATOR_STATUS> | undefined {
if (hasEmployeeListError(policy) || hasCustomUnitsError(policy) || hasPolicyErrorFields(policy) || hasSyncError(policy, isConnectionInProgress)) {
return CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR;
}
return undefined;
Expand Down
24 changes: 7 additions & 17 deletions src/libs/WorkspacesSettingsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import type {TranslationPaths} from '@src/languages/types';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Policy, ReimbursementAccount, Report, ReportAction, ReportActions, TransactionViolations} from '@src/types/onyx';
import type {Unit} from '@src/types/onyx/Policy';
import type {PolicyConnectionSyncProgress, Unit} from '@src/types/onyx/Policy';
import {isConnectionInProgress} from './actions/connections';
import * as CurrencyUtils from './CurrencyUtils';
import type {Phrase, PhraseParameters} from './Localize';
import * as OptionsListUtils from './OptionsListUtils';
Expand All @@ -18,7 +19,7 @@

type BrickRoad = ValueOf<typeof CONST.BRICK_ROAD_INDICATOR_STATUS> | undefined;

let allPolicies: OnyxCollection<Policy>;

Check failure on line 22 in src/libs/WorkspacesSettingsUtils.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

'allPolicies' is assigned a value but never used

Onyx.connect({
key: ONYXKEYS.COLLECTION.POLICY,
Expand Down Expand Up @@ -100,7 +101,7 @@
return shouldShowGreenDotIndicator ? CONST.BRICK_ROAD_INDICATOR_STATUS.INFO : undefined;
};

function hasGlobalWorkspaceSettingsRBR(policies: OnyxCollection<Policy>) {
function hasGlobalWorkspaceSettingsRBR(policies: OnyxCollection<Policy>, allConnectionProgresses: OnyxCollection<PolicyConnectionSyncProgress>) {
// When attempting to open a policy with an invalid policyID, the policy collection is updated to include policy objects with error information.
// Only policies displayed on the policy list page should be verified. Otherwise, the user will encounter an RBR unrelated to any policies on the list.
const cleanPolicies = Object.fromEntries(Object.entries(policies ?? {}).filter(([, policy]) => policy?.id));
Expand All @@ -110,7 +111,10 @@
() => Object.values(cleanPolicies).some(hasCustomUnitsError),
() => Object.values(cleanPolicies).some(hasTaxRateError),
() => Object.values(cleanPolicies).some(hasEmployeeListError),
() => Object.values(cleanPolicies).some(hasSyncError),
() =>
Object.values(cleanPolicies).some((cleanPolicy) =>
hasSyncError(cleanPolicy, isConnectionInProgress(allConnectionProgresses?.[`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${cleanPolicy?.id}`], cleanPolicy)),
),
() => Object.keys(reimbursementAccount?.errors ?? {}).length > 0,
];

Expand Down Expand Up @@ -154,19 +158,6 @@
return undefined;
}

function checkIfWorkspaceSettingsTabHasRBR(policyID?: string) {
hungvu193 marked this conversation as resolved.
Show resolved Hide resolved
if (!policyID) {
return hasGlobalWorkspaceSettingsRBR(allPolicies);
}
const policy = allPolicies ? allPolicies[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`] : null;

if (!policy) {
return false;
}

return hasWorkspaceSettingsRBR(policy);
}

/**
* @returns a map where the keys are policyIDs and the values are BrickRoads for each policy
*/
Expand Down Expand Up @@ -318,7 +309,6 @@
getWorkspacesBrickRoads,
getWorkspacesUnreadStatuses,
hasGlobalWorkspaceSettingsRBR,
checkIfWorkspaceSettingsTabHasRBR,
hasWorkspaceSettingsRBR,
getChatTabBrickRoad,
getUnitTranslationKey,
Expand Down
21 changes: 19 additions & 2 deletions src/libs/actions/connections/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {differenceInMinutes, isValid, parseISO} from 'date-fns';
import isObject from 'lodash/isObject';
import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
Expand All @@ -9,7 +10,7 @@ import * as Localize from '@libs/Localize';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type * as OnyxCommon from '@src/types/onyx/OnyxCommon';
import type {ConnectionName, Connections, PolicyConnectionName} from '@src/types/onyx/Policy';
import type {ConnectionName, Connections, PolicyConnectionName, PolicyConnectionSyncProgress} from '@src/types/onyx/Policy';
import type Policy from '@src/types/onyx/Policy';

type ConnectionNameExceptNetSuite = Exclude<ConnectionName, typeof CONST.POLICY.CONNECTIONS.NAME.NETSUITE>;
Expand Down Expand Up @@ -379,7 +380,8 @@ function getSynchronizationErrorMessage(policy: OnyxEntry<Policy>, connectionNam
}

const connection = policy?.connections?.[connectionName];
if (isSyncInProgress || connection?.lastSync?.isSuccessful) {

if (isSyncInProgress || connection?.lastSync?.isSuccessful !== false) {
return;
}
return `${syncError} ("${connection?.lastSync?.errorMessage}")`;
Expand Down Expand Up @@ -430,6 +432,20 @@ function copyExistingPolicyConnection(connectedPolicyID: string, targetPolicyID:
);
}

function isConnectionInProgress(connectionSyncProgress: OnyxEntry<PolicyConnectionSyncProgress>, policy?: OnyxEntry<Policy>): boolean {
if (!policy || !connectionSyncProgress) {
return false;
}

const lastSyncProgressDate = parseISO(connectionSyncProgress?.timestamp ?? '');
return (
!!connectionSyncProgress?.stageInProgress &&
(connectionSyncProgress.stageInProgress !== CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.JOB_DONE || !policy?.connections?.[connectionSyncProgress.connectionName]) &&
isValid(lastSyncProgressDate) &&
differenceInMinutes(new Date(), lastSyncProgressDate) < CONST.POLICY.CONNECTIONS.SYNC_STAGE_TIMEOUT_MINUTES
);
}

export {
removePolicyConnection,
updatePolicyConnectionConfig,
Expand All @@ -439,4 +455,5 @@ export {
syncConnection,
copyExistingPolicyConnection,
isConnectionUnverified,
isConnectionInProgress,
};
5 changes: 3 additions & 2 deletions src/pages/home/sidebar/AllSettingsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ function AllSettingsScreen({policies}: AllSettingsScreenProps) {
const waitForNavigate = useWaitForNavigation();
const {translate} = useLocalize();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const [allConnectionSyncProgresses] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}`);

const [privateSubscription] = useOnyx(ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION);

Expand All @@ -48,7 +49,7 @@ function AllSettingsScreen({policies}: AllSettingsScreenProps) {
})();
},
focused: !shouldUseNarrowLayout,
brickRoadIndicator: hasGlobalWorkspaceSettingsRBR(policies) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined,
brickRoadIndicator: hasGlobalWorkspaceSettingsRBR(policies, allConnectionSyncProgresses) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined,
},
...(privateSubscription
? [
Expand Down Expand Up @@ -90,7 +91,7 @@ function AllSettingsScreen({policies}: AllSettingsScreenProps) {
hoverAndPressStyle: styles.hoveredComponentBG,
brickRoadIndicator: item.brickRoadIndicator,
}));
}, [shouldUseNarrowLayout, policies, privateSubscription, waitForNavigate, translate, styles]);
}, [shouldUseNarrowLayout, policies, privateSubscription, waitForNavigate, translate, styles, allConnectionSyncProgresses]);

return (
<ScreenWrapper
Expand Down
5 changes: 3 additions & 2 deletions src/pages/settings/InitialSettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ function InitialSettingsPage({session, userWallet, bankAccountList, fundList, wa
const {translate, formatPhoneNumber} = useLocalize();
const activeCentralPaneRoute = useActiveCentralPaneRoute();
const emojiCode = currentUserPersonalDetails?.status?.emojiCode ?? '';
const [allConnectionSyncProgresses] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}`);

const [privateSubscription] = useOnyx(ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION);
const subscriptionPlan = useSubscriptionPlan();
Expand Down Expand Up @@ -191,7 +192,7 @@ function InitialSettingsPage({session, userWallet, bankAccountList, fundList, wa
translationKey: 'common.workspaces',
icon: Expensicons.Building,
routeName: ROUTES.SETTINGS_WORKSPACES,
brickRoadIndicator: hasGlobalWorkspaceSettingsRBR(policies) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined,
brickRoadIndicator: hasGlobalWorkspaceSettingsRBR(policies, allConnectionSyncProgresses) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined,
},
{
translationKey: 'allSettingsScreen.domains',
Expand Down Expand Up @@ -221,7 +222,7 @@ function InitialSettingsPage({session, userWallet, bankAccountList, fundList, wa
sectionTranslationKey: 'common.workspaces',
items,
};
}, [policies, privateSubscription?.errors, styles.badgeSuccess, styles.workspaceSettingsSectionContainer, subscriptionPlan, translate]);
}, [policies, privateSubscription?.errors, styles.badgeSuccess, styles.workspaceSettingsSectionContainer, subscriptionPlan, translate, allConnectionSyncProgresses]);

/**
* Retuns a list of menu items data for general section
Expand Down
9 changes: 6 additions & 3 deletions src/pages/workspace/WorkspaceInitialPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import {useOnyx, withOnyx} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import ConfirmModal from '@components/ConfirmModal';
Expand All @@ -20,6 +20,7 @@
import useSingleExecution from '@hooks/useSingleExecution';
import useThemeStyles from '@hooks/useThemeStyles';
import useWaitForNavigation from '@hooks/useWaitForNavigation';
import {isConnectionInProgress} from '@libs/actions/connections';
import getTopmostRouteName from '@libs/Navigation/getTopmostRouteName';
import Navigation from '@libs/Navigation/Navigation';
import * as PolicyUtils from '@libs/PolicyUtils';
Expand All @@ -42,6 +43,7 @@
import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscreenLoading';
import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading';


Check failure on line 46 in src/pages/workspace/WorkspaceInitialPage.tsx

View workflow job for this annotation

GitHub Actions / Run ESLint

Delete `⏎`
type WorkspaceMenuItem = {
translationKey: TranslationPaths;
icon: IconAsset;
Expand Down Expand Up @@ -93,7 +95,8 @@
const policy = policyDraft?.id ? policyDraft : policyProp;
const [isCurrencyModalOpen, setIsCurrencyModalOpen] = useState(false);
const hasPolicyCreationError = !!(policy?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD && !isEmptyObject(policy.errors));
const hasSyncError = PolicyUtils.hasSyncError(policy);
const [connectionSyncProgress] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${policy?.id}`);
const hasSyncError = PolicyUtils.hasSyncError(policy, isConnectionInProgress(connectionSyncProgress, policy));
const waitForNavigate = useWaitForNavigation();
const {singleExecution, isExecuting} = useSingleExecution();
const activeRoute = useNavigationState(getTopmostRouteName);
Expand Down Expand Up @@ -466,4 +469,4 @@
key: ({route}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${route.params?.policyID ?? '-1'}`,
},
})(WorkspaceInitialPage),
);
);

Check failure on line 472 in src/pages/workspace/WorkspaceInitialPage.tsx

View workflow job for this annotation

GitHub Actions / Run ESLint

Insert `⏎`
14 changes: 11 additions & 3 deletions src/pages/workspace/WorkspacesListPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {useCallback, useMemo, useState} from 'react';
import {FlatList, View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import {useOnyx, withOnyx} from 'react-native-onyx';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import Button from '@components/Button';
Expand All @@ -24,6 +24,7 @@
import useNetwork from '@hooks/useNetwork';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useTheme from '@hooks/useTheme';
import {isConnectionInProgress} from '@libs/actions/connections';

Check failure on line 27 in src/pages/workspace/WorkspacesListPage.tsx

View workflow job for this annotation

GitHub Actions / Run ESLint

Replace `{isConnectionInProgress}·from·'@libs/actions/connections';⏎import·useThemeStyles·from·'@hooks/useThemeStyle` with `useThemeStyles·from·'@hooks/useThemeStyles';⏎import·{isConnectionInProgress}·from·'@libs/actions/connection`
import useThemeStyles from '@hooks/useThemeStyles';
import interceptAnonymousUser from '@libs/interceptAnonymousUser';
import localeCompare from '@libs/LocaleCompare';
Expand All @@ -41,8 +42,9 @@
import type {Policy as PolicyType, ReimbursementAccount, Report, Session as SessionType} from '@src/types/onyx';
import type * as OnyxCommon from '@src/types/onyx/OnyxCommon';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import WorkspacesListRow from './WorkspacesListRow';

Check failure on line 45 in src/pages/workspace/WorkspacesListPage.tsx

View workflow job for this annotation

GitHub Actions / Run ESLint

Delete `⏎`


type WorkspaceItem = Required<Pick<MenuItemProps, 'title' | 'disabled'>> &
Pick<MenuItemProps, 'brickRoadIndicator' | 'iconFill' | 'fallbackIcon'> &
Pick<OfflineWithFeedbackProps, 'errors' | 'pendingAction'> &
Expand Down Expand Up @@ -123,6 +125,7 @@
const {translate} = useLocalize();
const {isOffline} = useNetwork();
const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
const [allConnectionSyncProgresses] = useOnyx(ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS);

const {activeWorkspaceID, setActiveWorkspaceID} = useActiveWorkspace();

Expand Down Expand Up @@ -338,7 +341,12 @@
title: policy.name,
icon: policy.avatarURL ? policy.avatarURL : ReportUtils.getDefaultWorkspaceAvatar(policy.name),
action: () => Navigation.navigate(ROUTES.WORKSPACE_INITIAL.getRoute(policy.id)),
brickRoadIndicator: reimbursementAccountBrickRoadIndicator ?? PolicyUtils.getPolicyBrickRoadIndicatorStatus(policy),
brickRoadIndicator:
reimbursementAccountBrickRoadIndicator ??
PolicyUtils.getPolicyBrickRoadIndicatorStatus(
policy,
isConnectionInProgress(allConnectionSyncProgresses?.[`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${policy.id}`], policy),
),
pendingAction: policy.pendingAction,
errors: policy.errors,
dismissError: () => dismissWorkspaceError(policy.id, policy.pendingAction),
Expand All @@ -355,7 +363,7 @@
};
})
.sort((a, b) => localeCompare(a.title, b.title));
}, [reimbursementAccount?.errors, policies, isOffline, theme.textLight, policyRooms]);
}, [reimbursementAccount?.errors, policies, isOffline, theme.textLight, policyRooms, allConnectionSyncProgresses]);

const getHeaderButton = () => (
<Button
Expand Down
Loading
Loading