1
+ import ReactMessageRenderer , { defaultMessageConfig } from '@botpress/messaging-components'
1
2
import classnames from 'classnames'
2
3
import _ from 'lodash'
3
- import mimeTypes from 'mime/lite'
4
4
import moment from 'moment'
5
- import path from 'path'
6
5
import React from 'react'
7
- import ReactAudioPlayer from 'react-audio-player'
8
6
9
7
import { Message as HitlMessage } from '../../../../backend/typings'
10
8
import SVGIcon from '../SVGIcon'
11
9
12
- const validMessageTypes = [
13
- 'text' ,
14
- 'message' ,
15
- 'image' ,
16
- 'video' ,
17
- 'audio' ,
18
- 'quick_reply' ,
19
- 'custom' ,
20
- 'visit' ,
21
- 'file' ,
22
- 'carousel'
23
- ]
24
-
25
- const getComponent = ( moduleName : string , componentName : string ) =>
26
- window . botpress [ moduleName ] && window . botpress [ moduleName ] [ componentName ]
27
-
28
10
export default class Message extends React . Component < { message : HitlMessage } > {
29
- renderFile ( ) {
30
- const { type, raw_message, text } = this . props . message
31
-
32
- const url = _ . get ( raw_message , 'url' , text )
33
- const name = _ . get ( raw_message , 'name' , '' )
34
-
35
- const extension = path . extname ( url )
36
- const mime = mimeTypes . getType ( extension )
37
-
38
- if ( type === 'image' || mime . includes ( 'image/' ) ) {
39
- return (
40
- < a href = { url } target = { '_blank' } >
41
- < img src = { url } title = { name } />
42
- </ a >
43
- )
44
- } else if ( type === 'audio' || mime . includes ( 'audio/' ) ) {
45
- return < ReactAudioPlayer src = { this . props . message . text } />
46
- } else if ( type === 'video' || mime . includes ( 'video/' ) ) {
47
- return (
48
- < video controls >
49
- < source src = { this . props . message . text } type = "video/mp4" />
50
- </ video >
51
- )
52
- }
53
-
54
- return < p > Unsupported media</ p >
55
- }
56
-
57
- renderText ( text ?: string ) {
58
- const Text = getComponent ( 'channel-web' , 'Text' )
59
- return Text ? < Text markdown = { true } text = { text || this . props . message . text } /> : < span > { text } </ span >
60
- }
61
-
62
- renderDropdown ( ) {
63
- const Dropdown = getComponent ( 'channel-web' , 'Dropdown' )
64
- return Dropdown ? (
65
- < Dropdown isLastGroup = { true } isLastOfGroup = { true } options = { this . props . message . raw_message . options } />
66
- ) : null
67
- }
68
-
69
- renderCarousel ( ) {
70
- const Carousel = getComponent ( 'channel-web' , 'Carousel' )
71
- return Carousel ? (
72
- < Carousel style = { { maxWidth : '400px' } } carousel = { this . props . message . raw_message } />
73
- ) : (
74
- < span > Could not display carousel</ span >
75
- )
76
- }
77
-
78
- renderQuickReply ( quickReplies ) {
79
- const Keyboard = getComponent ( 'channel-web' , 'Keyboard' )
80
- const QuickReplies = getComponent ( 'channel-web' , 'QuickReplies' )
81
-
82
- return Keyboard && QuickReplies ? (
83
- < span >
84
- < div style = { { paddingBottom : 10 } } > { this . renderText ( ) } </ div >
85
- < Keyboard . Default />
86
- < QuickReplies quick_replies = { quickReplies } isLastGroup = { true } isLastOfGroup = { true } />
87
- </ span >
88
- ) : (
89
- < span > Could not display quick replies</ span >
90
- )
91
- }
92
-
93
11
renderContent ( ) {
94
- const { type, raw_message } = this . props . message
95
-
96
- if ( type === 'message' || type === 'text' || type === 'quick_reply' ) {
97
- return this . renderText ( )
98
- } else if ( type === 'image' || type === 'file' || type === 'video' || type === 'audio' ) {
99
- return this . renderFile ( )
100
- } else if ( type === 'custom' && raw_message ) {
101
- if ( raw_message . component === 'Dropdown' && raw_message . options ) {
102
- return this . renderDropdown ( )
103
- } else if ( raw_message . component === 'QuickReplies' && raw_message . quick_replies ) {
104
- return this . renderQuickReply ( raw_message . quick_replies )
105
- }
12
+ let { raw_message : payload } = this . props . message
13
+ const { ts, source } = this . props . message
106
14
107
- return (
108
- < span >
109
- Bot sent custom component: [Module: { raw_message . module } , Component: { raw_message . component } ]
110
- </ span >
111
- )
112
- } else if ( type === 'carousel' ) {
113
- return this . renderCarousel ( )
15
+ if ( ! payload . type ) {
16
+ payload = { ...payload , type : 'text' }
114
17
}
115
18
116
- return < span > Cannot display this message</ span >
19
+ return (
20
+ < ReactMessageRenderer
21
+ content = { payload }
22
+ config = { {
23
+ ...defaultMessageConfig ,
24
+ isBotMessage : source !== 'user' ,
25
+ isLastGroup : false ,
26
+ isLastOfGroup : false ,
27
+ sentOn : ts
28
+ } }
29
+ />
30
+ )
117
31
}
118
32
119
33
renderMessage ( ) {
@@ -122,12 +36,19 @@ export default class Message extends React.Component<{ message: HitlMessage }> {
122
36
123
37
let messageFrom = 'bot'
124
38
if ( direction === 'in' ) {
39
+ // TODO: Visit and session reset are currently unsupported by @botpress /messaging-components
125
40
if ( type === 'visit' ) {
126
41
return (
127
42
< div className = { classnames ( 'bph-message' , 'bph-from-system' ) } >
128
43
< p > User visit: { date } </ p >
129
44
</ div >
130
45
)
46
+ } else if ( type === 'session_reset' ) {
47
+ return (
48
+ < div className = { classnames ( 'bph-message' , 'bph-from-system' ) } >
49
+ < p > Reset the conversation</ p >
50
+ </ div >
51
+ )
131
52
}
132
53
messageFrom = 'user'
133
54
} else if ( source === 'agent' ) {
@@ -150,18 +71,14 @@ export default class Message extends React.Component<{ message: HitlMessage }> {
150
71
>
151
72
{ messageFrom === 'user' && avatar }
152
73
< div className = "bph-message-container" >
153
- < div className = " bph-chat-bubble" > { this . renderContent ( ) } </ div >
74
+ < div className = { classnames ( ' bph-chat-bubble' , { [ 'card' ] : type === 'card' } ) } > { this . renderContent ( ) } </ div >
154
75
</ div >
155
76
{ messageFrom !== 'user' && avatar }
156
77
</ div >
157
78
)
158
79
}
159
80
160
81
render ( ) {
161
- if ( ! validMessageTypes . includes ( this . props . message . type ) ) {
162
- return null
163
- }
164
-
165
82
return this . renderMessage ( )
166
83
}
167
84
}
0 commit comments