Skip to content
This repository was archived by the owner on Jun 3, 2025. It is now read-only.

Commit f889826

Browse files
JWandrockeGitHub Enterprise
authored andcommitted
Merge pull request #52 from ML-Leonardo/fix/custom_json_issues
Fixed issue where trying to do a map on a undefined element. (Possib…
2 parents 0990224 + 925f4ec commit f889826

File tree

9 files changed

+361
-32
lines changed

9 files changed

+361
-32
lines changed

src/components/Message/Buttons.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
33

44
import Button from 'components/Button'
55

6-
import { truncate } from 'helpers'
6+
import { truncate, safeArrayOfItem } from 'helpers'
77

88
import './style.scss'
99

@@ -16,7 +16,7 @@ const Buttons = ({ content, sendMessage, style, readOnlyMode }) => {
1616
</p>
1717

1818
<div className='Buttons--container'>
19-
{buttons.slice(0, 3).map((b, i) => (
19+
{safeArrayOfItem(buttons).slice(0, 3).map((b, i) => (
2020
<Button
2121
key={i}
2222
button={b}

src/components/Message/Card.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react'
22
import PropTypes from 'prop-types'
33
import { sanitizeUrl } from '@braintree/sanitize-url'
44

5-
import { truncate } from 'helpers'
5+
import { truncate, safeArrayOfItem } from 'helpers'
66

77
import Button from 'components/Button'
88

@@ -25,7 +25,7 @@ const Card = ({ content, sendMessage, onImageLoaded, readOnlyMode }) => {
2525

2626
{buttons && buttons.length ? (
2727
<div className='RecastAppCard--button-container CaiAppCard--button-container'>
28-
{buttons.slice(0, 3).map((b, i) => (
28+
{safeArrayOfItem(buttons).slice(0, 3).map((b, i) => (
2929
<Button
3030
key={i}
3131
button={b}

src/components/Message/Carousel.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Slider from 'react-slick'
44

55
import Card from './Card'
66
import { PrevArrow, NextArrow } from 'components/arrows'
7+
import { safeArrayOfItem } from 'helpers'
78

89
import './style.scss'
910

@@ -22,7 +23,7 @@ const Carousel = ({ content, sendMessage, readOnlyMode }) => {
2223
slidesToScroll={1}
2324
className='Slider'
2425
>
25-
{content.map((card, i) => (
26+
{safeArrayOfItem(content).map((card, i) => (
2627
<div key={i}>
2728
<Card content={card} sendMessage={sendMessage} readOnlyMode={readOnlyMode} />
2829
</div>

src/components/Message/List.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { sanitizeUrl } from '@braintree/sanitize-url'
44
import propOr from 'ramda/es/propOr'
55
import cx from 'classnames'
66

7-
import { truncate } from 'helpers'
7+
import { truncate, safeArrayOfItem } from 'helpers'
88

99
import Button from 'components/Button'
1010

@@ -111,11 +111,12 @@ ListElement.propTypes = {
111111
}
112112

113113
const List = ({ content, sendMessage, readOnlyMode }) => {
114-
const button = content.buttons && content.buttons[0]
114+
const { buttons } = content
115+
const button = propOr(null, 0, buttons)
115116

116117
return (
117118
<div className={'RecastAppList CaiAppList'}>
118-
{content.elements.map((element, i) => (
119+
{safeArrayOfItem(content && content.elements).map((element, i) => (
119120
<ListElement
120121
key={i} {...element}
121122
sendMessage={sendMessage}

src/components/Message/QuickReplies.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import map from 'ramda/es/map'
66
import values from 'ramda/es/values'
77
import cx from 'classnames'
88

9-
import { truncate } from 'helpers'
9+
import { truncate, safeArrayOfItem } from 'helpers'
1010

1111
import Text from './Text'
1212
import { PrevArrow, NextArrow } from 'components/arrows'
@@ -79,7 +79,7 @@ class QuickReplies extends Component {
7979
nextArrow={<NextArrow />}
8080
className='RecastAppSlider RecastAppQuickReplies--slider CaiAppSlider CaiAppQuickReplies--slider'
8181
>
82-
{buttons.map((b, i) => (
82+
{safeArrayOfItem(buttons).map((b, i) => (
8383
<div key={i}>
8484
<div
8585
ref={ref => {

src/components/Message/Text.js

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import sanitizeHtml from 'sanitize-html-react'
44
import ReactMarkdown from 'react-markdown'
55
import cx from 'classnames'
66

7-
import { truncate } from 'helpers'
7+
import { truncate, safeStringValue } from 'helpers'
88

99
import './style.scss'
1010

@@ -31,24 +31,12 @@ const allowedMarkdownTypes = [
3131
]
3232

3333
const Text = ({ content, style, isMarkdown, readOnlyMode }) => {
34-
let respond
34+
const respond = safeStringValue(content)
3535

3636
if (typeof isMarkdown !== 'boolean') {
3737
isMarkdown = false
3838
}
3939

40-
if (typeof content === 'string') {
41-
respond = content
42-
} else if (typeof content === 'object') {
43-
respond = JSON.stringify(content)
44-
} else if (typeof content === 'number') {
45-
respond = content.toString()
46-
} else if (content === undefined) {
47-
respond = 'undefined'
48-
} else {
49-
respond = ''
50-
}
51-
5240
let maxLengthLimit = 640
5341
// JIRA: https://sapjira.wdf.sap.corp/browse/SAPMLCONV-4904
5442
if (isMarkdown) {

src/components/Message/index.js

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { Component } from 'react'
22
import PropTypes from 'prop-types'
33
import cx from 'classnames'
44
import contains from 'ramda/es/contains'
5+
import { safeBooleanValue } from 'helpers'
56

67
import Text from './Text'
78
import Card from './Card'
@@ -14,6 +15,15 @@ import QuickReplies from './QuickReplies'
1415
import './style.scss'
1516

1617
class Message extends Component {
18+
state = {
19+
exceptionThrownOccurred: false,
20+
}
21+
22+
componentDidCatch (error, info) {
23+
this.setState({ exceptionThrownOccurred: true })
24+
console.error(error, info)
25+
}
26+
1727
render () {
1828
const {
1929
message,
@@ -37,16 +47,35 @@ class Message extends Component {
3747
botMessageColor,
3848
botMessageBackgroundColor,
3949
} = preferences
40-
const { displayIcon } = message
41-
const { type, content, error, title, markdown } = message.attachment
42-
const isBot = message.participant.isBot
50+
const { displayIcon, attachment, participant } = message
51+
const { type, content, error, title, markdown } = attachment
52+
const { exceptionThrownOccurred } = this.state
53+
if (exceptionThrownOccurred) {
54+
const style = {
55+
color: '#fff',
56+
backgroundColor: '#f44336',
57+
padding: '1.0rem',
58+
textAlign: 'center',
59+
}
60+
61+
return (
62+
<div style={style} className={'RecastAppText CaiAppText'}>
63+
An Error has occured, unable to display this message
64+
</div>
65+
)
66+
}
67+
if (!content) {
68+
console.error('Missing content unable to proceed')
69+
return null
70+
}
71+
const { isBot } = participant
4372

4473
const image = isBot ? botPicture : userPicture
4574
const messageProps = {
4675
isBot,
4776
// Make sure we display the title of a button/quickReply click, and not its value
4877
content: title || content,
49-
isMarkdown: markdown,
78+
isMarkdown: safeBooleanValue(markdown),
5079
readOnlyMode,
5180
onImageLoaded,
5281
style: {

src/helpers.js

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11

22
export const truncate = (string, length) => {
3-
if (string.length <= length) {
4-
return string
5-
}
3+
// console.assert(typeof string === 'string', `Expected a 'string', but got a type:'${typeof string}' - '${string}'`)
4+
if (typeof string === 'string') {
5+
if (string.length <= length) {
6+
return string
7+
}
68

7-
return `${string.slice(0, length - 3)}...`
9+
return `${string.slice(0, length - 3)}...`
10+
}
11+
return ''
812
}
913

1014
const conversationKey = 'cai-conversation'
@@ -41,3 +45,34 @@ export const getCredentialsFromLocalStorage = () => {
4145
}
4246
return null
4347
}
48+
49+
export const safeArrayOfItem = (items) => {
50+
console.assert(items && Array.isArray(items), `Expected a array of items, but got a type:'${typeof items}'`)
51+
if (items && Array.isArray(items)) {
52+
return items
53+
}
54+
return []
55+
}
56+
57+
export const safeBooleanValue = (flag) => {
58+
if (typeof flag === 'boolean') {
59+
return flag
60+
} else if (typeof flag === 'string') {
61+
return flag.toLowerCase() === 'true'
62+
}
63+
return false
64+
}
65+
66+
export const safeStringValue = (content) => {
67+
if (typeof content === 'string') {
68+
return content
69+
} else if (typeof content === 'object') {
70+
return JSON.stringify(content)
71+
} else if (typeof content === 'number') {
72+
return content.toString()
73+
} else if (content === undefined) {
74+
return 'undefined'
75+
}
76+
return ''
77+
}
78+

0 commit comments

Comments
 (0)