diff --git a/.github/ISSUE_TEMPLATE/Standard.md b/.github/ISSUE_TEMPLATE/Standard.md
index f728a9761a36..8f5d0c6b97e2 100644
--- a/.github/ISSUE_TEMPLATE/Standard.md
+++ b/.github/ISSUE_TEMPLATE/Standard.md
@@ -36,4 +36,4 @@ Where is this issue occurring?
**Notes/Photos/Videos:** Any additional supporting documentation
**Expensify/Expensify Issue URL:**
-[View all open jobs on Upwork](https://www.upwork.com/ab/jobs/search/?q=Expensify%20React%20Native&sort=recency&user_location_match=2)
+[View all open jobs on GitHub](https://github.com/Expensify/App/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22)
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 6b2351ea4bd6..87a6aacb8bbf 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -150,8 +150,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
- versionCode 1001008506
- versionName "1.0.85-6"
+ versionCode 1001008601
+ versionName "1.0.86-1"
}
splits {
abi {
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index 638712115c8a..121e687f2f42 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -17,7 +17,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 1.0.85
+ 1.0.86
CFBundleSignature
????
CFBundleURLTypes
@@ -30,7 +30,7 @@
CFBundleVersion
- 1.0.85.6
+ 1.0.86.1
ITSAppUsesNonExemptEncryption
LSApplicationQueriesSchemes
diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist
index 1f8977d4e1bf..f352246bf05c 100644
--- a/ios/NewExpensifyTests/Info.plist
+++ b/ios/NewExpensifyTests/Info.plist
@@ -15,10 +15,10 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- 1.0.85
+ 1.0.86
CFBundleSignature
????
CFBundleVersion
- 1.0.85.6
+ 1.0.86.1
diff --git a/package-lock.json b/package-lock.json
index e0afa2be99aa..8d14221c2894 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "1.0.85-6",
+ "version": "1.0.86-1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -23082,8 +23082,8 @@
}
},
"expensify-common": {
- "version": "git://github.com/Expensify/expensify-common.git#8f286b5826a041ecb739cff1ad6940ffb9324bee",
- "from": "git://github.com/Expensify/expensify-common.git#8f286b5826a041ecb739cff1ad6940ffb9324bee",
+ "version": "git://github.com/Expensify/expensify-common.git#5fb22bd4a3619eb9fe9e2a9c0dc25e291863a2a2",
+ "from": "git://github.com/Expensify/expensify-common.git#5fb22bd4a3619eb9fe9e2a9c0dc25e291863a2a2",
"requires": {
"classnames": "2.3.1",
"clipboard": "2.0.4",
diff --git a/package.json b/package.json
index ec81840a90f7..bd8878610a82 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "1.0.85-6",
+ "version": "1.0.86-1",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
@@ -60,7 +60,7 @@
"electron-log": "^4.3.5",
"electron-serve": "^1.0.0",
"electron-updater": "^4.3.4",
- "expensify-common": "git://github.com/Expensify/expensify-common.git#8f286b5826a041ecb739cff1ad6940ffb9324bee",
+ "expensify-common": "git://github.com/Expensify/expensify-common.git#5fb22bd4a3619eb9fe9e2a9c0dc25e291863a2a2",
"expo-haptics": "^10.0.0",
"file-loader": "^6.0.0",
"html-entities": "^1.3.1",
diff --git a/src/components/ErrorBoundary/index.js b/src/components/ErrorBoundary/index.js
index 7e8fdfdc2131..37daf447ad1a 100644
--- a/src/components/ErrorBoundary/index.js
+++ b/src/components/ErrorBoundary/index.js
@@ -3,7 +3,6 @@ import Log from '../../libs/Log';
BaseErrorBoundary.defaultProps.logError = (errorMessage, error, errorInfo) => {
// Log the error to the server
- Log.alert(errorMessage, 0, {error: error.message, errorInfo}, false);
+ Log.alert(errorMessage, {error: error.message, errorInfo}, false);
};
-
export default BaseErrorBoundary;
diff --git a/src/components/ErrorBoundary/index.native.js b/src/components/ErrorBoundary/index.native.js
index d320b46984e0..ae295a9d0c4d 100644
--- a/src/components/ErrorBoundary/index.native.js
+++ b/src/components/ErrorBoundary/index.native.js
@@ -5,7 +5,7 @@ import Log from '../../libs/Log';
BaseErrorBoundary.defaultProps.logError = (errorMessage, error, errorInfo) => {
// Log the error to the server
- Log.alert(errorMessage, 0, {error: error.message, errorInfo}, false);
+ Log.alert(errorMessage, {error: error.message, errorInfo}, false);
/* On native we also log the error to crashlytics
* Since the error was handled we need to manually tell crashlytics about it */
diff --git a/src/languages/en.js b/src/languages/en.js
index 22a746f24070..107a1caee8fe 100755
--- a/src/languages/en.js
+++ b/src/languages/en.js
@@ -44,8 +44,9 @@ export default {
here: 'here',
dob: 'Date of Birth',
ssnLast4: 'Last 4 Digits of SSN',
- addressNoPO: 'Personal Address (PO Boxes and mail drop addresses are NOT allowed)',
- companyAddressNoPO: 'Company Address (PO Boxes and mail drop addresses are NOT allowed)',
+ personalAddress: 'Personal Address',
+ companyAddress: 'Company Address',
+ noPO: '(PO Boxes and mail drop addresses are NOT allowed)',
city: 'City',
state: 'State',
zip: 'Zip Code',
diff --git a/src/languages/es.js b/src/languages/es.js
index 0dfd38895d84..c65c9c7ee408 100644
--- a/src/languages/es.js
+++ b/src/languages/es.js
@@ -44,8 +44,9 @@ export default {
here: 'aquí',
dob: 'Fecha de Nacimiento',
ssnLast4: 'Últimos 4 dígitos de su SSN',
- addressNoPO: 'Dirección física personal (no se aceptan apartados ni direcciones postales)',
- companyAddressNoPO: 'Dirección física de la empresa (no se aceptan apartados ni direcciones postales)',
+ personalAddress: 'Dirección física personal',
+ companyAddress: 'Dirección física de la empresa',
+ noPO: '(No se aceptan apartados ni direcciones postales)',
city: 'Ciudad',
state: 'Estado',
zip: 'Código Postal',
diff --git a/src/libs/API.js b/src/libs/API.js
index 8a3c56b505e3..1f76c5cf9460 100644
--- a/src/libs/API.js
+++ b/src/libs/API.js
@@ -484,15 +484,13 @@ function GetRequestCountryCode() {
/**
* @param {Object} parameters
- * @param {String} parameters.message
- * @param {Object} parameters.parameters
* @param {String} parameters.expensifyCashAppVersion
- * @param {String} [parameters.email]
+ * @param {Object[]} parameters.logPacket
* @returns {Promise}
*/
function Log(parameters) {
const commandName = 'Log';
- requireParameters(['message', 'parameters', 'expensifyCashAppVersion'],
+ requireParameters(['logPacket', 'expensifyCashAppVersion'],
parameters, commandName);
// Note: We are forcing Log to run since it requires no authToken and should only be queued when we are offline.
diff --git a/src/libs/HttpUtils.js b/src/libs/HttpUtils.js
index 3e71518d0d37..dc4b2e817f33 100644
--- a/src/libs/HttpUtils.js
+++ b/src/libs/HttpUtils.js
@@ -2,6 +2,9 @@ import _ from 'underscore';
import CONFIG from '../CONFIG';
import CONST from '../CONST';
+// To avoid a circular dependency, we can't include Log here, so instead, we define an empty logging method and expose the setLogger method to set the logger from outside this file
+let info = () => {};
+
/**
* Send an HTTP request, and attempt to resolve the json response.
* If there is a network error, we'll set the application offline.
@@ -28,10 +31,30 @@ function processHTTPRequest(url, method = 'get', body = null) {
* @returns {Promise}
*/
function xhr(command, data, type = CONST.NETWORK.METHOD.POST, shouldUseSecure = false) {
+ if (command !== 'Log') {
+ info('Making API request', false, {
+ command,
+ type,
+ shouldUseSecure,
+ rvl: data.returnValueList,
+ });
+ }
const formData = new FormData();
_.each(data, (val, key) => formData.append(key, val));
const apiRoot = shouldUseSecure ? CONFIG.EXPENSIFY.URL_EXPENSIFY_SECURE : CONFIG.EXPENSIFY.URL_API_ROOT;
- return processHTTPRequest(`${apiRoot}api?command=${command}`, type, formData);
+ return processHTTPRequest(`${apiRoot}api?command=${command}`, type, formData)
+ .then((response) => {
+ if (command !== 'Log') {
+ info('Finished API request', false, {
+ command,
+ type,
+ shouldUseSecure,
+ jsonCode: response.jsonCode,
+ requestID: response.requestID,
+ });
+ }
+ return response;
+ });
}
/**
@@ -51,7 +74,12 @@ function download(relativePath) {
return processHTTPRequest(`${siteRoot}${strippedRelativePath}`);
}
+function setLogger(logger) {
+ info = logger.info;
+}
+
export default {
+ setLogger,
download,
xhr,
};
diff --git a/src/libs/Log.js b/src/libs/Log.js
index 1451ea25cc95..1bff8aa84fcb 100644
--- a/src/libs/Log.js
+++ b/src/libs/Log.js
@@ -4,22 +4,28 @@ import CONFIG from '../CONFIG';
import getPlatform from './getPlatform';
import {version} from '../../package.json';
import NetworkConnection from './NetworkConnection';
+import HttpUtils from './HttpUtils';
+
+let timeout = null;
/**
* Network interface for logger.
*
+ * @param {Logger} logger
* @param {Object} params
* @param {Object} params.parameters
* @param {String} params.message
+ * @return {Promise}
*/
-function serverLoggingCallback(params) {
- const requestParams = {
- message: params.message,
- parameters: JSON.stringify(params.parameters || {}),
- expensifyCashAppVersion: `expensifyCash[${getPlatform()}]${version}`,
- };
-
- API.Log(requestParams);
+function serverLoggingCallback(logger, params) {
+ const requestParams = params;
+ requestParams.expensifyCashAppVersion = `expensifyCash[${getPlatform()}]${version}`;
+ if (requestParams.parameters) {
+ requestParams.parameters = JSON.stringify(params.parameters);
+ }
+ clearTimeout(timeout);
+ timeout = setTimeout(() => logger.info('Flushing logs older than 10 minutes', true, {}, true), 10 * 60 * 1000);
+ return API.Log(requestParams);
}
// Note: We are importing Logger from expensify-common because it is
@@ -33,6 +39,9 @@ const Log = new Logger({
},
isDebug: !CONFIG.IS_IN_PRODUCTION,
});
+timeout = setTimeout(() => Log.info('Flushing logs older than 10 minutes', true, {}, true), 10 * 60 * 1000);
NetworkConnection.registerLogInfoCallback(Log.info);
+HttpUtils.setLogger(Log);
+
export default Log;
diff --git a/src/libs/Navigation/NavigationRoot.js b/src/libs/Navigation/NavigationRoot.js
index ec8745ec6cf1..903b71f161c4 100644
--- a/src/libs/Navigation/NavigationRoot.js
+++ b/src/libs/Navigation/NavigationRoot.js
@@ -6,6 +6,7 @@ import linkingConfig from './linkingConfig';
import AppNavigator from './AppNavigator';
import {setCurrentURL} from '../actions/App';
import FullScreenLoadingIndicator from '../../components/FullscreenLoadingIndicator';
+import Log from '../Log';
const propTypes = {
/** Whether the current user is logged in with an authToken */
@@ -29,6 +30,7 @@ class NavigationRoot extends Component {
}
const path = getPathFromState(state, linkingConfig.config);
+ Log.info('Navigating to route', false, {path});
setCurrentURL(path);
}
diff --git a/src/libs/NetworkConnection.js b/src/libs/NetworkConnection.js
index cb104b18d868..4e83f5a6d96c 100644
--- a/src/libs/NetworkConnection.js
+++ b/src/libs/NetworkConnection.js
@@ -19,7 +19,7 @@ const reconnectionCallbacks = [];
* Loop over all reconnection callbacks and fire each one
*/
const triggerReconnectionCallbacks = _.throttle((reason) => {
- logInfo(`[NetworkConnection] Firing reconnection callbacks because ${reason}`, true);
+ logInfo(`[NetworkConnection] Firing reconnection callbacks because ${reason}`);
Onyx.set(ONYXKEYS.IS_LOADING_AFTER_RECONNECT, true);
promiseAllSettled(_.map(reconnectionCallbacks, callback => callback()))
.then(() => Onyx.set(ONYXKEYS.IS_LOADING_AFTER_RECONNECT, false));
@@ -49,7 +49,7 @@ function setOfflineStatus(isCurrentlyOffline) {
* `disconnected` event which takes about 10-15 seconds to emit.
*/
function listenForReconnect() {
- logInfo('[NetworkConnection] listenForReconnect called', true);
+ logInfo('[NetworkConnection] listenForReconnect called');
unsubscribeFromAppState = AppStateMonitor.addBecameActiveListener(() => {
triggerReconnectionCallbacks('app became active');
@@ -67,7 +67,7 @@ function listenForReconnect() {
* Tear down the event listeners when we are finished with them.
*/
function stopListeningForReconnect() {
- logInfo('[NetworkConnection] stopListeningForReconnect called', true);
+ logInfo('[NetworkConnection] stopListeningForReconnect called');
if (unsubscribeFromNetInfo) {
unsubscribeFromNetInfo();
unsubscribeFromNetInfo = undefined;
diff --git a/src/libs/PusherConnectionManager.js b/src/libs/PusherConnectionManager.js
index 164efb40d7b3..9873ed33d20c 100644
--- a/src/libs/PusherConnectionManager.js
+++ b/src/libs/PusherConnectionManager.js
@@ -7,7 +7,7 @@ import Log from './Log';
// reconnect each time when we only need to reconnect once. This way, if an authToken is expired and we try to
// subscribe to a bunch of channels at once we will only reauthenticate and force reconnect Pusher once.
const reauthenticate = _.throttle(() => {
- Log.info('[Pusher] Re-authenticating and then reconnecting', true);
+ Log.info('[Pusher] Re-authenticating and then reconnecting');
API.reauthenticate('Push_Authenticate')
.then(() => Pusher.reconnect())
.catch(() => {
@@ -27,7 +27,7 @@ function init() {
*/
Pusher.registerCustomAuthorizer(channel => ({
authorize: (socketID, callback) => {
- Log.info('[PusherConnectionManager] Attempting to authorize Pusher', true);
+ Log.info('[PusherConnectionManager] Attempting to authorize Pusher', false, {channelName: channel.name});
API.Push_Authenticate({
socket_id: socketID,
@@ -44,11 +44,15 @@ function init() {
return;
}
- Log.info('[PusherConnectionManager] Pusher authenticated successfully', true);
+ Log.info(
+ '[PusherConnectionManager] Pusher authenticated successfully',
+ false,
+ {channelName: channel.name},
+ );
callback(null, data);
})
.catch((error) => {
- Log.info('[PusherConnectionManager] Unhandled error: ', error);
+ Log.info('[PusherConnectionManager] Unhandled error: ', false, {channelName: channel.name});
callback(error, {auth: ''});
});
},
@@ -63,14 +67,14 @@ function init() {
Pusher.registerSocketEventCallback((eventName, data) => {
switch (eventName) {
case 'error':
- Log.info('[PusherConnectionManager] error event', true, {error: data});
+ Log.info('[PusherConnectionManager] error event', false, {error: data});
reauthenticate();
break;
case 'connected':
- Log.info('[PusherConnectionManager] connected event', true);
+ Log.info('[PusherConnectionManager] connected event');
break;
case 'disconnected':
- Log.info('[PusherConnectionManager] disconnected event', true);
+ Log.info('[PusherConnectionManager] disconnected event');
break;
default:
break;
diff --git a/src/libs/actions/App.js b/src/libs/actions/App.js
index dcab886f39b2..642f826ddf80 100644
--- a/src/libs/actions/App.js
+++ b/src/libs/actions/App.js
@@ -1,9 +1,10 @@
+import {AppState, Linking} from 'react-native';
import Onyx from 'react-native-onyx';
-import {Linking} from 'react-native';
import lodashGet from 'lodash/get';
import ONYXKEYS from '../../ONYXKEYS';
import * as API from '../API';
import CONST from '../../CONST';
+import Log from '../Log';
import CONFIG from '../../CONFIG';
import Firebase from '../Firebase';
import ROUTES from '../../ROUTES';
@@ -71,6 +72,14 @@ function setSidebarLoaded() {
printPerformanceMetrics();
}
+let appState;
+AppState.addEventListener('change', (nextAppState) => {
+ if (nextAppState.match(/inactive|background/) && appState === 'active') {
+ Log.info('Flushing logs as app is going inactive', true, {}, true);
+ }
+ appState = nextAppState;
+});
+
export {
setCurrentURL,
setLocale,
diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js
index 1685997c382a..d9738e883bcf 100644
--- a/src/libs/actions/Report.js
+++ b/src/libs/actions/Report.js
@@ -309,7 +309,7 @@ function fetchChatReportsByIDs(chatList, shouldRedirectIfInacessible = false) {
const simplifiedReports = {};
return API.GetReportSummaryList({reportIDList: chatList.join(',')})
.then(({reportSummaryList, jsonCode}) => {
- Log.info('[Report] successfully fetched report data', true);
+ Log.info('[Report] successfully fetched report data', false, {chatList});
fetchedReports = reportSummaryList;
// If we receive a 404 response while fetching a single report, treat that report as inacessible.
@@ -329,7 +329,7 @@ function fetchChatReportsByIDs(chatList, shouldRedirectIfInacessible = false) {
return;
}
if (participants.length === 0) {
- Log.alert('[Report] Report with IOU action but does not have any participant.', true, {
+ Log.alert('[Report] Report with IOU action but does not have any participant.', {
reportID: chatReport.reportID,
participants,
});
@@ -682,7 +682,7 @@ function subscribeToUserEvents() {
// Live-update a report's actions when a 'report comment' event is received.
Pusher.subscribe(pusherChannelName, Pusher.TYPE.REPORT_COMMENT, (pushJSON) => {
Log.info(
- `[Report] Handled ${Pusher.TYPE.REPORT_COMMENT} event sent by Pusher`, true, {reportID: pushJSON.reportID},
+ `[Report] Handled ${Pusher.TYPE.REPORT_COMMENT} event sent by Pusher`, false, {reportID: pushJSON.reportID},
);
updateReportWithNewAction(pushJSON.reportID, pushJSON.reportAction, pushJSON.notificationPreference);
}, false,
@@ -692,7 +692,7 @@ function subscribeToUserEvents() {
.catch((error) => {
Log.info(
'[Report] Failed to subscribe to Pusher channel',
- true,
+ false,
{error, pusherChannelName, eventName: Pusher.TYPE.REPORT_COMMENT},
);
});
@@ -700,7 +700,7 @@ function subscribeToUserEvents() {
// Live-update a report's actions when an 'edit comment' event is received.
Pusher.subscribe(pusherChannelName, Pusher.TYPE.REPORT_COMMENT_EDIT, (pushJSON) => {
Log.info(
- `[Report] Handled ${Pusher.TYPE.REPORT_COMMENT_EDIT} event sent by Pusher`, true, {
+ `[Report] Handled ${Pusher.TYPE.REPORT_COMMENT_EDIT} event sent by Pusher`, false, {
reportActionID: pushJSON.reportActionID,
},
);
@@ -712,7 +712,7 @@ function subscribeToUserEvents() {
.catch((error) => {
Log.info(
'[Report] Failed to subscribe to Pusher channel',
- true,
+ false,
{error, pusherChannelName, eventName: Pusher.TYPE.REPORT_COMMENT_EDIT},
);
});
@@ -721,7 +721,7 @@ function subscribeToUserEvents() {
Pusher.subscribe(pusherChannelName, Pusher.TYPE.REPORT_TOGGLE_PINNED, (pushJSON) => {
Log.info(
`[Report] Handled ${Pusher.TYPE.REPORT_TOGGLE_PINNED} event sent by Pusher`,
- true,
+ false,
{reportID: pushJSON.reportID},
);
updateReportPinnedState(pushJSON.reportID, pushJSON.isPinned);
@@ -732,13 +732,13 @@ function subscribeToUserEvents() {
.catch((error) => {
Log.info(
'[Report] Failed to subscribe to Pusher channel',
- true,
+ false,
{error, pusherChannelName, eventName: Pusher.TYPE.REPORT_TOGGLE_PINNED},
);
});
PushNotification.onReceived(PushNotification.TYPE.REPORT_COMMENT, ({reportID, reportAction}) => {
- Log.info('[Report] Handled event sent by Airship', true, {reportID});
+ Log.info('[Report] Handled event sent by Airship', false, {reportID});
updateReportWithNewAction(reportID, reportAction);
});
@@ -810,7 +810,7 @@ function subscribeToReportTypingEvents(reportID) {
}, 1500);
})
.catch((error) => {
- Log.info('[Report] Failed to initially subscribe to Pusher channel', true, {error, pusherChannelName});
+ Log.info('[Report] Failed to initially subscribe to Pusher channel', false, {error, pusherChannelName});
});
}
@@ -877,7 +877,7 @@ function fetchActions(reportID, offset) {
const reportActionsOffset = !_.isUndefined(offset) ? offset : -1;
if (!_.isNumber(reportActionsOffset)) {
- Log.alert('[Report] Offset provided is not a number', true, {
+ Log.alert('[Report] Offset provided is not a number', {
offset,
reportActionsOffset,
});
diff --git a/src/libs/actions/Session.js b/src/libs/actions/Session.js
index eeb303a25c54..6313f3aac569 100644
--- a/src/libs/actions/Session.js
+++ b/src/libs/actions/Session.js
@@ -5,6 +5,7 @@ import ONYXKEYS from '../../ONYXKEYS';
import redirectToSignIn from './SignInRedirect';
import * as API from '../API';
import CONFIG from '../../CONFIG';
+import Log from '../Log';
import PushNotification from '../Notification/PushNotification';
import Timing from './Timing';
import CONST from '../../CONST';
@@ -63,6 +64,7 @@ function createAccount(login) {
* Clears the Onyx store and redirects user to the sign in page
*/
function signOut() {
+ Log.info('Flushing logs before signing out', true, {}, true);
if (credentials && credentials.autoGeneratedLogin) {
// Clean up the login that we created
API.DeleteLogin({
diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js
index e2428a124d04..c215f83c9f05 100644
--- a/src/libs/actions/User.js
+++ b/src/libs/actions/User.js
@@ -262,7 +262,7 @@ function subscribeToUserEvents() {
.catch((error) => {
Log.info(
'[User] Failed to subscribe to Pusher channel',
- true,
+ false,
{error, pusherChannelName, eventName: Pusher.TYPE.PREFERRED_LOCALE},
);
});
diff --git a/src/libs/translate.js b/src/libs/translate.js
index 4716a25841e9..d8f2e82bb049 100644
--- a/src/libs/translate.js
+++ b/src/libs/translate.js
@@ -46,7 +46,7 @@ function translate(locale = CONST.DEFAULT_LOCALE, phrase, variables = {}) {
return Str.result(translationValue, variables);
}
if (localeLanguage !== 'en') {
- Log.alert(`${phrase} was not found in the ${localeLanguage} locale`, 0, {}, false);
+ Log.alert(`${phrase} was not found in the ${localeLanguage} locale`);
}
// Phrase is not translated, search it in default language (en)
@@ -59,7 +59,7 @@ function translate(locale = CONST.DEFAULT_LOCALE, phrase, variables = {}) {
// on development throw an error
if (Config.IS_IN_PRODUCTION) {
const phraseString = Array.isArray(phrase) ? phrase.join('.') : phrase;
- Log.alert(`${phraseString} was not found in the en locale`, 0, {}, false);
+ Log.alert(`${phraseString} was not found in the en locale`);
return phraseString;
}
throw new Error(`${phrase} was not found in the default language`);
diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.js b/src/pages/EnablePayments/AdditionalDetailsStep.js
index dd65d99b9a4c..bf943b4966fb 100644
--- a/src/pages/EnablePayments/AdditionalDetailsStep.js
+++ b/src/pages/EnablePayments/AdditionalDetailsStep.js
@@ -62,7 +62,7 @@ class AdditionalDetailsStep extends React.Component {
fieldName: 'legalLastName',
},
{
- label: props.translate('common.addressNoPO'),
+ label: props.translate('common.personalAddress'),
fieldName: 'addressStreet',
},
{
@@ -128,17 +128,20 @@ class AdditionalDetailsStep extends React.Component {
{_.map(this.fields, field => (
- this.setState({[field.fieldName]: val})}
- value={this.state[field.fieldName]}
- errorText={errorFields.includes(field.fieldName)
- ? `${field.label} ${this.requiredText}`
- : ''}
- // eslint-disable-next-line react/jsx-props-no-spreading
- {..._.omit(field, ['label', 'fieldName'])}
- />
+ <>
+ this.setState({[field.fieldName]: val})}
+ value={this.state[field.fieldName]}
+ errorText={errorFields.includes(field.fieldName)
+ ? `${field.label} ${this.requiredText}`
+ : ''}
+ // eslint-disable-next-line react/jsx-props-no-spreading
+ {..._.omit(field, ['label', 'fieldName'])}
+ />
+ {field.fieldName === 'addressStreet' && {this.props.translate('common.noPO')}}
+ >
))}
diff --git a/src/pages/ReimbursementAccount/CompanyStep.js b/src/pages/ReimbursementAccount/CompanyStep.js
index c1ccb59f1cf7..de3fa93ae32a 100644
--- a/src/pages/ReimbursementAccount/CompanyStep.js
+++ b/src/pages/ReimbursementAccount/CompanyStep.js
@@ -170,7 +170,7 @@ class CompanyStep extends React.Component {
disabled={shouldDisableCompanyName}
/>
{
if (error === this.props.translate('bankAccount.error.addressStreet')) {
@@ -183,6 +183,7 @@ class CompanyStep extends React.Component {
? this.props.translate('bankAccount.error.addressStreet')
: ''}
/>
+ {this.props.translate('common.noPO')}
{
@@ -124,6 +124,7 @@ const IdentityForm = ({
}}
errorText={error === translateLocal('bankAccount.error.address') ? error : ''}
/>
+ {translate('common.noPO')}
+ {
+ if (this.textInput) {
+ this.textInput.focus();
+ }
+ }}
+ >
this.toggleOption(item.currencyCode)}
isSelected={
diff --git a/src/pages/settings/InitialPage.js b/src/pages/settings/InitialPage.js
index ca3774b4cd91..8bfa58596188 100755
--- a/src/pages/settings/InitialPage.js
+++ b/src/pages/settings/InitialPage.js
@@ -174,7 +174,7 @@ const InitialSettingsPage = ({
/>
-
+
{myPersonalDetails.displayName
? myPersonalDetails.displayName
diff --git a/src/pages/settings/NewPasswordForm.js b/src/pages/settings/NewPasswordForm.js
index a17d1bc7d560..8a6dce156b25 100644
--- a/src/pages/settings/NewPasswordForm.js
+++ b/src/pages/settings/NewPasswordForm.js
@@ -98,7 +98,7 @@ class NewPasswordForm extends React.Component {
secureTextEntry
autoCompleteType="password"
textContentType="password"
- value={this.state.password}
+ value={this.props.password}
onChangeText={password => this.props.updatePassword(password)}
onBlur={() => this.onBlurNewPassword()}
/>
diff --git a/src/pages/settings/PasswordPage.js b/src/pages/settings/PasswordPage.js
index d959d39a5c7b..b1febd78bfa5 100755
--- a/src/pages/settings/PasswordPage.js
+++ b/src/pages/settings/PasswordPage.js
@@ -71,15 +71,15 @@ class PasswordPage extends Component {
if (this.state.newPassword && this.state.confirmNewPassword && !this.doPasswordsMatch()) {
stateToUpdate.shouldShowPasswordConfirmError = true;
+ } else {
+ stateToUpdate.shouldShowPasswordConfirmError = false;
}
- if (!isEmpty(stateToUpdate)) {
- this.setState(stateToUpdate);
- }
+ this.setState(stateToUpdate);
}
onBlurConfirmPassword() {
- if (!this.state.confirmNewPassword || !this.doPasswordsMatch()) {
+ if ((this.state.newPassword && !this.state.confirmNewPassword) || !this.doPasswordsMatch()) {
this.setState({shouldShowPasswordConfirmError: true});
} else {
this.setState({shouldShowPasswordConfirmError: false});
diff --git a/src/pages/workspace/WorkspaceInvitePage.js b/src/pages/workspace/WorkspaceInvitePage.js
index 0b6c2f88ab9e..e50a52266516 100644
--- a/src/pages/workspace/WorkspaceInvitePage.js
+++ b/src/pages/workspace/WorkspaceInvitePage.js
@@ -55,7 +55,9 @@ class WorkspaceInvitePage extends React.Component {
welcomeNote: '',
};
+ this.focusEmailOrPhoneInput = this.focusEmailOrPhoneInput.bind(this);
this.inviteUser = this.inviteUser.bind(this);
+ this.emailOrPhoneInputRef = null;
}
/**
@@ -69,6 +71,13 @@ class WorkspaceInvitePage extends React.Component {
});
}
+ focusEmailOrPhoneInput() {
+ if (!this.emailOrPhoneInputRef) {
+ return;
+ }
+ this.emailOrPhoneInputRef.focus();
+ }
+
/**
* Handle the invite button click
*/
@@ -93,7 +102,7 @@ class WorkspaceInvitePage extends React.Component {
render() {
return (
-
+
this.emailOrPhoneInputRef = el}
label={this.props.translate('workspace.invite.enterEmailOrPhone')}
autoCompleteType="email"
autoCorrect={false}
diff --git a/src/styles/styles.js b/src/styles/styles.js
index d71e788b16a4..8905981ddb73 100644
--- a/src/styles/styles.js
+++ b/src/styles/styles.js
@@ -85,6 +85,12 @@ const styles = {
lineHeight: 18,
},
+ mutedTextLabel: {
+ color: themeColors.textSupporting,
+ fontSize: variables.fontSizeLabel,
+ lineHeight: 18,
+ },
+
textMicro: {
fontFamily: fontFamily.GTA,
fontSize: variables.fontSizeSmall,
diff --git a/src/styles/utilities/sizing.js b/src/styles/utilities/sizing.js
index 9724e9acf798..d823eb9856fa 100644
--- a/src/styles/utilities/sizing.js
+++ b/src/styles/utilities/sizing.js
@@ -24,6 +24,10 @@ export default {
maxWidth: 'auto',
},
+ mw100: {
+ maxWidth: '100%',
+ },
+
w1: {
width: 4,
},
diff --git a/test.md b/test.md
new file mode 100644
index 000000000000..db0d8318b8f5
--- /dev/null
+++ b/test.md
@@ -0,0 +1 @@
+This is for testing purposes, I will remove this file in subsequent PR.
\ No newline at end of file
diff --git a/test_webhook.md b/test_webhook.md
deleted file mode 100644
index 15b7e2b38138..000000000000
--- a/test_webhook.md
+++ /dev/null
@@ -1 +0,0 @@
-Just PR for testing a Webhook, I will remove this file in consequent PR.
\ No newline at end of file