@botonic/react 0.27.2 → 0.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/assets/thumbs-down.svg +3 -0
- package/lib/cjs/assets/thumbs-up.svg +3 -0
- package/lib/cjs/components/index-types.d.ts +2 -0
- package/lib/cjs/components/index-types.js +0 -14
- package/lib/cjs/components/index-types.js.map +1 -1
- package/lib/cjs/components/message/index.js +6 -3
- package/lib/cjs/components/message/index.js.map +1 -1
- package/lib/cjs/components/message/message-feedback.d.ts +6 -0
- package/lib/cjs/components/message/message-feedback.js +60 -0
- package/lib/cjs/components/message/message-feedback.js.map +1 -0
- package/lib/cjs/components/message/message-footer.d.ts +10 -0
- package/lib/cjs/components/message/message-footer.js +21 -0
- package/lib/cjs/components/message/message-footer.js.map +1 -0
- package/lib/cjs/components/message/styles.d.ts +3 -0
- package/lib/cjs/components/message/styles.js +48 -3
- package/lib/cjs/components/message/styles.js.map +1 -1
- package/lib/cjs/components/text.d.ts +6 -7
- package/lib/cjs/components/text.js +5 -9
- package/lib/cjs/components/text.js.map +1 -1
- package/lib/cjs/contexts.js +4 -0
- package/lib/cjs/contexts.js.map +1 -1
- package/lib/cjs/dev-app.d.ts +2 -1
- package/lib/cjs/dev-app.js +5 -3
- package/lib/cjs/dev-app.js.map +1 -1
- package/lib/cjs/index-types.d.ts +7 -0
- package/lib/cjs/index-types.js.map +1 -1
- package/lib/cjs/webchat/tracking.d.ts +7 -0
- package/lib/cjs/webchat/tracking.js +13 -0
- package/lib/cjs/webchat/tracking.js.map +1 -0
- package/lib/cjs/webchat/webchat.js +1 -0
- package/lib/cjs/webchat/webchat.js.map +1 -1
- package/lib/cjs/webchat-app.d.ts +3 -1
- package/lib/cjs/webchat-app.js +5 -3
- package/lib/cjs/webchat-app.js.map +1 -1
- package/lib/esm/assets/thumbs-down.svg +3 -0
- package/lib/esm/assets/thumbs-up.svg +3 -0
- package/lib/esm/components/index-types.d.ts +2 -0
- package/lib/esm/components/index-types.js +0 -14
- package/lib/esm/components/index-types.js.map +1 -1
- package/lib/esm/components/message/index.js +7 -4
- package/lib/esm/components/message/index.js.map +1 -1
- package/lib/esm/components/message/message-feedback.d.ts +6 -0
- package/lib/esm/components/message/message-feedback.js +56 -0
- package/lib/esm/components/message/message-feedback.js.map +1 -0
- package/lib/esm/components/message/message-footer.d.ts +10 -0
- package/lib/esm/components/message/message-footer.js +17 -0
- package/lib/esm/components/message/message-footer.js.map +1 -0
- package/lib/esm/components/message/styles.d.ts +3 -0
- package/lib/esm/components/message/styles.js +47 -2
- package/lib/esm/components/message/styles.js.map +1 -1
- package/lib/esm/components/text.d.ts +6 -7
- package/lib/esm/components/text.js +5 -8
- package/lib/esm/components/text.js.map +1 -1
- package/lib/esm/contexts.js +4 -0
- package/lib/esm/contexts.js.map +1 -1
- package/lib/esm/dev-app.d.ts +2 -1
- package/lib/esm/dev-app.js +5 -3
- package/lib/esm/dev-app.js.map +1 -1
- package/lib/esm/index-types.d.ts +7 -0
- package/lib/esm/index-types.js.map +1 -1
- package/lib/esm/webchat/tracking.d.ts +7 -0
- package/lib/esm/webchat/tracking.js +10 -0
- package/lib/esm/webchat/tracking.js.map +1 -0
- package/lib/esm/webchat/webchat.js +1 -0
- package/lib/esm/webchat/webchat.js.map +1 -1
- package/lib/esm/webchat-app.d.ts +3 -1
- package/lib/esm/webchat-app.js +5 -3
- package/lib/esm/webchat-app.js.map +1 -1
- package/package.json +3 -3
- package/src/assets/thumbs-down.svg +3 -0
- package/src/assets/thumbs-up.svg +3 -0
- package/src/components/index-types.ts +3 -19
- package/src/components/message/index.jsx +17 -8
- package/src/components/message/message-feedback.tsx +99 -0
- package/src/components/message/message-footer.tsx +52 -0
- package/src/components/message/styles.ts +50 -2
- package/src/components/{text.jsx → text.tsx} +7 -7
- package/src/contexts.tsx +3 -0
- package/src/dev-app.jsx +5 -0
- package/src/index-types.ts +9 -1
- package/src/webchat/tracking.ts +8 -0
- package/src/webchat/webchat.jsx +1 -0
- package/src/webchat-app.jsx +5 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React, { useContext, useEffect, useState } from 'react'
|
|
2
|
+
import { v4 as uuid } from 'uuid'
|
|
3
|
+
|
|
4
|
+
import ThumbsDown from '../../assets/thumbs-down.svg'
|
|
5
|
+
import ThumbsUp from '../../assets/thumbs-up.svg'
|
|
6
|
+
import { RequestContext, WebchatContext } from '../../contexts'
|
|
7
|
+
import { ActionRequest } from '../../index-types'
|
|
8
|
+
import { resolveImage } from '../../util'
|
|
9
|
+
import { EventAction, FeedbackOption } from '../../webchat/tracking'
|
|
10
|
+
import { FeedbackButton, FeedbackMessageContainer } from './styles'
|
|
11
|
+
|
|
12
|
+
interface ButtonsState {
|
|
13
|
+
positive: boolean
|
|
14
|
+
negative: boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface RatingProps {
|
|
18
|
+
inferenceId?: string
|
|
19
|
+
messageId: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const MessageFeedback = ({ inferenceId, messageId }: RatingProps) => {
|
|
23
|
+
const { webchatState, updateMessage, trackEvent } = useContext(WebchatContext)
|
|
24
|
+
const request = useContext(RequestContext)
|
|
25
|
+
|
|
26
|
+
const [className, setClassName] = useState('')
|
|
27
|
+
const [disabled, setDisabled] = useState<ButtonsState>({
|
|
28
|
+
positive: false,
|
|
29
|
+
negative: false,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const updateMsgWithFeedback = (feedbackEnabled: boolean) => {
|
|
33
|
+
const message = webchatState.messagesJSON.find(
|
|
34
|
+
message => message.id === messageId
|
|
35
|
+
)
|
|
36
|
+
const updatedMsg = {
|
|
37
|
+
...message,
|
|
38
|
+
feedbackEnabled,
|
|
39
|
+
}
|
|
40
|
+
updateMessage(updatedMsg)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
updateMsgWithFeedback(true)
|
|
45
|
+
}, [])
|
|
46
|
+
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
if (disabled.positive || disabled.negative) {
|
|
49
|
+
setClassName('clicked')
|
|
50
|
+
updateMsgWithFeedback(false)
|
|
51
|
+
}
|
|
52
|
+
}, [disabled])
|
|
53
|
+
|
|
54
|
+
const handleClick = async (isUseful: boolean) => {
|
|
55
|
+
if (!trackEvent) {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (isUseful) {
|
|
60
|
+
setDisabled({ positive: false, negative: true })
|
|
61
|
+
} else {
|
|
62
|
+
setDisabled({ positive: true, negative: false })
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const args = {
|
|
66
|
+
knowledgebaseInferenceId: inferenceId,
|
|
67
|
+
feedbackTargetId: messageId,
|
|
68
|
+
feedbackGroupId: uuid(),
|
|
69
|
+
possibleOptions: [FeedbackOption.ThumbsUp, FeedbackOption.ThumbsDown],
|
|
70
|
+
possibleValues: [0, 1],
|
|
71
|
+
option: isUseful ? FeedbackOption.ThumbsUp : FeedbackOption.ThumbsDown,
|
|
72
|
+
value: isUseful ? 1 : 0,
|
|
73
|
+
}
|
|
74
|
+
await trackEvent(
|
|
75
|
+
request as ActionRequest,
|
|
76
|
+
EventAction.FeedbackKnowledgebase,
|
|
77
|
+
args
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<FeedbackMessageContainer>
|
|
83
|
+
<FeedbackButton
|
|
84
|
+
className={className}
|
|
85
|
+
disabled={disabled.positive}
|
|
86
|
+
onClick={() => handleClick(true)}
|
|
87
|
+
>
|
|
88
|
+
<img src={resolveImage(ThumbsUp)} />
|
|
89
|
+
</FeedbackButton>
|
|
90
|
+
<FeedbackButton
|
|
91
|
+
className={className}
|
|
92
|
+
disabled={disabled.negative}
|
|
93
|
+
onClick={() => handleClick(false)}
|
|
94
|
+
>
|
|
95
|
+
<img src={resolveImage(ThumbsDown)} />
|
|
96
|
+
</FeedbackButton>
|
|
97
|
+
</FeedbackMessageContainer>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React, { useContext } from 'react'
|
|
2
|
+
|
|
3
|
+
import { WebchatContext } from '../../contexts'
|
|
4
|
+
import { SENDERS } from '../../index-types'
|
|
5
|
+
import { MessageFeedback } from './message-feedback'
|
|
6
|
+
import { MessageFooterContainer } from './styles'
|
|
7
|
+
import { MessageTimestamp, resolveMessageTimestamps } from './timestamps'
|
|
8
|
+
|
|
9
|
+
interface MessageFooterProps {
|
|
10
|
+
enabletimestamps: boolean
|
|
11
|
+
messageJSON: any
|
|
12
|
+
sentBy: SENDERS
|
|
13
|
+
feedbackEnabled: boolean
|
|
14
|
+
inferenceId?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const MessageFooter = ({
|
|
18
|
+
enabletimestamps,
|
|
19
|
+
messageJSON,
|
|
20
|
+
sentBy,
|
|
21
|
+
feedbackEnabled,
|
|
22
|
+
inferenceId,
|
|
23
|
+
}: MessageFooterProps) => {
|
|
24
|
+
const { getThemeProperty } = useContext(WebchatContext)
|
|
25
|
+
|
|
26
|
+
const { timestampsEnabled, timestampStyle } = resolveMessageTimestamps(
|
|
27
|
+
getThemeProperty,
|
|
28
|
+
enabletimestamps
|
|
29
|
+
)
|
|
30
|
+
const isSentByUser = sentBy === SENDERS.user
|
|
31
|
+
const messageFotterClass = isSentByUser
|
|
32
|
+
? 'message-footer-user'
|
|
33
|
+
: 'message-footer-bot'
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<MessageFooterContainer
|
|
37
|
+
className={messageFotterClass}
|
|
38
|
+
isSentByUser={isSentByUser}
|
|
39
|
+
>
|
|
40
|
+
{timestampsEnabled ? (
|
|
41
|
+
<MessageTimestamp
|
|
42
|
+
sentBy={sentBy}
|
|
43
|
+
style={timestampStyle}
|
|
44
|
+
timestamp={messageJSON.timestamp}
|
|
45
|
+
/>
|
|
46
|
+
) : null}
|
|
47
|
+
{feedbackEnabled ? (
|
|
48
|
+
<MessageFeedback inferenceId={inferenceId} messageId={messageJSON.id} />
|
|
49
|
+
) : null}
|
|
50
|
+
</MessageFooterContainer>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
@@ -85,8 +85,6 @@ export const TimestampContainer = styled.div<TimestampContainerProps>`
|
|
|
85
85
|
|
|
86
86
|
box-sizing: border-box;
|
|
87
87
|
width: 100%;
|
|
88
|
-
padding: 0px 15px 4px 15px;
|
|
89
|
-
padding-top: ${props => (props.isSentByUser ? '0px' : '4px')};
|
|
90
88
|
|
|
91
89
|
img {
|
|
92
90
|
max-width: 20px;
|
|
@@ -103,3 +101,53 @@ export const TimestampText = styled.div<TimestampTextProps>`
|
|
|
103
101
|
color: ${COLORS.SOLID_BLACK};
|
|
104
102
|
text-align: ${props => (props.isSentByUser ? 'right' : 'left')};
|
|
105
103
|
`
|
|
104
|
+
|
|
105
|
+
export const MessageFooterContainer = styled.div<TimestampContainerProps>`
|
|
106
|
+
display: flex;
|
|
107
|
+
justify-content: space-between;
|
|
108
|
+
align-items: center;
|
|
109
|
+
|
|
110
|
+
box-sizing: border-box;
|
|
111
|
+
padding: 0px 15px 4px 15px;
|
|
112
|
+
padding-top: ${props => (props.isSentByUser ? '0px' : '4px')};
|
|
113
|
+
width: 100%;
|
|
114
|
+
`
|
|
115
|
+
|
|
116
|
+
export const FeedbackMessageContainer = styled.div`
|
|
117
|
+
display: flex;
|
|
118
|
+
justify-content: space-between;
|
|
119
|
+
align-items: center;
|
|
120
|
+
gap: 4px;
|
|
121
|
+
|
|
122
|
+
box-sizing: border-box;
|
|
123
|
+
`
|
|
124
|
+
|
|
125
|
+
export const FeedbackButton = styled.button`
|
|
126
|
+
display: flex;
|
|
127
|
+
justify-content: center;
|
|
128
|
+
align-items: center;
|
|
129
|
+
|
|
130
|
+
background: none;
|
|
131
|
+
box-sizing: border-box;
|
|
132
|
+
border: none;
|
|
133
|
+
border-radius: 4px;
|
|
134
|
+
padding: 8px 8px;
|
|
135
|
+
height: 24px;
|
|
136
|
+
width: 24px;
|
|
137
|
+
|
|
138
|
+
&:hover {
|
|
139
|
+
cursor: pointer;
|
|
140
|
+
background-color: #f4f3f4;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
&:disabled {
|
|
144
|
+
cursor: default;
|
|
145
|
+
background: none;
|
|
146
|
+
opacity: 0.3;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
&.clicked {
|
|
150
|
+
opacity: 0;
|
|
151
|
+
transition: 1s 1s;
|
|
152
|
+
}
|
|
153
|
+
`
|
|
@@ -2,6 +2,7 @@ import { INPUT } from '@botonic/core'
|
|
|
2
2
|
import React, { Children } from 'react'
|
|
3
3
|
|
|
4
4
|
import { mapObjectNonBooleanValues } from '../util/react'
|
|
5
|
+
import { TextProps } from './index-types'
|
|
5
6
|
import { serializeMarkdown, toMarkdownChildren } from './markdown'
|
|
6
7
|
import { Message } from './message'
|
|
7
8
|
|
|
@@ -17,7 +18,7 @@ const serializeText = children => {
|
|
|
17
18
|
return text
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
const serialize = textProps => {
|
|
21
|
+
const serialize = (textProps: TextProps) => {
|
|
21
22
|
if (!textProps.markdown)
|
|
22
23
|
return {
|
|
23
24
|
text: serializeText(textProps.children),
|
|
@@ -25,20 +26,19 @@ const serialize = textProps => {
|
|
|
25
26
|
return { text: serializeMarkdown(textProps.children) }
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
*
|
|
30
|
-
* @param {TextProps} props
|
|
31
|
-
* @returns {JSX.Element}
|
|
32
|
-
*/
|
|
33
|
-
export const Text = props => {
|
|
29
|
+
export const Text = (props: TextProps) => {
|
|
34
30
|
const defaultTextProps = {
|
|
35
31
|
markdown: props.markdown === undefined ? true : props.markdown,
|
|
32
|
+
feedbackEnabled: props.feedbackEnabled,
|
|
33
|
+
inferenceId: props.inferenceId,
|
|
36
34
|
}
|
|
35
|
+
|
|
37
36
|
const textProps = mapObjectNonBooleanValues({
|
|
38
37
|
...props,
|
|
39
38
|
...defaultTextProps,
|
|
40
39
|
...{ children: Children.toArray(props.children) },
|
|
41
40
|
})
|
|
41
|
+
|
|
42
42
|
if (!textProps.markdown)
|
|
43
43
|
return (
|
|
44
44
|
<Message json={serialize(textProps)} {...textProps} type={INPUT.TEXT}>
|
package/src/contexts.tsx
CHANGED
package/src/dev-app.jsx
CHANGED
|
@@ -26,6 +26,7 @@ export class DevApp extends WebchatApp {
|
|
|
26
26
|
onOpen,
|
|
27
27
|
onClose,
|
|
28
28
|
onMessage,
|
|
29
|
+
onTrackEvent,
|
|
29
30
|
...botOptions
|
|
30
31
|
}) {
|
|
31
32
|
super({
|
|
@@ -45,6 +46,7 @@ export class DevApp extends WebchatApp {
|
|
|
45
46
|
onOpen,
|
|
46
47
|
onClose,
|
|
47
48
|
onMessage,
|
|
49
|
+
onTrackEvent,
|
|
48
50
|
})
|
|
49
51
|
this.bot = new ReactBot({
|
|
50
52
|
...botOptions,
|
|
@@ -67,6 +69,7 @@ export class DevApp extends WebchatApp {
|
|
|
67
69
|
onOpen,
|
|
68
70
|
onClose,
|
|
69
71
|
onMessage,
|
|
72
|
+
onTrackEvent,
|
|
70
73
|
hostId,
|
|
71
74
|
...webchatOptions
|
|
72
75
|
} = optionsAtRuntime
|
|
@@ -84,6 +87,7 @@ export class DevApp extends WebchatApp {
|
|
|
84
87
|
this.onOpen = onOpen || this.onOpen
|
|
85
88
|
this.onClose = onClose || this.onClose
|
|
86
89
|
this.onMessage = onMessage || this.onMessage
|
|
90
|
+
this.onTrackEvent = onTrackEvent || this.onTrackEvent
|
|
87
91
|
this.hostId = hostId || this.hostId
|
|
88
92
|
this.createRootElement(host)
|
|
89
93
|
return (
|
|
@@ -108,6 +112,7 @@ export class DevApp extends WebchatApp {
|
|
|
108
112
|
onOpen={(...args) => this.onOpenWebchat(...args)}
|
|
109
113
|
onClose={(...args) => this.onCloseWebchat(...args)}
|
|
110
114
|
onUserInput={(...args) => this.onUserInput(...args)}
|
|
115
|
+
onTrackEvent={(...args) => this.onTrackEvent(...args)}
|
|
111
116
|
/>
|
|
112
117
|
)
|
|
113
118
|
}
|
package/src/index-types.ts
CHANGED
|
@@ -117,13 +117,20 @@ export interface WebchatArgs {
|
|
|
117
117
|
onMessage?: (app: WebchatApp, message: WebchatMessage) => void
|
|
118
118
|
onOpen?: (app: WebchatApp, args: any) => void
|
|
119
119
|
onConnectionChange?: (app: WebchatApp, isOnline: boolean) => void
|
|
120
|
+
onTrackEvent?: TrackEventFunction
|
|
120
121
|
persistentMenu?: PersistentMenuTheme
|
|
121
122
|
storage?: Storage | null
|
|
122
123
|
storageKey?: any
|
|
123
124
|
theme?: ThemeProps
|
|
124
125
|
}
|
|
125
126
|
|
|
126
|
-
|
|
127
|
+
type EventArgs = { [key: string]: any }
|
|
128
|
+
type TrackEventFunction = (
|
|
129
|
+
request: ActionRequest,
|
|
130
|
+
eventName: string,
|
|
131
|
+
args?: EventArgs
|
|
132
|
+
) => Promise<void>
|
|
133
|
+
|
|
127
134
|
export interface WebchatAppArgs {
|
|
128
135
|
appId?: string
|
|
129
136
|
visibility?: () => boolean
|
|
@@ -201,6 +208,7 @@ export interface WebchatContextProps {
|
|
|
201
208
|
updateUser: (user: Partial<CoreSessionUser>) => void
|
|
202
209
|
updateWebchatDevSettings: (settings: WebchatSettingsProps) => void
|
|
203
210
|
webchatState: WebchatState
|
|
211
|
+
trackEvent: TrackEventFunction
|
|
204
212
|
}
|
|
205
213
|
|
|
206
214
|
// export class DevApp extends WebchatApp {
|
package/src/webchat/webchat.jsx
CHANGED
|
@@ -880,6 +880,7 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
880
880
|
updateUser: updateSessionWithUser,
|
|
881
881
|
updateWebchatDevSettings: updateWebchatDevSettings,
|
|
882
882
|
webchatState,
|
|
883
|
+
trackEvent: props.onTrackEvent,
|
|
883
884
|
}}
|
|
884
885
|
>
|
|
885
886
|
{!webchatState.isWebchatOpen && <TriggerButton />}
|
package/src/webchat-app.jsx
CHANGED
|
@@ -29,6 +29,7 @@ export class WebchatApp {
|
|
|
29
29
|
onOpen,
|
|
30
30
|
onClose,
|
|
31
31
|
onMessage,
|
|
32
|
+
onTrackEvent,
|
|
32
33
|
onConnectionChange,
|
|
33
34
|
appId,
|
|
34
35
|
visibility,
|
|
@@ -58,6 +59,7 @@ export class WebchatApp {
|
|
|
58
59
|
this.onOpen = onOpen
|
|
59
60
|
this.onClose = onClose
|
|
60
61
|
this.onMessage = onMessage
|
|
62
|
+
this.onTrackEvent = onTrackEvent
|
|
61
63
|
this.onConnectionChange = onConnectionChange
|
|
62
64
|
this.visibility = visibility
|
|
63
65
|
this.server = server
|
|
@@ -284,6 +286,7 @@ export class WebchatApp {
|
|
|
284
286
|
onClose,
|
|
285
287
|
onMessage,
|
|
286
288
|
onConnectionChange,
|
|
289
|
+
onTrackEvent,
|
|
287
290
|
appId,
|
|
288
291
|
visibility,
|
|
289
292
|
server,
|
|
@@ -307,6 +310,7 @@ export class WebchatApp {
|
|
|
307
310
|
this.onOpen = onOpen || this.onOpen
|
|
308
311
|
this.onClose = onClose || this.onClose
|
|
309
312
|
this.onMessage = onMessage || this.onMessage
|
|
313
|
+
this.onTrackEvent = onTrackEvent || this.onTrackEvent
|
|
310
314
|
this.onConnectionChange = onConnectionChange || this.onConnectionChange
|
|
311
315
|
this.visibility = visibility || this.visibility
|
|
312
316
|
this.appId = appId || this.appId
|
|
@@ -335,6 +339,7 @@ export class WebchatApp {
|
|
|
335
339
|
onClose={(...args) => this.onCloseWebchat(...args)}
|
|
336
340
|
onUserInput={(...args) => this.onUserInput(...args)}
|
|
337
341
|
onStateChange={webchatState => this.onStateChange(webchatState)}
|
|
342
|
+
onTrackEvent={(...args) => this.onTrackEvent(...args)}
|
|
338
343
|
server={server}
|
|
339
344
|
/>
|
|
340
345
|
)
|