Skip to content

Commit

Permalink
Merge branch 'main' into kicu/50787-search-utils
Browse files Browse the repository at this point in the history
  • Loading branch information
Kicu committed Oct 16, 2024
2 parents 1b9196e + 336c2dd commit 0c99713
Show file tree
Hide file tree
Showing 58 changed files with 740 additions and 699 deletions.
7 changes: 5 additions & 2 deletions .github/ISSUE_TEMPLATE/Standard.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ ___
**Version Number:**
**Reproducible in staging?:**
**Reproducible in production?:**
**If this was caught on HybridApp, is this reproducible on New Expensify Standalone?:**
**If this was caught during regression testing, add the test name, ID and link from TestRail:**
**Email or phone of affected tester (no customers):**
**Logs:** https://stackoverflow.com/c/expensify/questions/4856
Expand All @@ -34,9 +35,11 @@ Can the user still use Expensify without this being fixed? Have you informed the
Check off any platforms that are affected by this issue
--->
Which of our officially supported platforms is this issue occurring on?
- [ ] Android: Native
- [ ] Android: Standalone
- [ ] Android: HybridApp
- [ ] Android: mWeb Chrome
- [ ] iOS: Native
- [ ] iOS: Standalone
- [ ] iOS: HybridApp
- [ ] iOS: mWeb Safari
- [ ] MacOS: Chrome / Safari
- [ ] MacOS: Desktop
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ When a Domain Admin enables Consolidated Domain Billing, all Group workspaces ow
If you don’t have multiple billing owners across your organization, or if you want to keep billing separate for any reason, then this feature isn’t necessary.

If you have an Annual Subscription and enable Consolidated Domain Billing, the Consolidated Domain Billing feature will gather the amounts due for each Group workspace Billing Owner (listed under **Settings > Workspaces > Group**). To make full use of the Annual Subscription for all workspaces in your domain, you should also be the billing owner for all Group workspaces.

{% include faq-begin.md %}

## How do I take over the billing of a workspace with Consolidated Domain Billing enabled?
You’ll have to toggle off Consolidated Domain Billing, take over ownership of the workspace, and then toggle it back on.

## Can I use Consolidated Domain Billing to cover the bill for some workspaces, but not others?
No, this feature means that you’ll be paying the bill for all domain members who choose a subscription.

