Skip to content

Commit

Permalink
Merge pull request #10497 from Expensify/update-staging-from-main
Browse files Browse the repository at this point in the history
Update version to 1.1.89-0 on staging
  • Loading branch information
OSBotify authored Aug 23, 2022
2 parents b0af3a3 + 1f0c29b commit 24df24f
Show file tree
Hide file tree
Showing 112 changed files with 192,622 additions and 149,468 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = {
extends: ['expensify', 'plugin:storybook/recommended'],
parser: 'babel-eslint',
ignorePatterns: ['!.*', 'src/vendor', '.github/actions/**/index.js', 'desktop/dist/*.js', 'dist/*.js'],
ignorePatterns: ['!.*', 'src/vendor', '.github/actions/**/index.js', 'desktop/dist/*.js', 'dist/*.js', 'node_modules/.bin/**', '.git/**'],
env: {
jest: true,
},
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/composite/setupNode/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ runs:

- uses: actions/setup-node@09ba51f18e18a3756fea1f54d09c6745c064491d
with:
node-version: 14.19.3
node-version-file: '.nvmrc'
cache: npm

- name: Install node packages
Expand Down
21,045 changes: 11,038 additions & 10,007 deletions .github/actions/javascript/awaitStagingDeploys/index.js

Large diffs are not rendered by default.

2,643 changes: 2,364 additions & 279 deletions .github/actions/javascript/bumpVersion/index.js

Large diffs are not rendered by default.

2,273 changes: 2,183 additions & 90 deletions .github/actions/javascript/checkBundleVersionStringMatch/index.js

Large diffs are not rendered by default.

21,045 changes: 11,038 additions & 10,007 deletions .github/actions/javascript/checkDeployBlockers/index.js

Large diffs are not rendered by default.

30,573 changes: 15,802 additions & 14,771 deletions .github/actions/javascript/createOrUpdateStagingDeploy/index.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ const core = require('@actions/core');
const github = require('@actions/github');
const ActionUtils = require('../../../libs/ActionUtils');
const GitUtils = require('../../../libs/GitUtils');
const GithubUtils = require('../../../libs/GithubUtils');

const octokit = github.getOctokit(core.getInput('GITHUB_TOKEN', {required: true}));
const inputTag = core.getInput('TAG', {required: true});

const isProductionDeploy = ActionUtils.getJSONInput('IS_PRODUCTION_DEPLOY', {required: false}, false);
Expand All @@ -18,13 +18,13 @@ const itemToFetch = isProductionDeploy ? 'release' : 'tag';
*/
function getTagsOrReleases(fetchReleases) {
if (fetchReleases) {
return octokit.repos.listReleases({
return GithubUtils.octokit.repos.listReleases({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
});
}

return octokit.repos.listTags({
return GithubUtils.octokit.repos.listTags({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
});
Expand Down
9,459 changes: 7,287 additions & 2,172 deletions .github/actions/javascript/getDeployPullRequestList/index.js

Large diffs are not rendered by default.

21,045 changes: 11,038 additions & 10,007 deletions .github/actions/javascript/getPullRequestDetails/index.js

Large diffs are not rendered by default.

21,045 changes: 11,038 additions & 10,007 deletions .github/actions/javascript/getReleaseBody/index.js

Large diffs are not rendered by default.

21,045 changes: 11,038 additions & 10,007 deletions .github/actions/javascript/isPullRequestMergeable/index.js

Large diffs are not rendered by default.

21,045 changes: 11,038 additions & 10,007 deletions .github/actions/javascript/isStagingDeployLocked/index.js

Large diffs are not rendered by default.

20,903 changes: 10,967 additions & 9,936 deletions .github/actions/javascript/markPullRequestsAsDeployed/index.js

Large diffs are not rendered by default.

21,045 changes: 11,038 additions & 10,007 deletions .github/actions/javascript/reopenIssueWithComment/index.js

Large diffs are not rendered by default.

21,045 changes: 11,038 additions & 10,007 deletions .github/actions/javascript/triggerWorkflowAndWait/index.js

Large diffs are not rendered by default.

20,903 changes: 10,967 additions & 9,936 deletions .github/actions/javascript/verifySignedCommits/index.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
engine-strict=true
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
16.15.1
3 changes: 2 additions & 1 deletion .storybook/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const env = dotenv.config({path: path.resolve(__dirname, '../.env.staging')}).pa
module.exports = ({config}) => {
config.resolve.alias = {
'react-native-config': 'react-web-config',
'react-native$': 'react-native-web',
'react-native$': '@expensify/react-native-web',
'react-native-web': '@expensify/react-native-web',
'@react-native-community/netinfo': path.resolve(__dirname, '../__mocks__/@react-native-community/netinfo.js'),
};

Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,15 @@
These instructions should get you set up ready to work on New Expensify 🙌

## Getting Started
1. Install `node` & `npm`: `brew install node`
1. Install `nvm` then `node` & `npm`: `brew install nvm && nvm install`
2. Install `watchman`: `brew install watchman`
3. Install dependencies: `npm install`

You can use any IDE or code editing tool for developing on any platform. Use your favorite!

## Recommended `node` setup
In order to have more consistent builds, we use a strict `node` and `npm` version as defined in the `package.json` `engines` field and `.nvmrc` file. `npm install` will fail if you do not use the version defined, so it is recommended to install `node` via `nvm` for easy node version management. Automatic `node` version switching can be installed for [`zsh`](https://github.com/nvm-sh/nvm#zsh) or [`bash`](https://github.com/nvm-sh/nvm#bash) using `nvm`.

## Running the web app 🕸
* To run the **development web app**: `npm run web`
* Changes applied to Javascript will be applied automatically via WebPack as configured in `webpack.dev.js`
Expand All @@ -49,7 +52,6 @@ For an M1 Mac, read this [SO](https://stackoverflow.com/c/expensify/questions/11
* To run a on a **Development Simulator**: `npm run ios`
* Changes applied to Javascript will be applied automatically, any changes to native code will require a recompile


## Running the Android app 🤖
* To install the Android dependencies, run: `npm install`
* Go through the instructions on [this SO post](https://stackoverflow.com/c/expensify/questions/13283/13284#13284) to start running the app on android.
Expand Down Expand Up @@ -93,7 +95,6 @@ variables referenced here get updated since your local `.env` file is ignored.
- `ONYX_METRICS` (optional) - Set this to `true` to capture even more performance metrics and see them in Flipper
see [React-Native-Onyx#benchmarks](https://github.com/Expensify/react-native-onyx#benchmarks) for more information


----

# Running the tests
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001018815
versionName "1.1.88-15"
versionCode 1001018900
versionName "1.1.89-0"
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()

if (isNewArchitectureEnabled()) {
Expand Down
5 changes: 3 additions & 2 deletions config/webpack/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const includeModules = [
'react-native-animatable',
'react-native-reanimated',
'react-native-picker-select',
'react-native-web',
'@expensify/react-native-web',
'react-native-webview',
'@react-native-picker',
'react-native-modal',
Expand Down Expand Up @@ -151,7 +151,8 @@ const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({
resolve: {
alias: {
'react-native-config': 'react-web-config',
'react-native$': 'react-native-web',
'react-native$': '@expensify/react-native-web',
'react-native-web': '@expensify/react-native-web',
'react-content-loader/native': 'react-content-loader',
},

Expand Down
96 changes: 56 additions & 40 deletions contributingGuides/OFFLINE_UX.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#### Offline UX Patterns
# Offline UX Patterns

### Contents
* [Motivation & Philosophy](#motivation-&-philosophy)
* [UX Pattern Flowchart](#ux-pattern-flowchart)
* [Answering Questions on the Flow Chart](#answering-questions-on-the-flowchart)
* [Description of the Patterns](#description-of-the-patterns)
## Contents
* [Motivation & Philosophy](#motivation--philosophy)
* [Description of the Patterns](#descriptions-of-the-ux-patterns)
- [None - No Offline Behavior](#none---no-offline-behavior)
- [A - Optimistic Without Feedback](#a---optimistic-without-feedback)
- [B - Optimistic With Feedback](#b---optimistic-with-feedback)
- [C - Blocking Form](#c---blocking-form)
- [D - Full Page Blocking](#d---full-page-blocking)
- [A - Optimistic Without Feedback](#a---optimistic-without-feedback-pattern)
- [B - Optimistic With Feedback](#b---optimistic-with-feedback-pattern)
- [C - Blocking Form](#c---blocking-form-ui-pattern)
- [D - Full Page Blocking](#d---full-page-blocking-ui-pattern)
* [UX Pattern Flowchart](#ux-pattern-flow-chart)
- [Answering Questions on the Flow Chart](#answering-questions-on-the-flow-chart)

### Motivation & Philosophy
## Motivation & Philosophy

Understanding the offline behavior of our app is vital to becoming a productive contributor to the Expensify codebase. Our mission is to support our users in every possible environment, and often our app is used in places where a stable internet connection is not guaranteed.

Expand All @@ -20,7 +20,7 @@ The most important concept to keep in mind while reading this document is that w
<hr />
Example: Pinning a chat

When a user clicks the pin button <img style="height: 10px; width: 10px;" src="./assets/images/pin.svg"/> on a chat, two things should happen.
When a user clicks the pin button <img style="height: 10px; width: 10px;" src="../assets/images/pin.svg"/> on a chat, two things should happen.

1. **API Request:** We send a request to the API to ensure the change is saved in the database. This way the chat is pinned on all the user's devices, and will remain pinned even if they leave the app and come back.

Expand All @@ -38,9 +38,9 @@ The example we just looked at is nice and simple, but some actions should not us

To handle problems like this, we have developed offline UX patterns and guidance on when to use them. Every feature of this application should fit into one of these patterns.

### Descriptions of the UX Patterns
## Descriptions of the UX Patterns

# None - No Offline Behavior
### None - No Offline Behavior

There’s no specific UI for this case. The feature either looks totally normal and works as expected (because it doesn’t need the server to function) or the feature looks like it did whenever connection was lost.

Expand All @@ -50,7 +50,9 @@ There’s no specific UI for this case. The feature either looks totally normal

**How to implement:** Use [`API.read()`](https://github.com/Expensify/App/blob/3493f3ca3a1dc6cdbf9cb8bd342866fcaf45cf1d/src/libs/API.js#L53-L55).

# A - Optimistic Without Feedback Pattern
**Example:** The `About` page.

### A - Optimistic Without Feedback Pattern

This is the pattern where we queue the request to be sent when the user is online and we continue as if the request succeeded.

Expand All @@ -60,16 +62,34 @@ This is the pattern where we queue the request to be sent when the user is onlin

**How to implement:** Use [`API.write()`](https://github.com/Expensify/App/blob/3493f3ca3a1dc6cdbf9cb8bd342866fcaf45cf1d/src/libs/API.js#L7-L28) to implement this pattern. For this pattern we should only put `optimisticData` in the options. We don't need successData or failData as we don't care what response comes back at all.

# B - Optimistic WITH Feedback Pattern
This pattern queues the API request, but also makes sure that the user is aware that the request hasn’t been sent yet **when the user is offline**. When the user is online, the feature should just look like it succeeds immediately (we dont want the offline UI to flicker on and off when the user is online).
**Example:** Pinning a chat.

### B - Optimistic WITH Feedback Pattern
This pattern queues the API request, but also makes sure that the user is aware that the request hasn’t been sent yet **when the user is offline**.
When the user is online, the feature should just look like it succeeds immediately (we don't want the offline UI to flicker on and off when the user is online).
When the user is offline:
- Things pending to be created or updated will be shown greyed out (0.5 opacity)
- Things pending to be deleted will be shown greyed out and have strikethrough

**Used when…**
- the user needs feedback that data will be sent to the server later
This is a minority use case at the moment, but INCREDIBLY HELPFUL for the user, so proceed with cautious optimism.
- The user needs feedback that data will be sent to the server later. This is a minority use case at the moment, but INCREDIBLY HELPFUL for the user, so proceed with cautious optimism.

**How to implement:**
- Use API.write() to implement this pattern
- Optimistic data should include `pendingAction` ([with these possible values](https://github.com/Expensify/App/blob/15f7fa622805ee2971808d6bc67181c4715f0c62/src/CONST.js#L775-L779))
- To ensure the UI is shown as described above, you should enclose the components that contain the data that was added/updated/deleted with the OfflineWithFeedback component

**Handling errors:**
- The [OfflineWithFeedback component](https://github.com/Expensify/App/blob/main/src/components/OfflineWithFeedback.js) already handles showing errors too, as long as you pass the error field in the [errors prop](https://github.com/Expensify/App/blob/128ea378f2e1418140325c02f0b894ee60a8e53f/src/components/OfflineWithFeedback.js#L29-L31)
- When dismissing the error, the onClose prop will be called, there we need to call an action that either:
- If the pendingAction was `delete`, it removes the data altogether
- Otherwise, it would clear the errors and pendingAction properties from the data
- We also need to show a Red Brick Road (RBR) guiding the user to the error. We need to manually do this for each piece of data using pattern B Optimistic WITH Feedback. Some common components like `MenuItem` already have a prop for it (`brickRoadIndicator`)
- A Brick Road is the pattern of guiding members towards places that require their attention by following a series of UI elements that have the same color

**How to implement:** Use API.write() to implement this pattern. Optimistic data should include some pending state for the action that is reflected in the UI. Success/failure data should revert the pending state and/or set a failure state accordingly.
**Example:** Sending a chat message.

# C - Blocking Form UI Pattern
### C - Blocking Form UI Pattern
This pattern greys out the submit button on a form and does not allow the form to be submitted. We also show a "You appear offline" message near the bottom of the screen. Importantly, we _do_ let the user fill out the form fields. That data gets saved locally so they don’t have to fill it out again once online.

**Used when…**
Expand All @@ -80,18 +100,22 @@ This pattern greys out the submit button on a form and does not allow the form t

**How to implement:** Use the `<FormAlertWithSubmitButton/>` component. This pattern should use the `API.write()` method.

# D - Full Page Blocking UI Pattern
**Example:** Inviting new memebers to a workspace.

### D - Full Page Blocking UI Pattern
This pattern blocks the user from interacting with an entire page.

**Used when…**
- blocking READ is being performed. This occurs when the data that a user sees cannot be stale data and the data can only be displayed after fetching it from the server (eg. Plaid's list of bank accounts)
- blocking READ is being performed. This occurs when the data that a user sees cannot be stale data and the data can only be displayed after fetching it from the server
- the app is offline and the data cannot be fetched
- an error occurs when fetching the data and the user needs instructions on what to do next
This should only be used in the most extreme cases when all other options have been completely and utterly exhausted

**How to implement:** Wrap the component you're working on in a `<FullPageOfflineBlockingView>` component.

### UX Pattern Flow Chart
**Example:** Getting the list of bank accounts the user owns from Plaid (an external service).

## UX Pattern Flow Chart

The following flowchart can be used to determine which UX pattern should be used.

Expand All @@ -102,32 +126,24 @@ The following flowchart can be used to determine which UX pattern should be used
The numbers in this section correlate to the numbers in each decision box above (the diamond shapes).

1. Does the feature interact with the server?

If you're changing an existing feature, you can open the network tab of dev tools to see if any network requests are being made when you use the feature. If network requests are being made, the answer to this question is YES. Note: Sometimes you may see requests that happen to fire at the same time as the feature you're working on, so be sure to double check.
- If you're changing an existing feature, you can open the network tab of dev tools to see if any network requests are being made when you use the feature. If network requests are being made, the answer to this question is YES. Note: Sometimes you may see requests that happen to fire at the same time as the feature you're working on, so be sure to double check.
If you're making a new feature, think about whether any data would need to be retrieved or stored from anywhere other than the local device. If data needs to be stored to or retrieved from the server, then the answer is YES.

2. What type of request is being made?

If there's new data being saved on the server, you're making a WRITE request. If you're retrieving existing data from the server, you're making a READ request. If both things are happening, that's a WRITE request.
- If there's new data being saved on the server, you're making a WRITE request. If you're retrieving existing data from the server, you're making a READ request. If both things are happening, that's a WRITE request.

3. Is it OK for the user to see stale data?

Example: The payment method list. We don't want the user to see a payment method that we no longer support, not even while the payment methods are being loaded from the server (or while the user is offline). Therefore, we answer NO, which leads us to the blocking UI. This way the user won't see stale data while we load the payment methods.
- Example: The payment method list. We don't want the user to see a payment method that we no longer support, not even while the payment methods are being loaded from the server (or while the user is offline). Therefore, we answer NO, which leads us to the blocking UI. This way the user won't see stale data while we load the payment methods.

4. Is the UI a form?

An easy way to tell if something is a form is to try and find a submit button. If a submit button is present or if the user is filling out form inputs, answer YES to this question.
- An easy way to tell if something is a form is to try and find a submit button. If a submit button is present or if the user is filling out form inputs, answer YES to this question.

5. Can the server response be anticipated?

Answer NO if there is data coming back from the server that we can't know (example: a list of bank accounts from Plaid, input validation that the server must perform). Answer YES if we can know what the response from the server would be.
- Answer NO if there is data coming back from the server that we can't know (example: a list of bank accounts from Plaid, input validation that the server must perform). Answer YES if we can know what the response from the server would be.

6. Is there validation done on the server that can't be done on the front end?

If there is some validation happening on the server that needs to happen before the feature can work, then we answer YES to this question. Remember, this is referring to validation that cannot happen on the front end (e.g. reusing an existing password when resetting a password). For example, if we want to set up a bank account then our answer to this question is YES (because we can’t suggest to the user that their request succeeded when really it hasn’t been sent yet–their card wouldn’t work!)

This question can be tricky, so if you're unsure, please ask a question in the #expensify-open-source slack room and tag @contributor-management-engineering.
- If there is some validation happening on the server that needs to happen before the feature can work, then we answer YES to this question. Remember, this is referring to validation that cannot happen on the front end (e.g. reusing an existing password when resetting a password). For example, if we want to set up a bank account then our answer to this question is YES (because we can’t suggest to the user that their request succeeded when really it hasn’t been sent yet–their card wouldn’t work!)
- This question can be tricky, so if you're unsure, please ask a question in the #expensify-open-source slack room and tag @contributor-management-engineering.

7. Does the user need to know if the action was successful?

Think back to the pinning example from above: the user doesn’t need to know that their pinned report's NVP has been updated. To them the impact of clicking the pin button is that their chat is at the top of the LHN. It makes no difference to them if the server has been updated or not, so the answer would be NO. Now let’s consider sending a payment request to another user. In this example, the user needs to know if their request was actually sent, so our answer is YES.
- Think back to the pinning example from above: the user doesn’t need to know that their pinned report's NVP has been updated. To them the impact of clicking the pin button is that their chat is at the top of the LHN. It makes no difference to them if the server has been updated or not, so the answer would be NO. Now let’s consider sending a payment request to another user. In this example, the user needs to know if their request was actually sent, so our answer is YES.
Loading

0 comments on commit 24df24f

Please sign in to comment.