Skip to content

Commit 23bcfc9

Browse files
authored
Merge pull request #5550 from Expensify/aldo_vba-add-support-html-error
Add tag muted-text BaseHTMLEngineProvider to render html errors
2 parents c6570c9 + c12931b commit 23bcfc9

File tree

5 files changed

+66
-9
lines changed

5 files changed

+66
-9
lines changed

src/components/FormAlertWithSubmitButton.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Button from './Button';
1010
import withLocalize, {withLocalizePropTypes} from './withLocalize';
1111
import TextLink from './TextLink';
1212
import Text from './Text';
13+
import RenderHTML from './RenderHTML';
1314

1415
const propTypes = {
1516
/** Whether to show the alert text */
@@ -27,11 +28,15 @@ const propTypes = {
2728
/** Error message to display above button */
2829
message: PropTypes.string,
2930

31+
/** Whether message is in html format */
32+
isMessageHtml: PropTypes.bool,
33+
3034
...withLocalizePropTypes,
3135
};
3236

3337
const defaultProps = {
3438
message: '',
39+
isMessageHtml: false,
3540
};
3641

3742
const FormAlertWithSubmitButton = ({
@@ -41,6 +46,7 @@ const FormAlertWithSubmitButton = ({
4146
translate,
4247
onFixTheErrorsLinkPressed,
4348
message,
49+
isMessageHtml,
4450
}) => {
4551
/**
4652
* @returns {React.Component}
@@ -49,9 +55,15 @@ const FormAlertWithSubmitButton = ({
4955
let error = '';
5056

5157
if (!_.isEmpty(message)) {
52-
error = (
53-
<Text style={styles.mutedTextLabel}>{message}</Text>
54-
);
58+
if (isMessageHtml) {
59+
error = (
60+
<RenderHTML html={`<muted-text>${message}</muted-text>`} />
61+
);
62+
} else {
63+
error = (
64+
<Text style={styles.mutedTextLabel}>{message}</Text>
65+
);
66+
}
5567
} else {
5668
error = (
5769
<>

src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable react/prop-types */
22
import _ from 'underscore';
33
import React, {useMemo} from 'react';
4-
import {TouchableOpacity} from 'react-native';
4+
import {TouchableOpacity, Linking} from 'react-native';
55
import {
66
TRenderEngineProvider,
77
RenderHTMLConfigProvider,
@@ -66,6 +66,23 @@ function computeEmbeddedMaxWidth(tagName, contentWidth) {
6666
return contentWidth;
6767
}
6868

69+
/**
70+
* Check if there is an ancestor node with name 'comment'.
71+
* Finding node with name 'comment' flags that we are rendering a comment.
72+
* @param {TNode} tnode
73+
* @returns {Boolean}
74+
*/
75+
function isInsideComment(tnode) {
76+
let currentNode = tnode;
77+
while (currentNode.parent) {
78+
if (currentNode.domNode.name === 'comment') {
79+
return true;
80+
}
81+
currentNode = currentNode.parent;
82+
}
83+
return false;
84+
}
85+
6986
function AnchorRenderer({tnode, key, style}) {
7087
const htmlAttribs = tnode.attributes;
7188

@@ -89,6 +106,22 @@ function AnchorRenderer({tnode, key, style}) {
89106
);
90107
}
91108

109+
if (!isInsideComment(tnode)) {
110+
// This is not a comment from a chat, the AnchorForCommentsOnly uses a Pressable to create a context menu on right click.
111+
// We don't have this behaviour in other links in NewDot
112+
// TODO: We should use TextLink, but I'm leaving it as Text for now because TextLink breaks the alignment in Android.
113+
return (
114+
<Text
115+
style={styles.link}
116+
onPress={() => {
117+
Linking.openURL(htmlAttribs.href);
118+
}}
119+
>
120+
<TNodeChildrenRenderer tnode={tnode} />
121+
</Text>
122+
);
123+
}
124+
92125
return (
93126
<AnchorForCommentsOnly
94127
href={htmlAttribs.href}
@@ -223,6 +256,13 @@ const customHTMLElementModels = {
223256
edited: defaultHTMLElementModels.span.extend({
224257
tagName: 'edited',
225258
}),
259+
'muted-text': defaultHTMLElementModels.div.extend({
260+
tagName: 'muted-text',
261+
mixedUAStyles: styles.mutedTextLabel,
262+
}),
263+
comment: defaultHTMLElementModels.div.extend({
264+
tagName: 'comment',
265+
}),
226266
};
227267

228268
// Define the custom renderer components

src/libs/actions/BankAccounts.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -552,9 +552,10 @@ function setFreePlanVerifiedBankAccountID(bankAccountID) {
552552
* Show error modal and optionally a specific error message
553553
*
554554
* @param {String} errorModalMessage The error message to be displayed in the modal's body.
555+
* @param {Boolean} isErrorModalMessageHtml if @errorModalMessage is in html format or not
555556
*/
556-
function showBankAccountErrorModal(errorModalMessage = null) {
557-
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {errorModalMessage});
557+
function showBankAccountErrorModal(errorModalMessage = null, isErrorModalMessageHtml = false) {
558+
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {errorModalMessage, isErrorModalMessageHtml});
558559
}
559560

560561
/**
@@ -681,6 +682,7 @@ function setupWithdrawalAccount(data) {
681682
const currentStep = newACHData.currentStep;
682683
let achData = lodashGet(response, 'achData', {});
683684
let error = lodashGet(achData, CONST.BANK_ACCOUNT.VERIFICATIONS.ERROR_MESSAGE);
685+
let isErrorHTML = false;
684686
const errors = {};
685687

686688
if (response.jsonCode === 200 && !error) {
@@ -762,7 +764,9 @@ function setupWithdrawalAccount(data) {
762764
}
763765
} else {
764766
if (response.jsonCode === 666 || response.jsonCode === 404) {
765-
error = response.message;
767+
// Since these specific responses can have an error message in html format with richer content, give priority to the html error.
768+
error = response.htmlMessage || response.message;
769+
isErrorHTML = Boolean(response.htmlMessage);
766770
}
767771

768772
if (response.jsonCode === 402) {
@@ -790,7 +794,7 @@ function setupWithdrawalAccount(data) {
790794
}
791795
if (error) {
792796
showBankAccountFormValidationError(error);
793-
showBankAccountErrorModal(error);
797+
showBankAccountErrorModal(error, isErrorHTML);
794798
}
795799
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {loading: false});
796800
})

src/pages/ReimbursementAccount/ReimbursementAccountForm.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class ReimbursementAccountForm extends React.Component {
5353
this.form.scrollTo({y: 0, animated: true});
5454
}}
5555
message={this.props.reimbursementAccount.errorModalMessage}
56+
isMessageHtml={this.props.reimbursementAccount.isErrorModalMessageHtml}
5657
/>
5758
</ScrollView>
5859
);

src/pages/home/report/ReportActionItemFragment.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class ReportActionItemFragment extends React.PureComponent {
6666
return fragment.html !== fragment.text
6767
? (
6868
<RenderHTML
69-
html={fragment.html + (fragment.isEdited ? '<edited></edited>' : '')}
69+
html={`<comment>${fragment.html + (fragment.isEdited ? '<edited></edited>' : '')}</comment>`}
7070
/>
7171
) : (
7272
<Text

0 commit comments

Comments
 (0)