diff --git a/.eslintrc.js b/.eslintrc.js
index c4b91cd6c3d4..d5d9d8a2fa0a 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,4 +1,7 @@
module.exports = {
extends: 'expensify',
parser: 'babel-eslint',
+ rules: {
+ "react/jsx-filename-extension": [1, {"extensions": [".js"]}],
+ },
};
diff --git a/package-lock.json b/package-lock.json
index 43f0eb5ff392..c6cdf54af695 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5532,6 +5532,69 @@
"resolve": "^1.13.1"
}
},
+ "eslint-loader": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-4.0.2.tgz",
+ "integrity": "sha512-EDpXor6lsjtTzZpLUn7KmXs02+nIjGcgees9BYjNkWra3jVq5vVa8IoCKgzT2M7dNNeoMBtaSG83Bd40N3poLw==",
+ "dev": true,
+ "requires": {
+ "find-cache-dir": "^3.3.1",
+ "fs-extra": "^8.1.0",
+ "loader-utils": "^2.0.0",
+ "object-hash": "^2.0.3",
+ "schema-utils": "^2.6.5"
+ },
+ "dependencies": {
+ "find-cache-dir": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz",
+ "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^3.0.2",
+ "pkg-dir": "^4.1.0"
+ }
+ },
+ "loader-utils": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
+ "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
+ "dev": true,
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^2.1.2"
+ }
+ },
+ "make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "requires": {
+ "semver": "^6.0.0"
+ }
+ },
+ "schema-utils": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
+ "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
+ "dev": true,
+ "requires": {
+ "@types/json-schema": "^7.0.4",
+ "ajv": "^6.12.2",
+ "ajv-keywords": "^3.4.1"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
"eslint-module-utils": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz",
@@ -10737,6 +10800,12 @@
}
}
},
+ "object-hash": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.0.3.tgz",
+ "integrity": "sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg==",
+ "dev": true
+ },
"object-inspect": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
diff --git a/package.json b/package.json
index b97da38637f5..4c8aa9e1a702 100644
--- a/package.json
+++ b/package.json
@@ -40,6 +40,7 @@
"clean-webpack-plugin": "^3.0.0",
"eslint": "^7.6.0",
"eslint-config-expensify": "^2.0.11",
+ "eslint-loader": "^4.0.2",
"html-webpack-plugin": "^4.3.0",
"jest": "^26.2.2",
"metro-react-native-babel-preset": "^0.61.0",
diff --git a/src/App.js b/src/App.js
index 6fedeedafd79..92d45b2cdc51 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,4 +1,4 @@
-import Expensify from './Expensify';
import React from 'react';
+import Expensify from './Expensify';
export default () => ;
diff --git a/src/Expensify.js b/src/Expensify.js
index 18a219c964d3..306b7c468529 100644
--- a/src/Expensify.js
+++ b/src/Expensify.js
@@ -1,22 +1,24 @@
-import {init as StoreInit} from './store/Store';
+import React, {Component} from 'react';
import SignInPage from './page/SignInPage';
import HomePage from './page/HomePage/HomePage';
import * as Store from './store/Store';
import * as ActiveClientManager from './lib/ActiveClientManager';
import {verifyAuthToken} from './store/actions/SessionActions';
import STOREKEYS from './store/STOREKEYS';
-import React, {Component} from 'react';
-import {Route, Router, Redirect, Switch} from './lib/Router';
+import {
+ Route,
+ Router,
+ Redirect,
+ Switch
+} from './lib/Router';
// Initialize the store when the app loads for the first time
-StoreInit();
+Store.init();
export default class Expensify extends Component {
constructor(props) {
super(props);
- this.sessionChanged = this.sessionChanged.bind(this);
-
this.state = {
redirectTo: null,
};
@@ -33,21 +35,13 @@ export default class Expensify extends Component {
// Initialize this client as being an active client
await ActiveClientManager.init();
- //TODO: Refactor window events
+
+ // TODO: Refactor window events
// window.addEventListener('beforeunload', () => {
// ActiveClientManager.removeClient();
// });
}
- /**
- * When the session changes, change which page the user sees
- *
- * @param {object} newSession
- */
- sessionChanged(newSession) {
- this.setState({isAuthTokenValid: newSession && newSession.authToken});
- }
-
render() {
return (
diff --git a/src/lib/ActiveClientManager.js b/src/lib/ActiveClientManager.js
index 99f679aae680..dabd2958f4eb 100644
--- a/src/lib/ActiveClientManager.js
+++ b/src/lib/ActiveClientManager.js
@@ -18,9 +18,7 @@ const init = async () => {
*/
function removeClient() {
const activeClientIDs = Store.get(STOREKEYS.ACTIVE_CLIENT_IDS) || [];
- const newActiveClientIDs = activeClientIDs.filter(
- (activeClientID) => activeClientID !== clientID,
- );
+ const newActiveClientIDs = activeClientIDs.filter(activeClientID => activeClientID !== clientID);
Store.set(STOREKEYS.ACTIVE_CLIENT_IDS, newActiveClientIDs);
}
diff --git a/src/lib/Network.js b/src/lib/Network.js
index e90f2b65cd18..f915b6318a4e 100644
--- a/src/lib/Network.js
+++ b/src/lib/Network.js
@@ -21,14 +21,12 @@ function request(command, data, type = 'post') {
_.each(data, (val, key) => formData.append(key, val));
return formData;
})
- .then(formData => fetch(
- `${CONFIG.EXPENSIFY.API_ROOT}command=${command}`,
- {
- method: type,
- body: formData,
- },
- ))
+ .then(formData => fetch(`${CONFIG.EXPENSIFY.API_ROOT}command=${command}`, {
+ method: type,
+ body: formData,
+ }))
.then(response => response.json())
+ // eslint-disable-next-line no-unused-vars
.catch(() => isAppOffline = true);
}
@@ -56,27 +54,27 @@ function delayedWrite(command, data) {
/**
* Process the write queue by looping through the queue and attempting to make the requests
*/
-function processWriteQueue() {
- if (isAppOffline) {
- // Make a simple request to see if we're online again
- request('Get', null, 'get')
- .then(() => isAppOffline = false);
- return;
- }
-
- if (delayedWriteQueue.length === 0) {
- return;
- }
-
- _.each(delayedWriteQueue, (delayedWriteRequest) => {
- request(delayedWriteRequest.command, delayedWriteRequest.data)
- .then(delayedWriteRequest.callback)
- .catch(() => {
- // If the request failed, we need to put the request object back into the queue
- delayedWriteQueue.push(delayedWriteRequest);
- });
- });
-}
+// function processWriteQueue() {
+// if (isAppOffline) {
+// // Make a simple request to see if we're online again
+// request('Get', null, 'get')
+// .then(() => isAppOffline = false);
+// return;
+// }
+//
+// if (delayedWriteQueue.length === 0) {
+// return;
+// }
+//
+// _.each(delayedWriteQueue, (delayedWriteRequest) => {
+// request(delayedWriteRequest.command, delayedWriteRequest.data)
+// .then(delayedWriteRequest.callback)
+// .catch(() => {
+// // If the request failed, we need to put the request object back into the queue
+// delayedWriteQueue.push(delayedWriteRequest);
+// });
+// });
+// }
// TODO: Figure out setInterval
// Process our write queue very often
diff --git a/src/lib/PersistentStorage.js b/src/lib/PersistentStorage.js
index c748ab644710..0416366dcbf4 100644
--- a/src/lib/PersistentStorage.js
+++ b/src/lib/PersistentStorage.js
@@ -13,14 +13,9 @@ import _ from 'underscore';
*/
function get(key) {
return AsyncStorage.getItem(key)
- .then(val => {
- const jsonValue = JSON.parse(val);
- return jsonValue;
- })
- .catch(err => {
- console.error(`Unable to get item from persistent storage. Key: ${key} Error: ${err}`);
- });
-};
+ .then(val => JSON.parse(val))
+ .catch(err => console.error(`Unable to get item from persistent storage. Key: ${key} Error: ${err}`));
+}
/**
* Get the data for multiple keys
@@ -38,9 +33,7 @@ function multiGet(keys) {
...finalData,
[keyValuePair[0]]: JSON.parse(keyValuePair[1]),
}), {}))
- .catch((err) => {
- console.error(`Unable to get item from persistent storage. Keys: ${JSON.stringify(keys)} Error: ${err}`);
- });
+ .catch(err => console.error(`Unable to get item from persistent storage. Keys: ${JSON.stringify(keys)} Error: ${err}`));
}
/**
@@ -52,7 +45,7 @@ function multiGet(keys) {
*/
function set(key, val) {
return AsyncStorage.setItem(key, JSON.stringify(val));
-};
+}
/**
* Set multiple keys at once
@@ -79,7 +72,7 @@ function multiSet(data) {
*/
function clear() {
return AsyncStorage.clear();
-};
+}
/**
* Merges `val` into an existing key. Best used when updating an existing object
diff --git a/src/lib/Router/index.js b/src/lib/Router/index.js
index 524ccb8fddf1..02a430d7d165 100644
--- a/src/lib/Router/index.js
+++ b/src/lib/Router/index.js
@@ -7,4 +7,11 @@ import {
withRouter,
} from 'react-router-dom';
-export {Link, Route, Redirect, Router, Switch, withRouter};
+export {
+ Link,
+ Route,
+ Redirect,
+ Router,
+ Switch,
+ withRouter
+};
diff --git a/src/lib/Router/index.native.js b/src/lib/Router/index.native.js
index 860751fae08c..6dc3bd65b969 100644
--- a/src/lib/Router/index.native.js
+++ b/src/lib/Router/index.native.js
@@ -7,4 +7,11 @@ import {
withRouter,
} from 'react-router-native';
-export {Link, Route, Redirect, Router, Switch, withRouter};
+export {
+ Link,
+ Route,
+ Redirect,
+ Router,
+ Switch,
+ withRouter
+};
diff --git a/src/page/HomePage/HomePage.js b/src/page/HomePage/HomePage.js
index 534654ca7b57..f69b28678615 100644
--- a/src/page/HomePage/HomePage.js
+++ b/src/page/HomePage/HomePage.js
@@ -2,9 +2,14 @@
* @format
* @flow strict-local
*/
-
import React, {Component} from 'react';
-import {SafeAreaView, Text, StatusBar, View, Button} from 'react-native';
+import {
+ SafeAreaView,
+ Text,
+ StatusBar,
+ View,
+ Button
+} from 'react-native';
import {signOut} from '../../store/actions/SessionActions';
export default class App extends Component {
@@ -30,10 +35,11 @@ export default class App extends Component {
margin: 20,
textAlign: 'center',
fontWeight: 'bold',
- }}>
- {'React Native Chat Homepage!'}
+ }}
+ >
+ React Native Chat Homepage!
-
+
>
diff --git a/src/page/SignInPage.js b/src/page/SignInPage.js
index 96ebbdbd0234..80cc4e111b48 100644
--- a/src/page/SignInPage.js
+++ b/src/page/SignInPage.js
@@ -26,6 +26,7 @@ export default class App extends Component {
this.state = {
login: '',
password: '',
+ // eslint-disable-next-line react/no-unused-state
error: Store.get(STOREKEYS.SESSION, 'error'),
};
}
@@ -45,6 +46,7 @@ export default class App extends Component {
* @param {object} newSession
*/
sessionChanged(newSession) {
+ // eslint-disable-next-line react/no-unused-state
this.setState({error: newSession && newSession.error});
}
@@ -65,20 +67,20 @@ export default class App extends Component {
this.setState({login: text})}
+ onChangeText={text => this.setState({login: text})}
/>
Password:
this.setState({password: text})}
+ onChangeText={text => this.setState({password: text})}
/>
-
+
>
diff --git a/src/store/Store.js b/src/store/Store.js
index 8f85df6a9015..d2c1172e342a 100644
--- a/src/store/Store.js
+++ b/src/store/Store.js
@@ -10,7 +10,7 @@ const callbackMapping = {};
*/
function init() {
// Subscribe to the storage event so changes to local storage can be captured
- //TODO: Refactor window events
+ // TODO: Refactor window events
// window.addEventListener('storage', (e) => {
// try {
// keyChanged(e.key, JSON.parse(e.newValue));
@@ -43,9 +43,7 @@ function unsubscribe(keyPattern, cb) {
if (!callbackMapping[keyPattern] || !callbackMapping[keyPattern].length) {
return;
}
- callbackMapping[keyPattern] = callbackMapping[keyPattern].filter(
- (existingCallback) => existingCallback !== cb,
- );
+ callbackMapping[keyPattern] = callbackMapping[keyPattern].filter(existingCallback => existingCallback !== cb);
}
/**
@@ -102,7 +100,7 @@ function get(key, extraPath, defaultValue) {
}
return val;
});
-};
+}
/**
* Get multiple keys of data
diff --git a/src/store/actions/SessionActions.js b/src/store/actions/SessionActions.js
index 7fe586bf485c..32901dcd16c8 100644
--- a/src/store/actions/SessionActions.js
+++ b/src/store/actions/SessionActions.js
@@ -66,6 +66,7 @@ function signIn(login, password, useExpensifyLogin = false) {
// If we didn't get a 200 response from authenticate, the user needs to sign in again
if (data.jsonCode !== 200) {
+ // eslint-disable-next-line no-console
console.warn('Did not get a 200 from authenticate, going back to sign in page');
return Store.set(STOREKEYS.APP_REDIRECT_TO, ROUTES.SIGNIN);
}
diff --git a/webpack.config.js b/webpack.config.js
index 56c60e212ec2..49ef0a83b29d 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -20,19 +20,16 @@ module.exports = {
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: 'web/index.html',
- // With the dev server, we need to put this file in the dist folder
filename: 'index.html',
}),
],
module: {
rules: [
- // Transpiles ES6 and JSX
+ // Transpiles and lints all the JS
{
test: /\.js$/,
exclude: /node_modules|\.native.js$/,
- use: {
- loader: 'babel-loader',
- },
+ use: ['babel-loader', 'eslint-loader'],
},
],
},