Expand Down
4 changes: 3 additions & 1 deletion src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1108,7 +1108,7 @@ const CONST = {
},
TIMING: {
CALCULATE_MOST_RECENT_LAST_MODIFIED_ACTION: 'calc_most_recent_last_modified_action',
CHAT_FINDER_RENDER: 'search_render',
SEARCH_ROUTER_RENDER: 'search_router_render',
CHAT_RENDER: 'chat_render',
OPEN_REPORT: 'open_report',
HOMEPAGE_INITIAL_RENDER: 'homepage_initial_render',
Expand Down Expand Up @@ -1492,7 +1492,9 @@ const CONST = {
MARK_CHECKS_TO_BE_PRINTED: 'markChecksToBePrinted',
REIMBURSABLE_ACCOUNT: 'reimbursableAccount',
REIMBURSABLE: 'reimbursable',
AUTO_SYNC: 'autoSync',
ENABLE_NEW_CATEGORIES: 'enableNewCategories',
SHOULD_AUTO_CREATE_VENDOR: 'shouldAutoCreateVendor',
MAPPINGS: {
CLASSES: 'classes',
},
Expand Down
5 changes: 4 additions & 1 deletion src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ const ROUTES = {
route: 'flag/:reportID/:reportActionID',
getRoute: (reportID: string, reportActionID: string, backTo?: string) => getUrlWithBackToParam(`flag/${reportID}/${reportActionID}` as const, backTo),
},
CHAT_FINDER: 'chat-finder',
PROFILE: {
route: 'a/:accountID',
getRoute: (accountID?: string | number, backTo?: string, login?: string) => {
Expand Down Expand Up @@ -670,6 +669,10 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/accounting/quickbooks-online/export/date-select',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/quickbooks-online/export/date-select` as const,
},
WORKSPACE_ACCOUNTING_QUICKBOOKS_DESKTOP_ADVANCED: {
route: 'settings/workspaces/:policyID/accounting/quickbooks-desktop/advanced',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/quickbooks-desktop/advanced` as const,
},
POLICY_ACCOUNTING_QUICKBOOKS_DESKTOP_EXPORT_DATE_SELECT: {
route: 'settings/workspaces/:policyID/accounting/quickbooks-desktop/export/date-select',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/quickbooks-desktop/export/date-select` as const,
Expand Down
2 changes: 1 addition & 1 deletion src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ const SCREENS = {
ROOT: 'SaveTheWorld_Root',
},
LEFT_MODAL: {
CHAT_FINDER: 'ChatFinder',
WORKSPACE_SWITCHER: 'WorkspaceSwitcher',
},
RIGHT_MODAL: {
Expand Down Expand Up @@ -317,6 +316,7 @@ const SCREENS = {
QUICKBOOKS_ONLINE_ADVANCED: 'Policy_Accounting_Quickbooks_Online_Advanced',
QUICKBOOKS_ONLINE_ACCOUNT_SELECTOR: 'Policy_Accounting_Quickbooks_Online_Account_Selector',
QUICKBOOKS_ONLINE_INVOICE_ACCOUNT_SELECTOR: 'Policy_Accounting_Quickbooks_Online_Invoice_Account_Selector',
QUICKBOOKS_DESKTOP_ADVANCED: 'Policy_Accounting_Quickbooks_Desktop_Advanced',
QUICKBOOKS_DESKTOP_EXPORT_DATE_SELECT: 'Workspace_Accounting_Quickbooks_Desktop_Export_Date_Select',
QUICKBOOKS_DESKTOP_EXPORT_PREFERRED_EXPORTER: 'Workspace_Accounting_Quickbooks_Desktop_Export_Preferred_Exporter',
QUICKBOOKS_DESKTOP_EXPORT_OUT_OF_POCKET_EXPENSES: 'Workspace_Accounting_Quickbooks_Desktop_Export_Out_Of_Pocket_Expenses',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ type BaseAnchorForAttachmentsOnlyProps = AnchorForAttachmentsOnlyProps & {
function BaseAnchorForAttachmentsOnly({style, source = '', displayName = '', onPressIn, onPressOut}: BaseAnchorForAttachmentsOnlyProps) {
const sourceURLWithAuth = addEncryptedAuthTokenToURL(source);
const sourceID = (source.match(CONST.REGEX.ATTACHMENT_ID) ?? [])[1];

const [download] = useOnyx(`${ONYXKEYS.COLLECTION.DOWNLOAD}${sourceID}`);

const {isOffline} = useNetwork();
const styles = useThemeStyles();

Expand All @@ -35,7 +37,7 @@ function BaseAnchorForAttachmentsOnly({style, source = '', displayName = '', onP
<ShowContextMenuContext.Consumer>
{({anchor, report, reportNameValuePairs, action, checkIfContextMenuActive, isDisabled}) => (
<PressableWithoutFeedback
style={[style, isOffline && styles.cursorDefault]}
style={[style, (isOffline || !sourceID) && styles.cursorDefault]}
onPress={() => {
if (isDownloading || isOffline || !sourceID) {
return;
Expand All @@ -61,6 +63,7 @@ function BaseAnchorForAttachmentsOnly({style, source = '', displayName = '', onP
shouldShowDownloadIcon={!!sourceID && !isOffline}
shouldShowLoadingSpinnerIcon={isDownloading}
isUsedAsChatAttachment
isUploading={!sourceID}
/>
</PressableWithoutFeedback>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ type DefaultAttachmentViewProps = {
containerStyles?: StyleProp<ViewStyle>;

icon?: IconAsset;

/** Flag indicating if the attachment is being uploaded. */
isUploading?: boolean;
};

function DefaultAttachmentView({fileName = '', shouldShowLoadingSpinnerIcon = false, shouldShowDownloadIcon, containerStyles, icon}: DefaultAttachmentViewProps) {
function DefaultAttachmentView({fileName = '', shouldShowLoadingSpinnerIcon = false, shouldShowDownloadIcon, containerStyles, icon, isUploading}: DefaultAttachmentViewProps) {
const theme = useTheme();
const styles = useThemeStyles();
const {translate} = useLocalize();
Expand All @@ -53,7 +56,7 @@ function DefaultAttachmentView({fileName = '', shouldShowLoadingSpinnerIcon = fa
)}
{shouldShowLoadingSpinnerIcon && (
<View style={styles.ml2}>
<Tooltip text={translate('common.downloading')}>
<Tooltip text={isUploading ? translate('common.uploading') : translate('common.downloading')}>
<ActivityIndicator
size="small"
color={theme.textSupporting}
Expand Down
87 changes: 42 additions & 45 deletions src/components/Attachments/AttachmentView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import {Str} from 'expensify-common';
import React, {memo, useContext, useEffect, useState} from 'react';
import type {GestureResponderEvent, StyleProp, ViewStyle} from 'react-native';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import {useOnyx} from 'react-native-onyx';
import AttachmentCarouselPagerContext from '@components/Attachments/AttachmentCarousel/Pager/AttachmentCarouselPagerContext';
import type {Attachment, AttachmentSource} from '@components/Attachments/types';
import DistanceEReceipt from '@components/DistanceEReceipt';
Expand All @@ -24,60 +23,58 @@ import * as TransactionUtils from '@libs/TransactionUtils';
import type {ColorValue} from '@styles/utils/types';
import variables from '@styles/variables';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Transaction} from '@src/types/onyx';
import AttachmentViewImage from './AttachmentViewImage';
import AttachmentViewPdf from './AttachmentViewPdf';
import AttachmentViewVideo from './AttachmentViewVideo';
import DefaultAttachmentView from './DefaultAttachmentView';
import HighResolutionInfo from './HighResolutionInfo';

type AttachmentViewOnyxProps = {
transaction: OnyxEntry<Transaction>;
};
type AttachmentViewProps = Attachment & {
/** Whether this view is the active screen */
isFocused?: boolean;

type AttachmentViewProps = AttachmentViewOnyxProps &
Attachment & {
/** Whether this view is the active screen */
isFocused?: boolean;
/** Function for handle on press */
onPress?: (e?: GestureResponderEvent | KeyboardEvent) => void;

/** Function for handle on press */
onPress?: (e?: GestureResponderEvent | KeyboardEvent) => void;
/** Whether the attachment is used in attachment modal */
isUsedInAttachmentModal?: boolean;

isUsedInAttachmentModal?: boolean;
/** Flag to show/hide download icon */
shouldShowDownloadIcon?: boolean;

/** Flag to show/hide download icon */
shouldShowDownloadIcon?: boolean;
/** Flag to show the loading indicator */
shouldShowLoadingSpinnerIcon?: boolean;

/** Flag to show the loading indicator */
shouldShowLoadingSpinnerIcon?: boolean;
/** Notify parent that the UI should be modified to accommodate keyboard */
onToggleKeyboard?: (shouldFadeOut: boolean) => void;

/** Notify parent that the UI should be modified to accommodate keyboard */
onToggleKeyboard?: (shouldFadeOut: boolean) => void;
/** A callback when the PDF fails to load */
onPDFLoadError?: () => void;

/** A callback when the PDF fails to load */
onPDFLoadError?: () => void;
/** Extra styles to pass to View wrapper */
containerStyles?: StyleProp<ViewStyle>;

/** Extra styles to pass to View wrapper */
containerStyles?: StyleProp<ViewStyle>;
/** Denotes whether it is a workspace avatar or not */
isWorkspaceAvatar?: boolean;

/** Denotes whether it is a workspace avatar or not */
isWorkspaceAvatar?: boolean;
/** Denotes whether it is an icon (ex: SVG) */
maybeIcon?: boolean;

/** Denotes whether it is an icon (ex: SVG) */
maybeIcon?: boolean;
/** Fallback source to use in case of error */
fallbackSource?: AttachmentSource;

/** Fallback source to use in case of error */
fallbackSource?: AttachmentSource;
/* Whether it is hovered or not */
isHovered?: boolean;

/* Whether it is hovered or not */
isHovered?: boolean;
/** Whether the attachment is used as a chat attachment */
isUsedAsChatAttachment?: boolean;

/** Whether the attachment is used as a chat attachment */
isUsedAsChatAttachment?: boolean;
/* Flag indicating whether the attachment has been uploaded. */
isUploaded?: boolean;

/* Flag indicating whether the attachment has been uploaded. */
isUploaded?: boolean;
};
/** Flag indicating if the attachment is being uploaded. */
isUploading?: boolean;
};

function AttachmentView({
source,
Expand All @@ -95,16 +92,20 @@ function AttachmentView({
isWorkspaceAvatar,
maybeIcon,
fallbackSource,
transaction,
transactionID = '-1',
reportActionID,
isHovered,
duration,
isUsedAsChatAttachment,
isUploaded = true,
isUploading = false,
}: AttachmentViewProps) {
const {translate} = useLocalize();
const {updateCurrentlyPlayingURL} = usePlaybackContext();
const attachmentCarouselPagerContext = useContext(AttachmentCarouselPagerContext);

const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`);

const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
Expand Down Expand Up @@ -288,20 +289,16 @@ function AttachmentView({
<DefaultAttachmentView
fileName={file?.name}
shouldShowDownloadIcon={shouldShowDownloadIcon}
shouldShowLoadingSpinnerIcon={shouldShowLoadingSpinnerIcon}
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
shouldShowLoadingSpinnerIcon={shouldShowLoadingSpinnerIcon || isUploading}
containerStyles={containerStyles}
isUploading={isUploading}
/>
);
}

AttachmentView.displayName = 'AttachmentView';

export default memo(
withOnyx<AttachmentViewProps, AttachmentViewOnyxProps>({
transaction: {
key: ({transactionID}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
},
})(AttachmentView),
);
export default memo(AttachmentView);

export type {AttachmentViewProps};
2 changes: 1 addition & 1 deletion src/components/HeaderWithBackButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ function HeaderWithBackButton({
/>
)}
{middleContent}
<View style={[styles.reportOptions, styles.flexRow, styles.pr5, styles.alignItemsCenter]}>
<View style={[styles.reportOptions, styles.flexRow, styles.pr5, styles.gap4, styles.alignItemsCenter]}>
{children}
{shouldShowDownloadButton && (
<Tooltip text={translate('common.download')}>
Expand Down
3 changes: 2 additions & 1 deletion src/components/MoneyRequestConfirmationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ function MoneyRequestConfirmationList({
const prevRate = usePrevious(rate);

const currency = (mileageRate as MileageRate)?.currency ?? policyCurrency;
const prevCurrency = usePrevious(currency);

// A flag for showing the categories field
const shouldShowCategories = (isPolicyExpenseChat || isTypeInvoice) && (!!iouCategory || OptionsListUtils.hasEnabledOptions(Object.values(policyCategories ?? {})));
Expand Down Expand Up @@ -292,7 +293,7 @@ function MoneyRequestConfirmationList({
const distance = TransactionUtils.getDistanceInMeters(transaction, unit);
const prevDistance = usePrevious(distance);

const shouldCalculateDistanceAmount = isDistanceRequest && (iouAmount === 0 || prevRate !== rate || prevDistance !== distance);
const shouldCalculateDistanceAmount = isDistanceRequest && (iouAmount === 0 || prevRate !== rate || prevDistance !== distance || prevCurrency !== currency);

const hasRoute = TransactionUtils.hasRoute(transaction, isDistanceRequest);
const isDistanceRequestWithPendingRoute = isDistanceRequest && (!hasRoute || !rate) && !isMovingTransactionFromTrackExpense;
Expand Down
2 changes: 1 addition & 1 deletion src/components/ReportActionItem/MoneyRequestView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ function MoneyRequestView({report, shouldShowAnimatedBackground, readonly = fals
const hasRoute = TransactionUtils.hasRoute(transactionBackup ?? transaction, isDistanceRequest);
const rateID = TransactionUtils.getRateID(transaction) ?? '-1';

const currency = policy ? policy.outputCurrency : PolicyUtils.getPersonalPolicy()?.outputCurrency ?? CONST.CURRENCY.USD;
const currency = transactionCurrency ?? CONST.CURRENCY.USD;

const mileageRate = TransactionUtils.isCustomUnitRateIDForP2P(transaction) ? DistanceRequestUtils.getRateForP2P(currency) : distanceRates[rateID] ?? {};
const {unit} = mileageRate;
Expand Down
25 changes: 16 additions & 9 deletions src/components/Search/SearchRouter/SearchButton.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
import React from 'react';
import type {StyleProp, ViewStyle} from 'react-native';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import {PressableWithoutFeedback} from '@components/Pressable';
import useLocalize from '@hooks/useLocalize';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import Permissions from '@libs/Permissions';
import Performance from '@libs/Performance';
import * as Session from '@userActions/Session';
import Timing from '@userActions/Timing';
import CONST from '@src/CONST';
import {useSearchRouterContext} from './SearchRouterContext';

function SearchButton() {
type SearchButtonProps = {
style?: StyleProp<ViewStyle>;
};

function SearchButton({style}: SearchButtonProps) {
const styles = useThemeStyles();
const theme = useTheme();
const {translate} = useLocalize();
const {openSearchRouter} = useSearchRouterContext();

if (!Permissions.canUseNewSearchRouter()) {
return;
}

return (
<PressableWithoutFeedback
accessibilityLabel={translate('common.search')}
style={[styles.flexRow, styles.touchableButtonImage]}
onPress={() => {
style={[styles.flexRow, styles.touchableButtonImage, style]}
onPress={Session.checkIfActionIsAllowed(() => {
Timing.start(CONST.TIMING.SEARCH_ROUTER_RENDER);
Performance.markStart(CONST.TIMING.SEARCH_ROUTER_RENDER);

openSearchRouter();
}}
})}
>
<Icon
src={Expensicons.MagnifyingGlass}
Expand Down
Loading

0 comments on commit 0c99713

Please sign in to comment.