Skip to content

Commit

Permalink
Merge branch 'main' into chat-transition-optimisation-proposal
Browse files Browse the repository at this point in the history
  • Loading branch information
kacper-mikolajczak committed Oct 4, 2023
2 parents 86ee246 + fb9c763 commit 72ee59a
Show file tree
Hide file tree
Showing 180 changed files with 4,580 additions and 1,807 deletions.
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ module.exports = {
{
files: ['*.js', '*.jsx', '*.ts', '*.tsx'],
rules: {
'rulesdir/no-multiple-onyx-in-file': 'off',
'rulesdir/onyx-props-must-have-default': 'off',
'react-native-a11y/has-accessibility-hint': ['off'],
'react-native-a11y/has-valid-accessibility-descriptors': [
Expand Down Expand Up @@ -163,6 +164,7 @@ module.exports = {
},
],
curly: 'error',
'you-dont-need-lodash-underscore/throttle': 'off',
},
},
{
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/e2ePerformanceTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ jobs:
run: cat "./Host_Machine_Files/\$WORKING_DIRECTORY/debug.log"

- name: Check if test failed, if so post the results and add the DeployBlocker label
if: ${{ github.event_name == 'workflow_call' }}
run: |
if grep -q '🔴' ./Host_Machine_Files/\$WORKING_DIRECTORY/output.md; then
gh pr edit ${{ inputs.PR_NUMBER }} --add-label DeployBlockerCash
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ For an M1 Mac, read this [SO](https://stackoverflow.com/questions/64901180/how-t
* If you get the error `Could not find 'bundler'`, install the bundler gem first: `gem install bundler` and try again.
* If you are using MacOS and get the error `Gem::FilePermissionError` when trying to install the bundler gem, you're likely using system Ruby, which requires administrator permission to modify. To get around this, install another version of Ruby with a version manager like [rbenv](https://github.com/rbenv/rbenv#installation).
* Before installing iOS dependencies, you need to obtain a token from Mapbox to download their SDKs. Please run `npm run configure-mapbox` and follow the instructions.
* For help with MapBox token, you can see [this Slack thread](https://expensify.slack.com/archives/C01GTK53T8Q/p1692740856745279?thread_ts=1692322511.804599&cid=C01GTK53T8Q)
* To install the iOS dependencies, run: `npm install && npm run pod-install`
* If you are an Expensify employee and want to point the emulator to your local VM, follow [this](https://stackoverflow.com/c/expensify/questions/7699)
* To run a on a **Development Simulator**: `npm run ios`
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001037510
versionName "1.3.75-10"
versionCode 1001037705
versionName "1.3.77-5"
}

flavorDimensions "default"
Expand Down
1 change: 1 addition & 0 deletions android/app/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/>
<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning">
<meta-data
android:name="firebase_performance_logcat_enabled"
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/>

<!-- android:hardwareAccelerated is essential for Android performance: https://developer.android.com/topic/performance/hardware-accel -->
<application
Expand Down
64 changes: 43 additions & 21 deletions contributingGuides/FORMS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ This document lists specific guidelines for using our Form component and general

## General Form UI/UX

### Inputs
Any form input needs to be wrapped in [InputWrapper](https://github.com/Expensify/App/blob/029d009731dcd3c44cd1321672b9672ef0d3d7d9/src/components/Form/InputWrapper.js) and passed as `InputComponent` property additionally it's necessary po pass an unique `inputID`. All other props of the input can be passed as `InputWrapper` props.
```jsx
<InputWrapper
// `InputWrapper` required props
InputComponent={TextInput}
inputID="uniqueTextInputID"
// `TextInput` specific props
placeholder="Text input placeholder"
label="Text input label"
shouldSaveDraft
/>
```

### Labels, Placeholders, & Hints

Labels are required for each input and should clearly mark the field. Optional text may appear below a field when a hint, suggestion, or context feels necessary. If validation fails on such a field, its error should clearly explain why without relying on the hint. Inline errors should always replace the microcopy hints. Placeholders should not be used as it’s customary for labels to appear inside form fields and animate them above the field when focused.
Expand All @@ -13,7 +27,8 @@ Labels are required for each input and should clearly mark the field. Optional t
Labels and hints are enabled by passing the appropriate props to each input:

```jsx
<TextInput
<InputWrapper
InputComponent={TextInput}
label="Value"
hint="Hint text goes here"
/>
Expand All @@ -24,7 +39,8 @@ Labels and hints are enabled by passing the appropriate props to each input:
If a field has a character limit we should give that field a max limit. This is done by passing the maxLength prop to TextInput.

```jsx
<TextInput
<InputWrapper
InputComponent={TextInput}
maxLength={20}
/>
```
Expand All @@ -42,7 +58,8 @@ We should always set people up for success on native platforms by enabling the b
We have a couple of keyboard types [defined](https://github.com/Expensify/App/blob/572caa9e7cf32a2d64fe0e93d171bb05a1dfb217/src/CONST.js#L357-L360) and should be used like so:

```jsx
<TextInput
<InputWrapper
InputComponent={TextInput}
keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD}
/>
```
Expand All @@ -56,7 +73,8 @@ As a best practice we should avoid asking for information we can get via other m
Browsers use the name prop to autofill information into the input. Here's a [reference](https://developers.google.com/web/fundamentals/design-and-ux/input/forms#recommended_input_name_and_autocomplete_attribute_values) for available values for the name prop.

```jsx
<TextInput
<InputWrapper
InputComponent={TextInput}
name="fname"
/>
```
Expand Down Expand Up @@ -91,7 +109,7 @@ To give a slightly more detailed example of how this would work with phone numbe
Form inputs will NOT store draft values by default. This is to avoid accidentally storing any sensitive information like passwords, SSN or bank account information. We need to explicitly tell each form input to save draft values by passing the shouldSaveDraft prop to the input. Saving draft values is highly desirable and we should always try to save draft values. This way when a user continues a given flow they can easily pick up right where they left off if they accidentally exited a flow. Inputs with saved draft values [will be cleared when a user logs out](https://github.com/Expensify/App/blob/aa1f0f34eeba5d761657168255a1ae9aebdbd95e/src/libs/actions/SignInRedirect.js#L52) (like most data). Additionally, we should clear draft data once the form is successfully submitted by calling `Onyx.set(ONYXKEY.FORM_ID, null)` in the onSubmit callback passed to Form.

```jsx
<TextInput
<InputWrapper
shouldSaveDraft
/>
```
Expand Down Expand Up @@ -178,9 +196,9 @@ Submit buttons shall not be disabled or blocked from being pressed in most cases

The only time we won’t allow a user to press the submit button is when we have submitted the form and are waiting for a response (e.g. from the API). In this case we will show a loading indicator and additional taps on the submit button will have no effect. This is handled by the Form component and will also ensure that a form cannot be submitted multiple times.

## Using Form.js
## Using Form

The example below shows how to use [Form.js](https://github.com/Expensify/App/blob/c5a84e5b4c0b8536eed2214298a565e5237a27ca/src/components/Form.js) in our app. You can also refer to [Form.stories.js](https://github.com/Expensify/App/blob/c5a84e5b4c0b8536eed2214298a565e5237a27ca/src/stories/Form.stories.js) for more examples.
The example below shows how to use [FormProvider](https://github.com/Expensify/App/blob/029d009731dcd3c44cd1321672b9672ef0d3d7d9/src/components/Form/FormProvider.js) and [InputWrapper](https://github.com/Expensify/App/blob/029d009731dcd3c44cd1321672b9672ef0d3d7d9/src/components/Form/InputWrapper.js) in our app. You can also refer to [Form.stories.js](https://github.com/Expensify/App/blob/c5a84e5b4c0b8536eed2214298a565e5237a27ca/src/stories/Form.stories.js) for more examples.

```jsx
function validate(values) {
Expand All @@ -201,43 +219,47 @@ function onSubmit(values) {
}, 1000);
}

<Form
<FormProvider
formID="testForm"
submitButtonText="Submit"
validate={this.validate}
onSubmit={this.onSubmit}
>
// Wrapping TextInput in a View to show that Form inputs can be nested in other components
// Wrapping InputWrapper in a View to show that Form inputs can be nested in other components
<View>
<TextInput
<InputWrapper
InputComponent={TextInput}
label="Routing number"
inputID="routingNumber"
maxLength={8}
shouldSaveDraft
/>
</View>
<TextInput
<InputWrapper
InputComponent={TextInput}
label="Account number"
inputID="accountNumber"
containerStyles={[styles.mt4]}
/>
</Form>
</FormProvider>
```

`Form.js` also works with inputs nested in a custom component, e.g. [AddressForm](https://github.com/Expensify/App/blob/86579225ff30b21dea507347735259637a2df461/src/pages/ReimbursementAccount/AddressForm.js). The only exception is that the nested component shouldn't be wrapped around any HoC.
`FormProvider` also works with inputs nested in a custom component, e.g. [AddressForm](https://github.com/Expensify/App/blob/86579225ff30b21dea507347735259637a2df461/src/pages/ReimbursementAccount/AddressForm.js). The only exception is that the nested component shouldn't be wrapped around any HoC and all inputs in the component needs to be wrapped with `InputWrapper`.

```jsx
const BankAccountForm = () => (
<>
<View>
<TextInput
<InputWrapper
InputComponent={TextInput}
label="Routing number"
inputID="routingNumber"
maxLength={8}
shouldSaveDraft
/>
</View>
<TextInput
<InputWrapper
InputComponent={TextInput}
label="Account number"
inputID="accountNumber"
containerStyles={[styles.mt4]}
Expand All @@ -246,14 +268,14 @@ const BankAccountForm = () => (
);

// ...
<Form
<FormProvider
formID="testForm"
submitButtonText="Submit"
validate={this.validate}
onSubmit={this.onSubmit}
>
<BankAccountForm />
</Form>
</FormProvider>
```

### Props provided to Form inputs
Expand All @@ -266,7 +288,7 @@ The following prop is available to form inputs:
- value: The value to show for the input.
- onValueChange: A callback that is called when the input's value changes.

Form.js will automatically provide the following props to any input with the inputID prop.
InputWrapper component will automatically provide the following props to any input with the inputID prop.

- ref: A React ref that must be attached to the input.
- value: The input value.
Expand All @@ -287,13 +309,13 @@ An example of this can be seen in the [ACHContractStep](https://github.com/Expen

### Safe Area Padding

Any `Form.js` that has a button will also add safe area padding by default. If the `<Form/>` is inside a `<ScreenWrapper>` we will want to disable the default safe area padding applied there e.g.
Any `FormProvider.js` that has a button will also add safe area padding by default. If the `<FormProvider>` is inside a `<ScreenWrapper>` we will want to disable the default safe area padding applied there e.g.

```js
<ScreenWrapper includeSafeAreaPaddingBottom={false}>
<Form>
<FormProvider>
{...}
</Form>
</FormProvider>
</ScreenWrapper>
```

Expand Down
2 changes: 1 addition & 1 deletion docs/_config.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
title: Expensify Help
tagline: Expensify Help - all your Expensify questions answered in one place.
description: Got a question about receipts, expenses, corporate cards, or anything else in the spend management universe? Get answers at help.expensify.com.
url: help.expensify.com
url: https://help.expensify.com
author: Expensify
logo: /assets/images/expensify-help.svg
open_url: true
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
title: International Reimbursements
description: International Reimbursements
---
# Overview

If your company’s business bank account is in the US, Canada, the UK, Europe, or Australia, you now have the option to send direct reimbursements to nearly any country across the globe!
The process to enable global reimbursements is dependent on the currency of your reimbursement bank account, so be sure to review the corresponding instructions below.

# How to request international reimbursements

## The reimbursement account is in USD

If your reimbursement bank account is in USD, the first step is connecting the bank account to Expensify.
The individual who plans on sending reimbursements internationally should head to **Settings > Account > Payments > Add Verified Bank Account**. From there, you will provide company details, input personal information, and upload a copy of your ID.

Once the USD bank account is verified (or if you already had a USD business bank account connected), click the support icon in your Expensify account to inform your Setup Specialist, Account Manager, or Concierge that you’d like to enable international reimbursements. From there, Expensify will ask you to confirm the currencies of the reimbursement and employee bank accounts.

Our team will assess your account, and if you meet the criteria, international reimbursements will be enabled.

## The reimbursement account is in AUD, CAD, GBP, EUR

To request international reimbursements, contact Expensify Support to make that request.

You can do this by clicking on the support icon and informing your Setup Specialist, Account Manager, or Concierge that you’d like to set up global reimbursements on your account.
From there, Expensify will ask you to confirm both the currencies of the reimbursement and employee bank accounts.

Our team will assess your account, and if you meet the criteria, international reimbursements will be enabled.

# How to verify the bank account for sending international payments

Once international payments are enabled on your Expensify account, the next step is verifying the bank account to send the reimbursements.

## The reimbursement account is in USD

First, confirm the workspace settings are set up correctly by doing the following:
1. Head to **Settings > Workspaces > Group > _[Workspace Name]_ > Reports** and check that the workspace currency is USD
2. Under **Settings > Workspaces > Group > _[Workspace Name]_ > Reimbursements**, set the reimbursement method to direct
3. Under **Settings > Workspaces > Group > _[Workspace Name]_ > Reimbursements**, set the USD bank account to the default account

Once that’s all set, head to **Settings > Account > Payments**, and click **Enable Global Reimbursement** on the bank account (this button may not show for up to 60 minutes after the Expensify team confirms international reimbursements are available on your account).

From there, you’ll fill out a form via DocuSign. Once the form is complete, it is automatically sent to our Compliance Team for review. Our Support Team will contact you with more details if additional information is required.

## The reimbursement account is in AUD, CAD, GBP, EUR

First, confirm the workspace currency corresponds with the currency of the reimbursement bank account. You can do this under **Settings > Workspaces > Group > _[Workspace Name]_ > Reports**. It should be AUD, CAD, GBP, or EUR.

Next, add the bank account to Expensify:
1. Head to **Settings > Workspaces > Group > _[Workspace Name]_ > Reimbursements** and set the reimbursement method to direct (this button may not show for up to 60 minutes after the Expensify team confirms international reimbursements are available on your account)
2. Click **Add Business Bank Account**
3. If the incorrect country shows as the default, click **Switch Country** to select the correct country
4. Enter the bank account details
5. Click **Save & Continue**

From there, you’ll fill out a form via DocuSign. Once the form is complete, it is automatically sent to our Compliance Team for review. Our Support Team will contact you with more details if additional information is required.

# How to start reimbursing internationally

After the bank account is verified for international payments, set the correct bank account as the reimbursement account.

You can do this under **Settings > Workspaces > Group > _[Workspace Name]_ > Reimbursements** by selecting the reimbursement account as the default account.

Finally, have your employees add their deposit-only bank accounts. They can do this by logging into their Expensify accounts, heading to **Settings > Account > Payments**, and clicking **Add Deposit-Only Bank Account**.

# Deep Dive

## Documents requested

Our Compliance Team may ask for additional information depending on who initiates the verification or what information you provide on the DocuSign form.

Examples of additional requested information:
- The reimburser’s proof of address and ID
- Company directors’ proofs of address and IDs
- An authorization letter
- An independently certified documentation such as shareholder agreement from a lawyer, notary, or public accountant if an individual owns more than 25% of the company

# FAQ

## How many people can send reimbursements internationally?

Once your company is authorized to send global payments, only the individual who went through the verification can reimburse international employees.

## How long does it take to verify an account for international payments?

It varies! The verification process can take a few business days to several weeks. It depends on whether or not the information in the DocuSign form is correct if our Compliance Team requires any additional information, and how responsive the employee verifying the company’s details is to our requests.

## If I already have a USD bank account connected to Expensify, do I need to go through the verification process again to enable international payments?

If you’ve already connected a US business bank account, you can request to enable global reimbursements by contacting Expensify Support immediately. However, additional steps are required to verify the bank account for international payments.

## My employee says they don’t have the option to add their non-USD bank account as a deposit account – what should they do?

Have the employee double-check that their default workspace is set as the workspace that's connected to the bank you're using to send international payments.

An employee can confirm their default workspace is under **Settings > Workspaces > Group**. The default workspace has a green checkmark next to it. They can change their default workspace by clicking **Default Workspace** on the correct workspace.

## Who is the “Authorized User” on the International Reimbursement DocuSign form?

This is the person who will process international reimbursements. The authorized user should be the same person who manages the bank account connection in Expensify.

## Who should I enter as the “User” on the International Reimbursement form?

You can leave this form section blank since the “User” is Expensify.

Loading

0 comments on commit 72ee59a

Please sign in to comment.