Skip to content

Commit

Permalink
Merge pull request #42543 from Expensify/qbo-freeze-branch
Browse files Browse the repository at this point in the history
QBO freeze branch
  • Loading branch information
Hayata Suenaga authored May 31, 2024
2 parents b71d98d + d234079 commit b0e2361
Show file tree
Hide file tree
Showing 24 changed files with 337 additions and 61 deletions.
6 changes: 5 additions & 1 deletion src/components/BlockingViews/BlockingView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ type BaseBlockingViewProps = {

/** Render custom subtitle */
CustomSubtitle?: React.ReactElement;

/** Additional styles to apply to the container */
containerStyle?: StyleProp<ViewStyle>;
};

type BlockingViewIconProps = {
Expand Down Expand Up @@ -81,6 +84,7 @@ function BlockingView({
animationStyles = [],
animationWebStyle = {},
CustomSubtitle,
containerStyle,
}: BlockingViewProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
Expand Down Expand Up @@ -117,7 +121,7 @@ function BlockingView({
}, [styles, subtitleText, shouldEmbedLinkWithSubtitle, CustomSubtitle]);

return (
<View style={[styles.flex1, styles.alignItemsCenter, styles.justifyContentCenter, styles.ph10]}>
<View style={[styles.flex1, styles.alignItemsCenter, styles.justifyContentCenter, styles.ph10, containerStyle]}>
{animation && (
<Lottie
source={animation}
Expand Down
7 changes: 6 additions & 1 deletion src/components/SelectionList/BaseSelectionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ function BaseSelectionList<TItem extends ListItem>(
headerContent,
footerContent,
listFooterContent,
listEmptyContent,
showScrollIndicator = true,
showLoadingPlaceholder = false,
showConfirmButton = false,
Expand Down Expand Up @@ -103,6 +104,7 @@ function BaseSelectionList<TItem extends ListItem>(
const itemFocusTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const [currentPage, setCurrentPage] = useState(1);
const isTextInputFocusedRef = useRef<boolean>(false);
const isEmptyList = sections.length === 0;

const incrementPage = () => setCurrentPage((prev) => prev + 1);

Expand Down Expand Up @@ -694,8 +696,11 @@ function BaseSelectionList<TItem extends ListItem>(
testID="selection-list"
onLayout={onSectionListLayout}
style={(!maxToRenderPerBatch || (shouldHideListOnInitialRender && isInitialSectionListRender)) && styles.opacity0}
ListHeaderComponent={listHeaderContent}
ListFooterComponent={listFooterContent ?? ShowMoreButtonInstance}
ListHeaderComponent={listHeaderContent && listHeaderContent}
ListEmptyComponent={listEmptyContent}
contentContainerStyle={isEmptyList && listEmptyContent ? styles.flexGrow1 : undefined}
scrollEnabled={!isEmptyList || !listEmptyContent}
onEndReached={onEndReached}
onEndReachedThreshold={onEndReachedThreshold}
/>
Expand Down
3 changes: 3 additions & 0 deletions src/components/SelectionList/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,9 @@ type BaseSelectionListProps<TItem extends ListItem> = Partial<ChildrenProps> & {
/** Custom content to display in the footer of list component. If present ShowMore button won't be displayed */
listFooterContent?: React.JSX.Element | null;

/** Content to display if the list is empty */
listEmptyContent?: React.JSX.Element | null;

/** Whether to use dynamic maxToRenderPerBatch depending on the visible number of elements */
shouldUseDynamicMaxToRenderPerBatch?: boolean;

Expand Down
5 changes: 5 additions & 0 deletions src/components/SelectionScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ type SelectionScreenProps = {
/** Custom content to display in the header */
headerContent?: React.ReactNode;

/** Content to display if the list is empty */
listEmptyContent?: React.JSX.Element | null;

/** Sections for the section list */
sections: Array<SectionListDataType<SelectorType>>;

Expand Down Expand Up @@ -63,6 +66,7 @@ function SelectionScreen({
displayName,
title,
headerContent,
listEmptyContent,
sections,
listItem,
initiallyFocusedOptionKey,
Expand Down Expand Up @@ -102,6 +106,7 @@ function SelectionScreen({
showScrollIndicator
shouldShowTooltips={false}
initiallyFocusedOptionKey={initiallyFocusedOptionKey}
listEmptyContent={listEmptyContent}
/>
</ScreenWrapper>
</AccessOrNotFoundWrapper>
Expand Down
20 changes: 14 additions & 6 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1938,10 +1938,11 @@ export default {
customersDescription: 'Choose whether to import customers/projects and see where customers/projects are displayed.',
locationsDescription: 'Choose whether to import locations, and see where locations are displayed.',
taxesDescription: 'Choose whether to import tax rates and tax defaults from your accounting integration.',
locationsAdditionalDescription: `QuickBooks Online does not support adding a location to vendor bills or checks. Update your export preference to journal entry if you'd like to import locations as tags.`,
outOfPocketLocationEnabledDescription:
'Note: QuickBooks Online does not support a field for locations on vendor bill or check exports. As you have locations enabled on your workspace, this export option is unavailable.',
taxesJournalEntrySwitchNote:
'Note: QuickBooks Online does not support a field for tax on Journal Entry exports. Change your export preference to Vendor Bill or Check to import taxes.',
locationsAdditionalDescription:
'Locations are imported as Tags. This limits exporting expense reports as Vendor Bills or Checks to QuickBooks Online. To unlock these export options, either disable Locations import or upgrade to the Control Plan to export Locations encoded as a Report Field.',
export: 'Export',
exportAs: 'Export as',
exportDescription: 'Configure how data in Expensify gets exported to QuickBooks Online.',
Expand Down Expand Up @@ -1981,20 +1982,23 @@ export default {
exportPreferredExporterNote: 'This can be any workspace admin, but must be a Domain Admin if you set different export accounts for individual company cards in Domain Settings.',
exportPreferredExporterSubNote: 'Once set, the preferred exporter will see reports for export in their account.',
exportOutOfPocketExpensesDescription: 'Set how out-of-pocket expenses export to QuickBooks Online.',
exportCheckDescription: "We'll create a single itemized check for each Expensify report. You can write the check from your bank account of choice (below).",
exportJournalEntryDescription: "We'll create a single itemized journal entry for each Expensify report. You can post the offset entry to your account of choice (below).",
exportVendorBillDescription:
"We'll create a single itemized vendor bill for each Expensify report. If the period of the bill is closed, we'll post to the 1st of the next open period. You can add the vendor bill to your A/P account of choice (below).",
accountsPayable: 'Accounts payable',
account: 'Account',
accountDescription: 'This is your chosen account to post the journal entry offset for each report.',
accountsPayable: 'Accounts payable',
accountsPayableDescription: 'This is your chosen A/P account, against which vendor bills for each report are created.',
bankAccount: 'Bank account',
bankAccountDescription: 'This is your chosen bank account to write checks from.',
optionBelow: 'Choose an option below:',
companyCardsLocationEnabledDescription:
'Note: QuickBooks Online does not support a field for Locations as Tags on Vendor Bills exports. As you import Locations from, this this export option is unavailable.',
'Note: QuickBooks Online does not support a field for locations on vendor bill exports. As you have locations enabled on your workspace, this export option is unavailable.',
outOfPocketTaxEnabledDescription:
"Note: QuickBooks Online doesn't support a field for tax on Journal Entry exports. Because you have tax tracking enabled on your workspace, this export option is unavailable.",
outOfPocketTaxEnabledError: 'Journal entry is not available when taxes enabled. please select a different export option.',
outOfPocketLocationEnabledError: 'Vendor Bills are not available when locations are enabled. Please select a different export option.',
outOfPocketLocationEnabledDescription:
'Note: QuickBooks Online does not support a field for Locations as Tags on Vendor Bills exports. As you import Locations as Tags, this export option is unavailable.',
advancedConfig: {
advanced: 'Advanced',
autoSync: 'Auto-sync',
Expand Down Expand Up @@ -2035,6 +2039,8 @@ export default {
[`${CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.CHECK}Error`]: 'Check is not available when locations are enabled. Please select a different export option.',
[`${CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.JOURNAL_ENTRY}Error`]: 'Journal entry is not available when taxes enabled. please select a different export option.',
},
noAccountsFound: 'No accounts found',
noAccountsFoundDescription: 'Add the account in Quickbooks Online and sync the connection again',
},
xero: {
organization: 'Xero organization',
Expand Down Expand Up @@ -2113,6 +2119,8 @@ export default {
},
exportPreferredExporterNote: 'This can be any workspace admin, but must be a domain admin if you set different export accounts for individual company cards in domain settings.',
exportPreferredExporterSubNote: 'Once set, the preferred exporter will see reports for export in their account.',
noAccountsFound: 'No accounts found',
noAccountsFoundDescription: 'Add the account in Xero and sync the connection again',
},
type: {
free: 'Free',
Expand Down
14 changes: 12 additions & 2 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1965,7 +1965,7 @@ export default {
taxesJournalEntrySwitchNote:
'Nota: QuickBooks Online no admite un campo para impuestos al exportar entradas en el libro diario. Cambia tu preferencia de exportación a Factura de Proveedor o Cheque para importar impuestos.',
locationsAdditionalDescription:
'Los lugares son importados como Etiquegas. Esto limita a exportar los informes de gastos como Factura del Proveedor o Cheques a Quicbooks Online. Para desbloquear estas opciones de exportación desactiva la importación de Lugares o cambia al Plan Control para exportar Lugares como Campos de Informes.',
'QuickBooks Online no permite añadir una ubicación a las facturas de proveedores o a los cheques. Actualice su preferencia de exportación a asiento contable si desea importar ubicaciones como etiquetas.',
export: 'Exportar',
exportAs: 'Exportar cómo',
exportExpenses: 'Exportar gastos de bolsillo como',
Expand Down Expand Up @@ -2000,26 +2000,32 @@ export default {
exportInvoicesDescription: 'Las facturas se exportarán a esta cuenta en QuickBooks Online.',
exportCompanyCardsDescription: 'Establece cómo se exportan las compras con tarjeta de empresa a QuickBooks Online.',
account: 'Cuenta',
accountDescription: 'Esta es la cuenta elegida para contabilizar la compensación de la entrada de diario de cada informe.',
vendor: 'Proveedor',
defaultVendor: 'Proveedor predeterminado',
defaultVendorDescription: 'Establece un proveedor predeterminado que se aplicará a todas las transacciones con tarjeta de crédito al momento de exportarlas.',
accountsPayable: 'Cuentas por pagar',
accountsPayableDescription: 'Esta es la cuenta de cuentas por pagar elegida, contra la cual se crean las facturas de proveedores para cada informe.',
bankAccount: 'Cuenta bancaria',
bankAccountDescription: 'Esta es la cuenta bancaria elegida para emitir cheques.',
optionBelow: 'Elija una opción a continuación:',
companyCardsLocationEnabledDescription:
'Nota: QuickBooks Online no admite un campo para Ubicaciones como etiquetas en las exportaciones de facturas de proveedores. A medida que importa ubicaciones, esta opción de exportación no está disponible.',
exportPreferredExporterNote:
'Puede ser cualquier administrador del espacio de trabajo, pero debe ser un administrador de dominio si configura diferentes cuentas de exportación para tarjetas de empresa individuales en la configuración del dominio.',
exportPreferredExporterSubNote: 'Una vez configurado, el exportador preferido verá los informes para exportar en tu cuenta.',
exportOutOfPocketExpensesDescription: 'Establezca cómo se exportan los gastos de bolsillo a QuickBooks Online.',
exportCheckDescription: 'Crearemos un único cheque desglosado para cada informe de Expensify. Puedes emitir el cheque desde la cuenta bancaria que elijas (más abajo).',
exportJournalEntryDescription:
'Crearemos una única entrada de diario desglosada para cada informe de Expensify. Puedes enviar la compensación de la entrada de diario a la cuenta que elijas (más abajo).',
exportVendorBillDescription:
'Crearemos una única factura de proveedor detallada para cada informe de Expensify. Si el período de la factura está cerrado, lo publicaremos en el día 1 del siguiente período abierto. Puede agregar la factura del proveedor a la cuenta A/P de tu elección (a continuación).',
outOfPocketTaxEnabledDescription:
'Nota: QuickBooks Online no admite un campo para impuestos en las exportaciones de Anotación en el diario. Debido a que tienes habilitado el seguimiento de impuestos en tu área de trabajo, esta opción de exportación no está disponible.',
outOfPocketTaxEnabledError: 'La Anotacion en el diario no está disponible cuando los impuestos están activados. Por favor, selecciona una opción de exportación diferente.',
outOfPocketLocationEnabledError: 'Las facturas de proveedores no están disponibles cuando las ubicaciones están activadas. Seleccione otra opción de exportación.',
outOfPocketLocationEnabledDescription:
'Nota: QuickBooks Online no admite un campo para Ubicaciones como Etiquetas en las exportaciones de Facturas de Proveedor. Al importar Ubicaciones como Etiquetas, esta opción de exportación no está disponible.',
'Nota: QuickBooks Online no permite añadir una ubicación a las facturas de proveedores o a los cheques. Al importar ubicaciones como etiquetas, esta opción de exportación no está disponible.',

advancedConfig: {
advanced: 'Avanzado',
Expand Down Expand Up @@ -2067,6 +2073,8 @@ export default {
[`${CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.JOURNAL_ENTRY}Error`]:
'El asiento de diario no está disponible cuando los impuestos están habilitados. seleccione una opción de exportación diferente.',
},
noAccountsFound: 'No se ha encontrado ninguna cuenta',
noAccountsFoundDescription: 'Añade la cuenta en Quickbooks Online y sincroniza de nuevo la conexión',
},
xero: {
organization: 'Organización Xero',
Expand Down Expand Up @@ -2149,6 +2157,8 @@ export default {
exportPreferredExporterNote:
'Puede ser cualquier administrador del espacio de trabajo, pero debe ser un administrador de dominio si configura diferentes cuentas de exportación para tarjetas de empresa individuales en la configuración del dominio.',
exportPreferredExporterSubNote: 'Una vez configurado, el exportador preferido verá los informes para exportar en su cuenta.',
noAccountsFound: 'No se ha encontrado ninguna cuenta',
noAccountsFoundDescription: 'Añade la cuenta en Xero y sincroniza de nuevo la conexión',
},
type: {
free: 'Gratis',
Expand Down
4 changes: 2 additions & 2 deletions src/pages/workspace/WorkspaceNewRoomPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,8 @@ function WorkspaceNewRoomPage({policies, reports, formState, session, activePoli
<>
<BlockingView
icon={Illustrations.TeleScope}
iconWidth={variables.emptyWorkspaceIconWidth}
iconHeight={variables.emptyWorkspaceIconHeight}
iconWidth={variables.emptyListIconWidth}
iconHeight={variables.emptyListIconHeight}
title={translate('workspace.emptyWorkspace.notFound')}
subtitle={translate('workspace.emptyWorkspace.description')}
shouldShowLink={false}
Expand Down
15 changes: 11 additions & 4 deletions src/pages/workspace/accounting/PolicyAccountingPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, {useMemo, useRef, useState} from 'react';
import {formatDistanceToNow} from 'date-fns';
import React, {useEffect, useMemo, useRef, useState} from 'react';
import {ActivityIndicator, View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
Expand Down Expand Up @@ -113,13 +114,16 @@ function PolicyAccountingPage({policy, connectionSyncProgress}: PolicyAccounting
const {isSmallScreenWidth, windowWidth} = useWindowDimensions();
const [threeDotsMenuPosition, setThreeDotsMenuPosition] = useState<AnchorPosition>({horizontal: 0, vertical: 0});
const [isDisconnectModalOpen, setIsDisconnectModalOpen] = useState(false);
const [datetimeToRelative, setDateTimeToRelative] = useState('');
const threeDotsMenuContainerRef = useRef<View>(null);

const isSyncInProgress = !!connectionSyncProgress?.stageInProgress && connectionSyncProgress.stageInProgress !== CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.JOB_DONE;

const accountingIntegrations = Object.values(CONST.POLICY.CONNECTIONS.NAME).filter((name) => !(name === CONST.POLICY.CONNECTIONS.NAME.XERO && !canUseXeroIntegration));
const connectedIntegration = accountingIntegrations.find((integration) => !!policy?.connections?.[integration]) ?? connectionSyncProgress?.connectionName;
const policyID = policy?.id ?? '';
const successfulDate = policy?.connections?.quickbooksOnline?.lastSync?.successfulDate;
const formattedDate = useMemo(() => (successfulDate ? new Date(successfulDate) : new Date()), [successfulDate]);

const policyConnectedToXero = connectedIntegration === CONST.POLICY.CONNECTIONS.NAME.XERO;

Expand All @@ -144,6 +148,10 @@ function PolicyAccountingPage({policy, connectionSyncProgress}: PolicyAccounting
[translate, policyID, isOffline, connectedIntegration],
);

useEffect(() => {
setDateTimeToRelative(formatDistanceToNow(formattedDate, {addSuffix: true}));
}, [formattedDate]);

const connectionsMenuItems: MenuItemData[] = useMemo(() => {
if (isEmptyObject(policy?.connections) && !isSyncInProgress) {
return accountingIntegrations.map((integration) => {
Expand Down Expand Up @@ -176,9 +184,7 @@ function PolicyAccountingPage({policy, connectionSyncProgress}: PolicyAccounting
errorText: shouldShowSynchronizationError ? translate('workspace.accounting.syncError', connectedIntegration) : undefined,
errorTextStyle: [styles.mt5],
shouldShowRedDotIndicator: true,
description: isSyncInProgress
? translate('workspace.accounting.connections.syncStageName', connectionSyncProgress.stageInProgress)
: translate('workspace.accounting.lastSync'),
description: isSyncInProgress ? translate('workspace.accounting.connections.syncStageName', connectionSyncProgress.stageInProgress) : datetimeToRelative,
rightComponent: isSyncInProgress ? (
<ActivityIndicator
style={[styles.popoverMenuIcon]}
Expand Down Expand Up @@ -270,6 +276,7 @@ function PolicyAccountingPage({policy, connectionSyncProgress}: PolicyAccounting
policyConnectedToXero,
currentXeroOrganizationName,
tenants.length,
datetimeToRelative,
accountingIntegrations,
currentXeroOrganization?.id,
]);
Expand Down
Loading

0 comments on commit b0e2361

Please sign in to comment.