Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -901,8 +901,8 @@ export default {
},
requestCallPage: {
title: 'Request a call',
subtitle: 'Have questions, or need help?',
description: 'Our team of guides are on hand to help you each step of the way. Type in your name and phone number, and well give you a call back.',
subtitle: 'Need help?',
description: 'Our team is ready to help each step of the way. Enter your name and phone number, and we\'ll give you a call back asap.',
extension: 'Extension (Optional)',
callMe: 'Call me',
growlMessageOnSave: 'Call requested.',
Expand All @@ -922,6 +922,11 @@ export default {
phoneExtension: 'Please enter a valid phone extension number',
},
},
requestCallConfirmationScreen: {
callRequested: 'Call successfully requested!',
allSet: 'You’re all set. You will be receiving a call from us soon.',
gotIt: 'Got it',
},
emojiPicker: {
skinTonePickerLabel: 'Change default skin tone',
headers: {
Expand Down
9 changes: 7 additions & 2 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -903,8 +903,8 @@ export default {
},
requestCallPage: {
title: 'Llámame por teléfono',
subtitle: '¿Tienes preguntas o necesitas ayuda?',
description: '¿Necesitas ayuda configurando tu cuenta? Nuestro equipo de guías puede ayudarte. Escribe tu nombre y número de teléfono y te llamaremos.',
subtitle: '¿Necesitas ayuda?',
description: 'Nuestro equipo está listo para ayudarte en cada paso. Ingresa tu nombre y número de teléfono y te llamaremos lo antes posible.',
extension: 'Extensión (Opcional)',
callMe: 'Llámame',
growlMessageOnSave: 'Llamada solicitada.',
Expand All @@ -924,6 +924,11 @@ export default {
phoneExtension: 'Por favor, introduzca una extensión telefónica válida',
},
},
requestCallConfirmationScreen: {
callRequested: '¡Llamada solicitada con éxito!',
allSet: 'Todo listo! Pronto recibirás una llamada nuestra.',
gotIt: 'Entendido',
},
emojiPicker: {
skinTonePickerLabel: 'Elige el tono de piel por defecto',
headers: {
Expand Down
36 changes: 22 additions & 14 deletions src/libs/Middleware/SaveResponseInOnyx.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,29 @@ import _ from 'underscore';
function SaveResponseInOnyx(response, request) {
return response
.then((responseData) => {
// We'll only save the onyxData, successData and failureData for the refactored commands
if (_.has(responseData, 'onyxData')) {
const data = [];
if (responseData.jsonCode === 200) {
if (request.successData) {
data.push(...request.successData);
}
} else if (request.failureData) {
data.push(...request.failureData);
}
if (responseData.onyxData) {
data.push(...responseData.onyxData);
}
Onyx.update(data);
const onyxUpdates = [];

// Make sure we have response data (i.e. response isn't a promise being passed down to us by a failed retry request and responseData undefined)
if (!responseData) {
return;
}

// Handle the request's success/failure data (client-side data)
if (responseData.jsonCode === 200 && request.successData) {
onyxUpdates.push(...request.successData);
} else if (responseData.jsonCode !== 200 && request.failureData) {
onyxUpdates.push(...request.failureData);
}
Comment on lines +15 to +24

@aldo-expensify aldo-expensify Aug 25, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @yuwenmemon

I'm not sure if this case matters, but if a requests hits the back end with a command that is not implemented, the backend returns a 404. I would have expected that the failureData to be pushed into Onyx, but it isn't because responseData is undefined so I ended up without feedback in the UI. Could this happen in a real case? like if we try to send a request about a workspace or a chat that doesn't exist anymore?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you mean because the response for that case does not come via jsonCode: https://github.com/Expensify/Web-Expensify/blob/30edfabd582f9ac70ec59cef3172a5bf25657efa/api.php#L2761-L2766

Maybe we can add a parameter that indicates if this call to the Middleware is coming from a failed retry request or not? Maybe checking the retryCount? Or check the HTTP response code somehow? The original issue was that if a request was a failed retry (i.e. could not connect to the Server), we'd have no responseData and thus get an undefined error.

However I don't really think this case matters too much right? Why would we want to support error messages for non-existent API commands? We shouldn't be calling non-existent API commands in the production App ever, right? Any "feedback in the UI" would solely be serving developers and that's it, no?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However I don't really think this case matters too much right? Why would we want to support error messages for non-existent API commands? We shouldn't be calling non-existent API commands in the production App ever, right? Any "feedback in the UI" would solely be serving developers and that's it, no?

I completely agree that this doesn't matter if it only happens when a command doesn't exist, but I had my doubt if this could happen with other crashes like and exception being thrown. I'll test and let you know.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, retested throwing an exception in the web API, we get a jsonCode = 666, responseData is not undefined, and the failureData is applied correctly. I think this is the case that matters and works fine.. so lets do nothing :)


// Add any onyx updates that are being sent back from the API
if (responseData.onyxData) {
onyxUpdates.push(...responseData.onyxData);
}

if (!_.isEmpty(onyxUpdates)) {
Onyx.update(onyxUpdates);
}

return responseData;
});
}
Expand Down
100 changes: 62 additions & 38 deletions src/libs/actions/Inbox.js
Original file line number Diff line number Diff line change
@@ -1,57 +1,81 @@
import Onyx from 'react-native-onyx';
import ONYXKEYS from '../../ONYXKEYS';
import * as API from '../API';
import * as DeprecatedAPI from '../deprecatedAPI';
import Growl from '../Growl';
import * as Localize from '../Localize';
import Navigation from '../Navigation/Navigation';
import * as User from './User';

/**
* Requests a call from Guides
*
* @param {Object} params
* @param {String} taskID
* @param {String} policyID
* @param {String} firstName
* @param {String} lastName
* @param {String} phoneNumber
* @param {String} params.taskID
* @param {String} params.policyID
* @param {String} params.firstName
* @param {String} params.lastName
* @param {String} params.phoneNumber
* @param {String} params.phoneNumberExtension
*/
function requestInboxCall({
function requestCall({
Comment thread
marcaaron marked this conversation as resolved.
taskID, policyID, firstName, lastName, phoneNumber, phoneNumberExtension,
}) {
Onyx.merge(ONYXKEYS.REQUEST_CALL_FORM, {loading: true});
DeprecatedAPI.Inbox_CallUser({
policyID,
firstName,
lastName,
phoneNumber,
phoneNumberExtension,
taskID,
})
.then((result) => {
if (result.jsonCode === 200) {
Growl.success(Localize.translateLocal('requestCallPage.growlMessageOnSave'));
Navigation.goBack();
return;
}
const optimisticData = [{
onyxMethod: 'merge',
key: ONYXKEYS.REQUEST_CALL_FORM,
value: {
loading: true,
Comment thread
marcaaron marked this conversation as resolved.
},
}];

if (result.jsonCode === 666) {
// The fact that the API is returning this error means the BLOCKED_FROM_CONCIERGE nvp in the user details has changed since the last time we checked, so let's update
User.getUserDetails();
}
const successData = [
{
onyxMethod: 'merge',
key: ONYXKEYS.REQUEST_CALL_FORM,
value: {
loading: false,
error: '',
didRequestCallSucceed: true,
},
},
];

// Phone number validation is handled by the API
Growl.error(result.message, 3000);
})
.finally(() => {
Onyx.merge(ONYXKEYS.REQUEST_CALL_FORM, {loading: false});
});
const failureData = [{
onyxMethod: 'merge',
key: ONYXKEYS.REQUEST_CALL_FORM,
value: {
loading: false,
},
}];

API.write(
'RequestCall',
{
policyID,
firstName,
lastName,
phoneNumber,
phoneNumberExtension,
taskID,
},
{optimisticData, successData, failureData},
);
}

function openRequestCallPage() {
API.read('OpenRequestCallPage');
// Reset the error message in case we had one set from a previous failed attempt at requesting a call.
const optimisticData = [{
onyxMethod: 'merge',
key: ONYXKEYS.REQUEST_CALL_FORM,
value: {
error: '',
},
}];
API.read('OpenRequestCallPage', {}, {optimisticData});
}

function clearDidRequestCallSucceed() {
Onyx.merge(ONYXKEYS.REQUEST_CALL_FORM, {didRequestCallSucceed: false});
}

export {
requestInboxCall,
openRequestCallPage,
requestCall,
clearDidRequestCallSucceed,
};
50 changes: 50 additions & 0 deletions src/pages/RequestCallConfirmationScreen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import {Image, View} from 'react-native';
import Text from '../components/Text';
import withLocalize, {withLocalizePropTypes} from '../components/withLocalize';
import styles from '../styles/styles';
import confettiPop from '../../assets/images/confetti-pop.gif';
import Button from '../components/Button';
import FixedFooter from '../components/FixedFooter';
import Navigation from '../libs/Navigation/Navigation';

const propTypes = {
...withLocalizePropTypes,
};

const RequestCallConfirmationScreen = props => (
<>
<View style={[styles.screenCenteredContainer, styles.alignItemsCenter]}>
<Image
source={confettiPop}
style={styles.confettiIcon}
/>
<Text
style={[
styles.textStrong,
styles.textLarge,
styles.mb2,
]}
>
{props.translate('requestCallConfirmationScreen.callRequested')}
</Text>
<Text style={styles.textAlignCenter}>
{props.translate('requestCallConfirmationScreen.allSet')}
</Text>
</View>
<FixedFooter>
<Button
success
text={props.translate('requestCallConfirmationScreen.gotIt')}
style={styles.mt6}
pressOnEnter
onPress={() => Navigation.goBack()}
/>
</FixedFooter>
</>
);

RequestCallConfirmationScreen.propTypes = propTypes;
RequestCallConfirmationScreen.displayName = 'RequestCallConfirmationScreen';

export default withLocalize(RequestCallConfirmationScreen);
Loading