diff --git a/packages/botonic-plugin-flow-builder/src/action/knowledge-bases.ts b/packages/botonic-plugin-flow-builder/src/action/knowledge-bases.ts
index 73395c6922..ab84519bfe 100644
--- a/packages/botonic-plugin-flow-builder/src/action/knowledge-bases.ts
+++ b/packages/botonic-plugin-flow-builder/src/action/knowledge-bases.ts
@@ -71,16 +71,17 @@ async function getContentsWithKnowledgeResponse(
return undefined
}
- return updateContentsWithAnswer(contents, knowledgeBaseResponse.answer)
+ return updateContentsWithResponse(contents, knowledgeBaseResponse)
}
-function updateContentsWithAnswer(
+function updateContentsWithResponse(
contents: FlowContent[],
- answer: string
+ response: KnowledgeBaseResponse
): FlowContent[] {
return contents.map(content => {
if (content instanceof FlowKnowledgeBase) {
- content.text = answer
+ content.text = response.answer
+ content.inferenceId = response.inferenceId
}
return content
diff --git a/packages/botonic-plugin-flow-builder/src/content-fields/flow-knowledge-base.tsx b/packages/botonic-plugin-flow-builder/src/content-fields/flow-knowledge-base.tsx
index 4ab2ff475e..fc76bfb139 100644
--- a/packages/botonic-plugin-flow-builder/src/content-fields/flow-knowledge-base.tsx
+++ b/packages/botonic-plugin-flow-builder/src/content-fields/flow-knowledge-base.tsx
@@ -5,19 +5,30 @@ import { ContentFieldsBase } from './content-fields-base'
import { HtKnowledgeBaseNode } from './hubtype-fields'
export class FlowKnowledgeBase extends ContentFieldsBase {
- public code = ''
+ public code: string = ''
+ public feedbackEnabled: boolean = false
public sources: string[] = []
- public text = ''
+ public text: string = ''
+ public inferenceId?: string
static fromHubtypeCMS(component: HtKnowledgeBaseNode): FlowKnowledgeBase {
const newKnowledgeBase = new FlowKnowledgeBase(component.id)
newKnowledgeBase.code = component.code
+ newKnowledgeBase.feedbackEnabled = component.content.feedback_enabled
newKnowledgeBase.sources = component.content.sources
return newKnowledgeBase
}
toBotonic(id: string): JSX.Element {
- return {this.text}
+ return (
+
+ {this.text}
+
+ )
}
}
diff --git a/packages/botonic-plugin-flow-builder/src/content-fields/hubtype-fields/knowledge-base.ts b/packages/botonic-plugin-flow-builder/src/content-fields/hubtype-fields/knowledge-base.ts
index 9e7e7cbc6c..190f8ad4c1 100644
--- a/packages/botonic-plugin-flow-builder/src/content-fields/hubtype-fields/knowledge-base.ts
+++ b/packages/botonic-plugin-flow-builder/src/content-fields/hubtype-fields/knowledge-base.ts
@@ -4,6 +4,7 @@ import { HtNodeWithContentType } from './node-types'
export interface HtKnowledgeBaseNode extends HtBaseNode {
type: HtNodeWithContentType.KNOWLEDGE_BASE
content: {
+ feedback_enabled: boolean
sources: string[]
}
}
diff --git a/packages/botonic-plugin-hubtype-analytics/src/event-models/ht-event-feedback-knowledgebase.ts b/packages/botonic-plugin-hubtype-analytics/src/event-models/ht-event-feedback-knowledgebase.ts
new file mode 100644
index 0000000000..776cde2fea
--- /dev/null
+++ b/packages/botonic-plugin-hubtype-analytics/src/event-models/ht-event-feedback-knowledgebase.ts
@@ -0,0 +1,33 @@
+import {
+ EventAction,
+ EventFeedbackKnowledgebase,
+ EventType,
+ RequestData,
+} from '../types'
+import { HtEvent } from './ht-event'
+
+export class HtEventFeedbackKnowledgebase extends HtEvent {
+ action: EventAction.FeedbackKnowledgebase
+ knowledgebase_inference_id: string
+ feedback_target_id: string
+ feedback_group_id: string
+ possible_options: string[]
+ possible_values?: number[]
+ option: string
+ value?: number
+ comment?: string
+
+ constructor(event: EventFeedbackKnowledgebase, requestData: RequestData) {
+ super(event, requestData)
+ this.type = EventType.WebEvent
+ this.action = event.action
+ this.knowledgebase_inference_id = event.knowledgebaseInferenceId
+ this.feedback_target_id = event.feedbackTargetId
+ this.feedback_group_id = event.feedbackGroupId
+ this.possible_options = event.possibleOptions
+ this.possible_values = event.possibleValues
+ this.option = event.option
+ this.value = event.value
+ this.comment = event.comment
+ }
+}
diff --git a/packages/botonic-plugin-hubtype-analytics/src/event-models/ht-event-feedback.ts b/packages/botonic-plugin-hubtype-analytics/src/event-models/ht-event-feedback.ts
index c05c373d04..b11ec83686 100644
--- a/packages/botonic-plugin-hubtype-analytics/src/event-models/ht-event-feedback.ts
+++ b/packages/botonic-plugin-hubtype-analytics/src/event-models/ht-event-feedback.ts
@@ -7,20 +7,20 @@ export class HtEventFeedback extends HtEvent {
| EventAction.FeedbackConversation
| EventAction.FeedbackMessage
| EventAction.FeedbackWebview
- feedback_target_id?: string
- feedback_group_id?: string
+ feedback_target_id: string
+ feedback_group_id: string
possible_options: string[]
- possible_values: number[]
+ possible_values?: number[]
option: string
- value: number
+ value?: number
comment?: string
constructor(event: EventFeedback, requestData: RequestData) {
super(event, requestData)
this.type = EventType.WebEvent
this.action = event.action
- this.feedback_target_id = event.feedbackTargetId // ?? case_id, message_id, conversation_id ???, webview_name
- this.feedback_group_id = event.feedbackGroupId // ??
+ this.feedback_target_id = event.feedbackTargetId
+ this.feedback_group_id = event.feedbackGroupId
this.possible_options = event.possibleOptions
this.possible_values = event.possibleValues
this.option = event.option
diff --git a/packages/botonic-plugin-hubtype-analytics/src/event-models/index.ts b/packages/botonic-plugin-hubtype-analytics/src/event-models/index.ts
index 9fac8e84d2..db6546c7b2 100644
--- a/packages/botonic-plugin-hubtype-analytics/src/event-models/index.ts
+++ b/packages/botonic-plugin-hubtype-analytics/src/event-models/index.ts
@@ -2,6 +2,7 @@ export { HtEvent } from './ht-event'
export { HtEventCustom } from './ht-event-custom'
export { HtEventFallback } from './ht-event-fallback'
export { HtEventFeedback } from './ht-event-feedback'
+export { HtEventFeedbackKnowledgebase } from './ht-event-feedback-knowledgebase'
export { HtEventFlow } from './ht-event-flow'
export { HtEventHandoff } from './ht-event-handoff'
export { HtEventHandoffOption } from './ht-event-handoff-option'
diff --git a/packages/botonic-plugin-hubtype-analytics/src/types.ts b/packages/botonic-plugin-hubtype-analytics/src/types.ts
index b8457360d4..507015c7f3 100644
--- a/packages/botonic-plugin-hubtype-analytics/src/types.ts
+++ b/packages/botonic-plugin-hubtype-analytics/src/types.ts
@@ -7,6 +7,7 @@ export enum EventAction {
FeedbackCase = 'feedback_case',
FeedbackMessage = 'feedback_message',
FeedbackConversation = 'feedback_conversation',
+ FeedbackKnowledgebase = 'feedback_knowledgebase',
FeedbackWebview = 'feedback_webview',
FlowNode = 'flow_node',
HandoffOption = 'handoff_option',
@@ -32,13 +33,24 @@ export interface EventFeedback extends HtBaseEventProps {
| EventAction.FeedbackConversation
| EventAction.FeedbackMessage
| EventAction.FeedbackWebview
- messageGeneratedBy?: string
- feedbackTargetId?: string
- feedbackGroupId?: string
+ feedbackTargetId: string
+ feedbackGroupId: string
possibleOptions: string[]
- possibleValues: number[]
+ possibleValues?: number[]
option: string
- value: number
+ value?: number
+ comment?: string
+}
+
+export interface EventFeedbackKnowledgebase extends HtBaseEventProps {
+ action: EventAction.FeedbackKnowledgebase
+ knowledgebaseInferenceId: string
+ feedbackTargetId: string
+ feedbackGroupId: string
+ possibleOptions: string[]
+ possibleValues?: number[]
+ option: string
+ value?: number
comment?: string
}
@@ -135,6 +147,7 @@ export interface EventCustom extends HtBaseEventProps {
export type HtEventProps =
| EventFeedback
+ | EventFeedbackKnowledgebase
| EventFlow
| EventHandoff
| EventHandoffOption
diff --git a/packages/botonic-plugin-hubtype-analytics/src/utils.ts b/packages/botonic-plugin-hubtype-analytics/src/utils.ts
index 74c45185a3..74be62543c 100644
--- a/packages/botonic-plugin-hubtype-analytics/src/utils.ts
+++ b/packages/botonic-plugin-hubtype-analytics/src/utils.ts
@@ -3,6 +3,7 @@ import {
HtEventCustom,
HtEventFallback,
HtEventFeedback,
+ HtEventFeedbackKnowledgebase,
HtEventFlow,
HtEventHandoff,
HtEventHandoffOption,
@@ -25,6 +26,9 @@ export function createHtEvent(
case EventAction.FeedbackWebview:
return new HtEventFeedback(htEventProps, requestData)
+ case EventAction.FeedbackKnowledgebase:
+ return new HtEventFeedbackKnowledgebase(htEventProps, requestData)
+
case EventAction.FlowNode:
return new HtEventFlow(htEventProps, requestData)
diff --git a/packages/botonic-plugin-hubtype-analytics/tests/event-feedback-knowledgebase.test.ts b/packages/botonic-plugin-hubtype-analytics/tests/event-feedback-knowledgebase.test.ts
new file mode 100644
index 0000000000..d9bcdc1314
--- /dev/null
+++ b/packages/botonic-plugin-hubtype-analytics/tests/event-feedback-knowledgebase.test.ts
@@ -0,0 +1,34 @@
+import { createHtEvent, EventAction, EventType } from '../src'
+import { getRequestData } from './helpers'
+
+describe('Create feedback knowledgebase event', () => {
+ test('A message generated for a knowledge base recive feedback', () => {
+ const requestData = getRequestData()
+ const htEvent = createHtEvent(requestData, {
+ action: EventAction.FeedbackKnowledgebase,
+ feedbackTargetId: 'messageIdTest',
+ feedbackGroupId: 'groupIdTest',
+ knowledgebaseInferenceId: 'knowledgebaseInferenceIdTest',
+ possibleOptions: ['thumbs_down', 'thumbs_up'],
+ possibleValues: [0, 1],
+ option: 'thumbs_down',
+ value: 0,
+ })
+
+ expect(htEvent).toEqual({
+ chat_id: 'chatIdTest',
+ chat_language: 'es',
+ chat_country: 'ES',
+ format_version: 2,
+ action: EventAction.FeedbackKnowledgebase,
+ feedback_target_id: 'messageIdTest',
+ feedback_group_id: 'groupIdTest',
+ knowledgebase_inference_id: 'knowledgebaseInferenceIdTest',
+ possible_options: ['thumbs_down', 'thumbs_up'],
+ possible_values: [0, 1],
+ option: 'thumbs_down',
+ value: 0,
+ type: EventType.WebEvent,
+ })
+ })
+})
diff --git a/packages/botonic-plugin-hubtype-analytics/tests/event-feedback.test.ts b/packages/botonic-plugin-hubtype-analytics/tests/event-feedback.test.ts
index 2d0526e381..a71f55ee7b 100644
--- a/packages/botonic-plugin-hubtype-analytics/tests/event-feedback.test.ts
+++ b/packages/botonic-plugin-hubtype-analytics/tests/event-feedback.test.ts
@@ -5,7 +5,9 @@ describe('Create feedback event', () => {
test('A conversation feedback event is created', () => {
const requestData = getRequestData()
const htEvent = createHtEvent(requestData, {
- action: EventAction.FeedbackMessage,
+ action: EventAction.FeedbackCase,
+ feedbackTargetId: 'caseId',
+ feedbackGroupId: 'groupIdTest',
possibleOptions: ['*', '**', '***', '****', '*****'],
possibleValues: [1, 2, 3, 4, 5],
option: '**',
@@ -17,7 +19,9 @@ describe('Create feedback event', () => {
chat_language: 'es',
chat_country: 'ES',
format_version: 2,
- action: EventAction.FeedbackMessage,
+ action: EventAction.FeedbackCase,
+ feedback_target_id: 'caseId',
+ feedback_group_id: 'groupIdTest',
possible_options: ['*', '**', '***', '****', '*****'],
possible_values: [1, 2, 3, 4, 5],
option: '**',
@@ -30,6 +34,8 @@ describe('Create feedback event', () => {
const requestData = getRequestData()
const htEvent = createHtEvent(requestData, {
action: EventAction.FeedbackConversation,
+ feedbackTargetId: 'chatIdTest',
+ feedbackGroupId: 'groupIdTest',
possibleOptions: ['*', '**', '***', '****', '*****'],
possibleValues: [1, 2, 3, 4, 5],
option: '**',
@@ -43,6 +49,8 @@ describe('Create feedback event', () => {
chat_country: 'ES',
format_version: 2,
action: EventAction.FeedbackConversation,
+ feedback_target_id: 'chatIdTest',
+ feedback_group_id: 'groupIdTest',
possible_options: ['*', '**', '***', '****', '*****'],
possible_values: [1, 2, 3, 4, 5],
option: '**',
diff --git a/packages/botonic-react/src/assets/thumbs-down.svg b/packages/botonic-react/src/assets/thumbs-down.svg
new file mode 100644
index 0000000000..2d967cb3b8
--- /dev/null
+++ b/packages/botonic-react/src/assets/thumbs-down.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/botonic-react/src/assets/thumbs-up.svg b/packages/botonic-react/src/assets/thumbs-up.svg
new file mode 100644
index 0000000000..4885323b86
--- /dev/null
+++ b/packages/botonic-react/src/assets/thumbs-up.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/botonic-react/src/components/index-types.ts b/packages/botonic-react/src/components/index-types.ts
index e70fc4c50c..44ddd963b9 100644
--- a/packages/botonic-react/src/components/index-types.ts
+++ b/packages/botonic-react/src/components/index-types.ts
@@ -1,4 +1,4 @@
-import React, { ErrorInfo } from 'react'
+import React from 'react'
import { SENDERS } from '../index-types'
import { CoverComponentProps } from '../webchat/index-types'
@@ -29,6 +29,8 @@ export interface MessageProps {
export interface TextProps extends MessageProps {
// converts markdown syntax to HTML
markdown?: boolean
+ feedbackEnabled?: boolean
+ inferenceId?: string
}
export interface Webview {
@@ -204,21 +206,3 @@ export interface WebchatSettingsProps {
export type WrappedComponent = React.FunctionComponent & {
customTypeName: string
}
-
-// TODO: Reuse types to be typed in respective functions
-// export class ErrorBoundary extends React.Component {
-// componentDidCatch(error: Error, errorInfo: ErrorInfo): void
-// }
-
-// export function createErrorBoundary(_?: {
-// errorComponent: React.ComponentType
-// }): ErrorBoundary
-
-// export function customMessage(_: {
-// name: string
-// component: React.ComponentType
-// defaultProps?: Record
-// errorBoundary?: ErrorBoundary
-// }): WrappedComponent
-
-// export function getDisplayName(component: React.ComponentType): string
diff --git a/packages/botonic-react/src/components/message/index.jsx b/packages/botonic-react/src/components/message/index.jsx
index 9017c740ae..7f662e7f0c 100644
--- a/packages/botonic-react/src/components/message/index.jsx
+++ b/packages/botonic-react/src/components/message/index.jsx
@@ -12,6 +12,7 @@ import { Button } from '../button'
import { ButtonsDisabler } from '../buttons-disabler'
import { getMarkdownStyle, renderLinks, renderMarkdown } from '../markdown'
import { Reply } from '../reply'
+import { MessageFooter } from './message-footer'
import { MessageImage } from './message-image'
import {
BlobContainer,
@@ -20,7 +21,7 @@ import {
BlobTickContainer,
MessageContainer,
} from './styles'
-import { MessageTimestamp, resolveMessageTimestamps } from './timestamps'
+import { resolveMessageTimestamps } from './timestamps'
export const Message = props => {
const { defaultTyping, defaultDelay } = useContext(RequestContext)
@@ -36,6 +37,8 @@ export const Message = props => {
style,
imagestyle = props.imagestyle || props.imageStyle,
isUnread = true,
+ feedbackEnabled,
+ inferenceId,
...otherProps
} = props
@@ -67,8 +70,10 @@ export const Message = props => {
typeof e === 'string' ? renderLinks(e) : e
)
- const { timestampsEnabled, getFormattedTimestamp, timestampStyle } =
- resolveMessageTimestamps(getThemeProperty, enabletimestamps)
+ const { timestampsEnabled, getFormattedTimestamp } = resolveMessageTimestamps(
+ getThemeProperty,
+ enabletimestamps
+ )
const getEnvAck = () => {
if (isDev) return 1
@@ -111,6 +116,8 @@ export const Message = props => {
customTypeName: decomposedChildren.customTypeName,
ack: ack,
isUnread: isUnread === 1 || isUnread === true,
+ feedbackEnabled,
+ inferenceId,
}
addMessage(message)
}
@@ -255,13 +262,15 @@ export const Message = props => {
{Boolean(blob) && hasBlobTick() && getBlobTick(5)}
- {timestampsEnabled && (
-
- )}
+ ) : null}
>
)
diff --git a/packages/botonic-react/src/components/message/message-feedback.tsx b/packages/botonic-react/src/components/message/message-feedback.tsx
new file mode 100644
index 0000000000..0c4713fb7d
--- /dev/null
+++ b/packages/botonic-react/src/components/message/message-feedback.tsx
@@ -0,0 +1,99 @@
+import React, { useContext, useEffect, useState } from 'react'
+import { v4 as uuid } from 'uuid'
+
+import ThumbsDown from '../../assets/thumbs-down.svg'
+import ThumbsUp from '../../assets/thumbs-up.svg'
+import { RequestContext, WebchatContext } from '../../contexts'
+import { ActionRequest } from '../../index-types'
+import { resolveImage } from '../../util'
+import { EventAction, FeedbackOption } from '../../webchat/tracking'
+import { FeedbackButton, FeedbackMessageContainer } from './styles'
+
+interface ButtonsState {
+ positive: boolean
+ negative: boolean
+}
+
+interface RatingProps {
+ inferenceId?: string
+ messageId: string
+}
+
+export const MessageFeedback = ({ inferenceId, messageId }: RatingProps) => {
+ const { webchatState, updateMessage, trackEvent } = useContext(WebchatContext)
+ const request = useContext(RequestContext)
+
+ const [className, setClassName] = useState('')
+ const [disabled, setDisabled] = useState({
+ positive: false,
+ negative: false,
+ })
+
+ const updateMsgWithFeedback = (feedbackEnabled: boolean) => {
+ const message = webchatState.messagesJSON.find(
+ message => message.id === messageId
+ )
+ const updatedMsg = {
+ ...message,
+ feedbackEnabled,
+ }
+ updateMessage(updatedMsg)
+ }
+
+ useEffect(() => {
+ updateMsgWithFeedback(true)
+ }, [])
+
+ useEffect(() => {
+ if (disabled.positive || disabled.negative) {
+ setClassName('clicked')
+ updateMsgWithFeedback(false)
+ }
+ }, [disabled])
+
+ const handleClick = async (isUseful: boolean) => {
+ if (!trackEvent) {
+ return
+ }
+
+ if (isUseful) {
+ setDisabled({ positive: false, negative: true })
+ } else {
+ setDisabled({ positive: true, negative: false })
+ }
+
+ const args = {
+ knowledgebaseInferenceId: inferenceId,
+ feedbackTargetId: messageId,
+ feedbackGroupId: uuid(),
+ possibleOptions: [FeedbackOption.ThumbsUp, FeedbackOption.ThumbsDown],
+ possibleValues: [0, 1],
+ option: isUseful ? FeedbackOption.ThumbsUp : FeedbackOption.ThumbsDown,
+ value: isUseful ? 1 : 0,
+ }
+ await trackEvent(
+ request as ActionRequest,
+ EventAction.FeedbackKnowledgebase,
+ args
+ )
+ }
+
+ return (
+
+ handleClick(true)}
+ >
+
+
+ handleClick(false)}
+ >
+
+
+
+ )
+}
diff --git a/packages/botonic-react/src/components/message/message-footer.tsx b/packages/botonic-react/src/components/message/message-footer.tsx
new file mode 100644
index 0000000000..3ec50f170c
--- /dev/null
+++ b/packages/botonic-react/src/components/message/message-footer.tsx
@@ -0,0 +1,52 @@
+import React, { useContext } from 'react'
+
+import { WebchatContext } from '../../contexts'
+import { SENDERS } from '../../index-types'
+import { MessageFeedback } from './message-feedback'
+import { MessageFooterContainer } from './styles'
+import { MessageTimestamp, resolveMessageTimestamps } from './timestamps'
+
+interface MessageFooterProps {
+ enabletimestamps: boolean
+ messageJSON: any
+ sentBy: SENDERS
+ feedbackEnabled: boolean
+ inferenceId?: string
+}
+
+export const MessageFooter = ({
+ enabletimestamps,
+ messageJSON,
+ sentBy,
+ feedbackEnabled,
+ inferenceId,
+}: MessageFooterProps) => {
+ const { getThemeProperty } = useContext(WebchatContext)
+
+ const { timestampsEnabled, timestampStyle } = resolveMessageTimestamps(
+ getThemeProperty,
+ enabletimestamps
+ )
+ const isSentByUser = sentBy === SENDERS.user
+ const messageFotterClass = isSentByUser
+ ? 'message-footer-user'
+ : 'message-footer-bot'
+
+ return (
+
+ {timestampsEnabled ? (
+
+ ) : null}
+ {feedbackEnabled ? (
+
+ ) : null}
+
+ )
+}
diff --git a/packages/botonic-react/src/components/message/styles.ts b/packages/botonic-react/src/components/message/styles.ts
index 5b8d26597a..71bf0d88e1 100644
--- a/packages/botonic-react/src/components/message/styles.ts
+++ b/packages/botonic-react/src/components/message/styles.ts
@@ -85,8 +85,6 @@ export const TimestampContainer = styled.div`
box-sizing: border-box;
width: 100%;
- padding: 0px 15px 4px 15px;
- padding-top: ${props => (props.isSentByUser ? '0px' : '4px')};
img {
max-width: 20px;
@@ -103,3 +101,53 @@ export const TimestampText = styled.div`
color: ${COLORS.SOLID_BLACK};
text-align: ${props => (props.isSentByUser ? 'right' : 'left')};
`
+
+export const MessageFooterContainer = styled.div`
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ box-sizing: border-box;
+ padding: 0px 15px 4px 15px;
+ padding-top: ${props => (props.isSentByUser ? '0px' : '4px')};
+ width: 100%;
+`
+
+export const FeedbackMessageContainer = styled.div`
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 4px;
+
+ box-sizing: border-box;
+`
+
+export const FeedbackButton = styled.button`
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ background: none;
+ box-sizing: border-box;
+ border: none;
+ border-radius: 4px;
+ padding: 8px 8px;
+ height: 24px;
+ width: 24px;
+
+ &:hover {
+ cursor: pointer;
+ background-color: #f4f3f4;
+ }
+
+ &:disabled {
+ cursor: default;
+ background: none;
+ opacity: 0.3;
+ }
+
+ &.clicked {
+ opacity: 0;
+ transition: 1s 1s;
+ }
+`
diff --git a/packages/botonic-react/src/components/text.jsx b/packages/botonic-react/src/components/text.tsx
similarity index 85%
rename from packages/botonic-react/src/components/text.jsx
rename to packages/botonic-react/src/components/text.tsx
index 58b0d9d1dc..8cb5947fd8 100644
--- a/packages/botonic-react/src/components/text.jsx
+++ b/packages/botonic-react/src/components/text.tsx
@@ -2,6 +2,7 @@ import { INPUT } from '@botonic/core'
import React, { Children } from 'react'
import { mapObjectNonBooleanValues } from '../util/react'
+import { TextProps } from './index-types'
import { serializeMarkdown, toMarkdownChildren } from './markdown'
import { Message } from './message'
@@ -17,7 +18,7 @@ const serializeText = children => {
return text
}
-const serialize = textProps => {
+const serialize = (textProps: TextProps) => {
if (!textProps.markdown)
return {
text: serializeText(textProps.children),
@@ -25,20 +26,19 @@ const serialize = textProps => {
return { text: serializeMarkdown(textProps.children) }
}
-/**
- *
- * @param {TextProps} props
- * @returns {JSX.Element}
- */
-export const Text = props => {
+export const Text = (props: TextProps) => {
const defaultTextProps = {
markdown: props.markdown === undefined ? true : props.markdown,
+ feedbackEnabled: props.feedbackEnabled,
+ inferenceId: props.inferenceId,
}
+
const textProps = mapObjectNonBooleanValues({
...props,
...defaultTextProps,
...{ children: Children.toArray(props.children) },
})
+
if (!textProps.markdown)
return (
diff --git a/packages/botonic-react/src/contexts.tsx b/packages/botonic-react/src/contexts.tsx
index 04568567bd..0c78d72b40 100644
--- a/packages/botonic-react/src/contexts.tsx
+++ b/packages/botonic-react/src/contexts.tsx
@@ -91,4 +91,7 @@ export const WebchatContext = createContext({
return
},
webchatState: webchatInitialState,
+ trackEvent: async () => {
+ return
+ },
})
diff --git a/packages/botonic-react/src/dev-app.jsx b/packages/botonic-react/src/dev-app.jsx
index 0bcd7f87fb..77980f510a 100644
--- a/packages/botonic-react/src/dev-app.jsx
+++ b/packages/botonic-react/src/dev-app.jsx
@@ -26,6 +26,7 @@ export class DevApp extends WebchatApp {
onOpen,
onClose,
onMessage,
+ onTrackEvent,
...botOptions
}) {
super({
@@ -45,6 +46,7 @@ export class DevApp extends WebchatApp {
onOpen,
onClose,
onMessage,
+ onTrackEvent,
})
this.bot = new ReactBot({
...botOptions,
@@ -67,6 +69,7 @@ export class DevApp extends WebchatApp {
onOpen,
onClose,
onMessage,
+ onTrackEvent,
hostId,
...webchatOptions
} = optionsAtRuntime
@@ -84,6 +87,7 @@ export class DevApp extends WebchatApp {
this.onOpen = onOpen || this.onOpen
this.onClose = onClose || this.onClose
this.onMessage = onMessage || this.onMessage
+ this.onTrackEvent = onTrackEvent || this.onTrackEvent
this.hostId = hostId || this.hostId
this.createRootElement(host)
return (
@@ -108,6 +112,7 @@ export class DevApp extends WebchatApp {
onOpen={(...args) => this.onOpenWebchat(...args)}
onClose={(...args) => this.onCloseWebchat(...args)}
onUserInput={(...args) => this.onUserInput(...args)}
+ onTrackEvent={(...args) => this.onTrackEvent(...args)}
/>
)
}
diff --git a/packages/botonic-react/src/index-types.ts b/packages/botonic-react/src/index-types.ts
index 4ddee29ba9..139ffa3a30 100644
--- a/packages/botonic-react/src/index-types.ts
+++ b/packages/botonic-react/src/index-types.ts
@@ -117,13 +117,20 @@ export interface WebchatArgs {
onMessage?: (app: WebchatApp, message: WebchatMessage) => void
onOpen?: (app: WebchatApp, args: any) => void
onConnectionChange?: (app: WebchatApp, isOnline: boolean) => void
+ onTrackEvent?: TrackEventFunction
persistentMenu?: PersistentMenuTheme
storage?: Storage | null
storageKey?: any
theme?: ThemeProps
}
-// export interface WebchatAppArgs extends WebchatArgs {
+type EventArgs = { [key: string]: any }
+type TrackEventFunction = (
+ request: ActionRequest,
+ eventName: string,
+ args?: EventArgs
+) => Promise
+
export interface WebchatAppArgs {
appId?: string
visibility?: () => boolean
@@ -201,6 +208,7 @@ export interface WebchatContextProps {
updateUser: (user: Partial) => void
updateWebchatDevSettings: (settings: WebchatSettingsProps) => void
webchatState: WebchatState
+ trackEvent: TrackEventFunction
}
// export class DevApp extends WebchatApp {
diff --git a/packages/botonic-react/src/webchat-app.jsx b/packages/botonic-react/src/webchat-app.jsx
index b524501a98..5afe510c49 100644
--- a/packages/botonic-react/src/webchat-app.jsx
+++ b/packages/botonic-react/src/webchat-app.jsx
@@ -29,6 +29,7 @@ export class WebchatApp {
onOpen,
onClose,
onMessage,
+ onTrackEvent,
onConnectionChange,
appId,
visibility,
@@ -58,6 +59,7 @@ export class WebchatApp {
this.onOpen = onOpen
this.onClose = onClose
this.onMessage = onMessage
+ this.onTrackEvent = onTrackEvent
this.onConnectionChange = onConnectionChange
this.visibility = visibility
this.server = server
@@ -284,6 +286,7 @@ export class WebchatApp {
onClose,
onMessage,
onConnectionChange,
+ onTrackEvent,
appId,
visibility,
server,
@@ -307,6 +310,7 @@ export class WebchatApp {
this.onOpen = onOpen || this.onOpen
this.onClose = onClose || this.onClose
this.onMessage = onMessage || this.onMessage
+ this.onTrackEvent = onTrackEvent || this.onTrackEvent
this.onConnectionChange = onConnectionChange || this.onConnectionChange
this.visibility = visibility || this.visibility
this.appId = appId || this.appId
@@ -335,6 +339,7 @@ export class WebchatApp {
onClose={(...args) => this.onCloseWebchat(...args)}
onUserInput={(...args) => this.onUserInput(...args)}
onStateChange={webchatState => this.onStateChange(webchatState)}
+ onTrackEvent={(...args) => this.onTrackEvent(...args)}
server={server}
/>
)
diff --git a/packages/botonic-react/src/webchat/tracking.ts b/packages/botonic-react/src/webchat/tracking.ts
new file mode 100644
index 0000000000..c30603d403
--- /dev/null
+++ b/packages/botonic-react/src/webchat/tracking.ts
@@ -0,0 +1,8 @@
+export enum EventAction {
+ FeedbackKnowledgebase = 'feedback_knowledgebase',
+}
+
+export enum FeedbackOption {
+ ThumbsUp = 'thumbsUp',
+ ThumbsDown = 'thumbsDown',
+}
diff --git a/packages/botonic-react/src/webchat/webchat.jsx b/packages/botonic-react/src/webchat/webchat.jsx
index 8a414de81b..12de1c8f05 100644
--- a/packages/botonic-react/src/webchat/webchat.jsx
+++ b/packages/botonic-react/src/webchat/webchat.jsx
@@ -880,6 +880,7 @@ export const Webchat = forwardRef((props, ref) => {
updateUser: updateSessionWithUser,
updateWebchatDevSettings: updateWebchatDevSettings,
webchatState,
+ trackEvent: props.onTrackEvent,
}}
>
{!webchatState.isWebchatOpen && }