Skip to content

Add tag muted-text BaseHTMLEngineProvider to render html errors #5550

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Oct 13, 2021
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
18 changes: 15 additions & 3 deletions src/components/FormAlertWithSubmitButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Button from './Button';
import withLocalize, {withLocalizePropTypes} from './withLocalize';
import TextLink from './TextLink';
import Text from './Text';
import RenderHTML from './RenderHTML';

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

/** Whether message is in html format */
isMessageHtml: PropTypes.bool,

...withLocalizePropTypes,
};

const defaultProps = {
message: '',
isMessageHtml: false,
};

const FormAlertWithSubmitButton = ({
Expand All @@ -41,6 +46,7 @@ const FormAlertWithSubmitButton = ({
translate,
onFixTheErrorsLinkPressed,
message,
isMessageHtml,
}) => {
/**
* @returns {React.Component}
Expand All @@ -49,9 +55,15 @@ const FormAlertWithSubmitButton = ({
let error = '';

if (!_.isEmpty(message)) {
error = (
<Text style={styles.mutedTextLabel}>{message}</Text>
);
if (isMessageHtml) {
error = (
<RenderHTML html={`<muted-text>${message}</muted-text>`} />
);
} else {
error = (
<Text style={styles.mutedTextLabel}>{message}</Text>
);
}
} else {
error = (
<>
Expand Down
42 changes: 41 additions & 1 deletion src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable react/prop-types */
import _ from 'underscore';
import React, {useMemo} from 'react';
import {TouchableOpacity} from 'react-native';
import {TouchableOpacity, Linking} from 'react-native';
import {
TRenderEngineProvider,
RenderHTMLConfigProvider,
Expand Down Expand Up @@ -66,6 +66,23 @@ function computeEmbeddedMaxWidth(tagName, contentWidth) {
return contentWidth;
}

/**
* Check if there is an ancestor node with name 'comment'.
* Finding node with name 'comment' flags that we are rendering a comment.
* @param {TNode} tnode
* @returns {Boolean}
*/
function isInsideComment(tnode) {
let currentNode = tnode;
while (currentNode.parent) {
if (currentNode.domNode.name === 'comment') {
return true;
}
currentNode = currentNode.parent;
}
return false;
}

function AnchorRenderer({tnode, key, style}) {
const htmlAttribs = tnode.attributes;

Expand All @@ -89,6 +106,22 @@ function AnchorRenderer({tnode, key, style}) {
);
}

if (!isInsideComment(tnode)) {
// This is not a comment from a chat, the AnchorForCommentsOnly uses a Pressable to create a context menu on right click.
// We don't have this behaviour in other links in NewDot
// TODO: We should use TextLink, but I'm leaving it as Text for now because TextLink breaks the alignment in Android.
return (
<Text
style={styles.link}
onPress={() => {
Linking.openURL(htmlAttribs.href);
}}
>
<TNodeChildrenRenderer tnode={tnode} />
</Text>
);
}

return (
<AnchorForCommentsOnly
href={htmlAttribs.href}
Expand Down Expand Up @@ -223,6 +256,13 @@ const customHTMLElementModels = {
edited: defaultHTMLElementModels.span.extend({
tagName: 'edited',
}),
'muted-text': defaultHTMLElementModels.div.extend({
tagName: 'muted-text',
mixedUAStyles: styles.mutedTextLabel,
}),
comment: defaultHTMLElementModels.div.extend({
tagName: 'comment',
}),
};

// Define the custom renderer components
Expand Down
12 changes: 8 additions & 4 deletions src/libs/actions/BankAccounts.js
Original file line number Diff line number Diff line change
Expand Up @@ -526,9 +526,10 @@ function setFreePlanVerifiedBankAccountID(bankAccountID) {
* Show error modal and optionally a specific error message
*
* @param {String} errorModalMessage The error message to be displayed in the modal's body.
* @param {Boolean} isErrorModalMessageHtml if @errorModalMessage is in html format or not
*/
function showBankAccountErrorModal(errorModalMessage = null) {
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {errorModalMessage});
function showBankAccountErrorModal(errorModalMessage = null, isErrorModalMessageHtml = false) {
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {errorModalMessage, isErrorModalMessageHtml});
}

/**
Expand Down Expand Up @@ -655,6 +656,7 @@ function setupWithdrawalAccount(data) {
const currentStep = newACHData.currentStep;
let achData = lodashGet(response, 'achData', {});
let error = lodashGet(achData, CONST.BANK_ACCOUNT.VERIFICATIONS.ERROR_MESSAGE);
let isErrorHTML = false;
const errors = {};

if (response.jsonCode === 200 && !error) {
Expand Down Expand Up @@ -733,7 +735,9 @@ function setupWithdrawalAccount(data) {
}
} else {
if (response.jsonCode === 666 || response.jsonCode === 404) {
error = response.message;
// Since these specific responses can have an error message in html format with richer content, give priority to the html error.
error = response.htmlMessage || response.message;
isErrorHTML = Boolean(response.htmlMessage);
}

if (response.jsonCode === 402) {
Expand Down Expand Up @@ -761,7 +765,7 @@ function setupWithdrawalAccount(data) {
}
if (error) {
showBankAccountFormValidationError(error);
showBankAccountErrorModal(error);
showBankAccountErrorModal(error, isErrorHTML);
}
})
.catch((response) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class ReimbursementAccountForm extends React.Component {
this.form.scrollTo({y: 0, animated: true});
}}
message={this.props.reimbursementAccount.errorModalMessage}
isMessageHtml={this.props.reimbursementAccount.isErrorModalMessageHtml}
/>
</ScrollView>
);
Expand Down
2 changes: 1 addition & 1 deletion src/pages/home/report/ReportActionItemFragment.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class ReportActionItemFragment extends React.PureComponent {
return fragment.html !== fragment.text
? (
<RenderHTML
html={fragment.html + (fragment.isEdited ? '<edited></edited>' : '')}
html={`<comment>${fragment.html + (fragment.isEdited ? '<edited></edited>' : '')}</comment>`}
/>
) : (
<Text
Expand Down