@botonic/react 1.0.0-dev.1 → 1.0.0-dev.2
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/components/button.js +2 -0
- package/lib/components/button.js.map +1 -1
- package/lib/components/components.js +1 -1
- package/lib/components/image.js +47 -5
- package/lib/components/image.js.map +1 -1
- package/lib/components/index.js +6 -6
- package/lib/components/markdown.js +1 -1
- package/lib/components/multichannel/multichannel-utils.js +8 -6
- package/lib/components/multichannel/multichannel-utils.js.map +1 -1
- package/lib/components/timestamps.js +1 -1
- package/lib/constants.js +2 -1
- package/lib/constants.js.map +1 -1
- package/lib/dev-app.js +7 -6
- package/lib/dev-app.js.map +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.js +20 -20
- package/lib/message-utils.js +1 -1
- package/lib/util/dom.js +8 -2
- package/lib/util/dom.js.map +1 -1
- package/lib/util/environment.js +1 -1
- package/lib/util/objects.js +1 -1
- package/lib/util/react.js +1 -1
- package/lib/util/webchat.js +1 -1
- package/lib/webchat/actions.js +3 -1
- package/lib/webchat/actions.js.map +1 -1
- package/lib/webchat/devices/device-adapter.js +14 -4
- package/lib/webchat/devices/device-adapter.js.map +1 -1
- package/lib/webchat/devices/scrollbar-controller.js +5 -3
- package/lib/webchat/devices/scrollbar-controller.js.map +1 -1
- package/lib/webchat/header.js +1 -1
- package/lib/webchat/hooks.js +14 -4
- package/lib/webchat/hooks.js.map +1 -1
- package/lib/webchat/index.js +1 -1
- package/lib/webchat/webchat-reducer.js +6 -0
- package/lib/webchat/webchat-reducer.js.map +1 -1
- package/lib/webchat/webchat.js +21 -4
- package/lib/webchat/webchat.js.map +1 -1
- package/lib/webchat/webview.js +1 -1
- package/lib/webchat-app.js +20 -9
- package/lib/webchat-app.js.map +1 -1
- package/package.json +6 -6
- package/src/components/button.jsx +2 -0
- package/src/dev-app.jsx +8 -3
- package/src/experimental/components/custom-message.jsx +2 -1
- package/src/experimental/components/message.jsx +14 -7
- package/src/experimental/constants.js +189 -0
- package/src/experimental/contexts.jsx +36 -0
- package/src/experimental/dev-app.jsx +14 -7
- package/src/experimental/index.js +32 -20
- package/src/experimental/msg-to-botonic.jsx +9 -9
- package/src/experimental/react-bot.jsx +1 -1
- package/src/experimental/util/dom.js +55 -0
- package/src/experimental/util/objects.js +39 -0
- package/src/experimental/util/webchat.js +61 -0
- package/src/experimental/webchat/actions.jsx +24 -0
- package/src/experimental/webchat/hooks.js +296 -0
- package/src/experimental/webchat/messages-reducer.js +86 -0
- package/src/experimental/webchat/session-view.jsx +166 -0
- package/src/experimental/webchat/webchat-dev.jsx +23 -19
- package/src/experimental/webchat/webchat-reducer.js +68 -0
- package/src/experimental/webchat/webchat.jsx +107 -75
- package/src/experimental/webchat-app.jsx +34 -15
- package/src/index.d.ts +1 -0
- package/src/util/dom.js +5 -3
- package/src/webchat/devices/device-adapter.js +16 -4
- package/src/webchat/devices/scrollbar-controller.js +9 -4
- package/src/webchat/webchat.jsx +2 -1
- package/src/webchat-app.jsx +6 -4
- package/lib/experimental/components/audio.js +0 -46
- package/lib/experimental/components/audio.js.map +0 -1
- package/lib/experimental/components/carousel.js +0 -194
- package/lib/experimental/components/carousel.js.map +0 -1
- package/lib/experimental/components/custom-message.js +0 -132
- package/lib/experimental/components/custom-message.js.map +0 -1
- package/lib/experimental/components/document.js +0 -69
- package/lib/experimental/components/document.js.map +0 -1
- package/lib/experimental/components/image.js +0 -47
- package/lib/experimental/components/image.js.map +0 -1
- package/lib/experimental/components/index.js +0 -184
- package/lib/experimental/components/index.js.map +0 -1
- package/lib/experimental/components/location.js +0 -54
- package/lib/experimental/components/location.js.map +0 -1
- package/lib/experimental/components/markdown.js +0 -103
- package/lib/experimental/components/markdown.js.map +0 -1
- package/lib/experimental/components/message.js +0 -353
- package/lib/experimental/components/message.js.map +0 -1
- package/lib/experimental/components/text.js +0 -80
- package/lib/experimental/components/text.js.map +0 -1
- package/lib/experimental/components/video.js +0 -49
- package/lib/experimental/components/video.js.map +0 -1
- package/lib/experimental/components/whatsapp-template.js +0 -53
- package/lib/experimental/components/whatsapp-template.js.map +0 -1
- package/lib/experimental/dev-app.js +0 -240
- package/lib/experimental/dev-app.js.map +0 -1
- package/lib/experimental/index.js +0 -1022
- package/lib/experimental/index.js.map +0 -1
- package/lib/experimental/msg-to-botonic.js +0 -162
- package/lib/experimental/msg-to-botonic.js.map +0 -1
- package/lib/experimental/node-app.js +0 -97
- package/lib/experimental/node-app.js.map +0 -1
- package/lib/experimental/react-bot.js +0 -167
- package/lib/experimental/react-bot.js.map +0 -1
- package/lib/experimental/webchat/assets/Inter-VariableFont_slnt,wght.ttf +0 -0
- package/lib/experimental/webchat/assets/botonic-logo-white.svg +0 -16
- package/lib/experimental/webchat/assets/messenger.svg +0 -10
- package/lib/experimental/webchat/assets/open-new-window.svg +0 -3
- package/lib/experimental/webchat/assets/open.svg +0 -3
- package/lib/experimental/webchat/assets/telegram.svg +0 -10
- package/lib/experimental/webchat/assets/webchat.svg +0 -21
- package/lib/experimental/webchat/assets/whatsapp.svg +0 -4
- package/lib/experimental/webchat/webchat-dev.js +0 -300
- package/lib/experimental/webchat/webchat-dev.js.map +0 -1
- package/lib/experimental/webchat/webchat.js +0 -1051
- package/lib/experimental/webchat/webchat.js.map +0 -1
- package/lib/experimental/webchat-app.js +0 -642
- package/lib/experimental/webchat-app.js.map +0 -1
|
@@ -77,8 +77,9 @@ export const customMessage = ({
|
|
|
77
77
|
WrappedComponent.customTypeName = name
|
|
78
78
|
// eslint-disable-next-line react/display-name
|
|
79
79
|
WrappedComponent.deserialize = msg => {
|
|
80
|
+
const customMessageProps = msg.json
|
|
80
81
|
return (
|
|
81
|
-
<WrappedComponent {...msg}>
|
|
82
|
+
<WrappedComponent {...msg} {...customMessageProps}>
|
|
82
83
|
{msg.replies.length > 0 &&
|
|
83
84
|
msg.replies.map((r, i) => (
|
|
84
85
|
<Reply key={i} payload={r.payload}>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { INPUT, isBrowser } from '@botonic/core'
|
|
2
|
+
import { MessageEventAck } from '@botonic/core/src/models/events/message'
|
|
2
3
|
import React, { useContext, useEffect, useState } from 'react'
|
|
3
4
|
import Fade from 'react-reveal/Fade'
|
|
4
5
|
import styled from 'styled-components'
|
|
@@ -126,14 +127,18 @@ export const Message = props => {
|
|
|
126
127
|
timestampStyle,
|
|
127
128
|
} = resolveMessageTimestamps(getThemeProperty, enabletimestamps)
|
|
128
129
|
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (
|
|
133
|
-
|
|
130
|
+
const resolveAck = ack => {
|
|
131
|
+
// Browser app version
|
|
132
|
+
// eslint-disable-next-line no-undef
|
|
133
|
+
if (typeof FULLSTACK === 'undefined' || !FULLSTACK) {
|
|
134
|
+
return MessageEventAck.RECEIVED
|
|
135
|
+
}
|
|
136
|
+
if (ack !== undefined) return ack
|
|
137
|
+
if (isFromBot) return MessageEventAck.RECEIVED
|
|
138
|
+
return MessageEventAck.DRAFT
|
|
134
139
|
}
|
|
135
140
|
|
|
136
|
-
const ack =
|
|
141
|
+
const ack = resolveAck(props.ack)
|
|
137
142
|
|
|
138
143
|
if (isBrowser()) {
|
|
139
144
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
@@ -171,6 +176,8 @@ export const Message = props => {
|
|
|
171
176
|
display: delay + typing == 0,
|
|
172
177
|
customTypeName: decomposedChildren.customTypeName,
|
|
173
178
|
ack: ack,
|
|
179
|
+
channel: props.channel,
|
|
180
|
+
idFromChannel: props.idFromChannel,
|
|
174
181
|
}
|
|
175
182
|
addMessage(message)
|
|
176
183
|
}, [])
|
|
@@ -305,7 +312,7 @@ export const Message = props => {
|
|
|
305
312
|
style={{
|
|
306
313
|
...getMessageStyle(),
|
|
307
314
|
...style,
|
|
308
|
-
...{ opacity: ack ===
|
|
315
|
+
...{ opacity: ack === MessageEventAck.DRAFT ? 0.6 : 1 },
|
|
309
316
|
}}
|
|
310
317
|
{...otherProps}
|
|
311
318
|
>
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import BotonicLogo from '../assets/botonic_react_logo100x100.png'
|
|
2
|
+
|
|
3
|
+
export const SENDERS = {
|
|
4
|
+
bot: 'bot',
|
|
5
|
+
user: 'user',
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const COLORS = {
|
|
9
|
+
// http://chir.ag/projects/name-that-color
|
|
10
|
+
APPLE_GREEN: 'rgba(58, 156, 53, 1)',
|
|
11
|
+
BLEACHED_CEDAR_PURPLE: 'rgba(46, 32, 59, 1)',
|
|
12
|
+
BOTONIC_BLUE: 'rgba(0, 153, 255, 1)',
|
|
13
|
+
CACTUS_GREEN: 'rgba(96, 115, 94, 1)',
|
|
14
|
+
CONCRETE_WHITE: 'rgba(243, 243, 243, 1)',
|
|
15
|
+
CURIOUS_BLUE: 'rgba(38, 139, 210, 1)',
|
|
16
|
+
DAINTREE_BLUE: 'rgba(0, 43, 53, 1)',
|
|
17
|
+
ERROR_RED: 'rgba(255, 43, 94)',
|
|
18
|
+
FRINGY_FLOWER_GREEN: 'rgba(198, 231, 192, 1)',
|
|
19
|
+
GRAY: 'rgba(129, 129, 129, 1)',
|
|
20
|
+
LIGHT_GRAY: 'rgba(209, 209, 209, 1)',
|
|
21
|
+
MID_GRAY: 'rgba(105, 105, 115, 1)',
|
|
22
|
+
PIGEON_POST_BLUE_ALPHA_0_5: 'rgba(176, 196, 222, 0.5)',
|
|
23
|
+
SCORPION_GRAY: 'rgba(87, 87, 87, 1)',
|
|
24
|
+
SEASHELL_WHITE: 'rgba(241, 240, 240, 1)',
|
|
25
|
+
SILVER: 'rgba(200, 200, 200, 1)',
|
|
26
|
+
SOLID_BLACK_ALPHA_0_2: 'rgba(0, 0, 0, 0.2)',
|
|
27
|
+
SOLID_BLACK_ALPHA_0_5: 'rgba(0, 0, 0, 0.5)',
|
|
28
|
+
SOLID_BLACK: 'rgba(0, 0, 0, 1)',
|
|
29
|
+
SOLID_WHITE_ALPHA_0_2: 'rgba(255, 255, 255, 0.2)',
|
|
30
|
+
SOLID_WHITE_ALPHA_0_8: 'rgba(255, 255, 255, 0.8)',
|
|
31
|
+
SOLID_WHITE: 'rgba(255, 255, 255, 1)',
|
|
32
|
+
TASMAN_GRAY: 'rgba(209, 216, 207, 1)',
|
|
33
|
+
TRANSPARENT: 'rgba(0, 0, 0, 0)',
|
|
34
|
+
WILD_SAND_WHITE: 'rgba(244, 244, 244, 1)',
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const WEBCHAT = {
|
|
38
|
+
DEFAULTS: {
|
|
39
|
+
WIDTH: 300,
|
|
40
|
+
HEIGHT: 450,
|
|
41
|
+
TITLE: 'Botonic',
|
|
42
|
+
LOGO: BotonicLogo,
|
|
43
|
+
PLACEHOLDER: 'Ask me something...',
|
|
44
|
+
FONT_FAMILY: "'Noto Sans JP', sans-serif",
|
|
45
|
+
BORDER_RADIUS_TOP_CORNERS: '6px 6px 0px 0px',
|
|
46
|
+
ELEMENT_WIDTH: 222,
|
|
47
|
+
ELEMENT_MARGIN_RIGHT: 6,
|
|
48
|
+
STORAGE_KEY: 'botonicState',
|
|
49
|
+
HOST_ID: 'root',
|
|
50
|
+
ID: 'botonic-webchat',
|
|
51
|
+
BUTTON_AUTO_DISABLE: false,
|
|
52
|
+
BUTTON_DISABLED_STYLE: {
|
|
53
|
+
opacity: 0.5,
|
|
54
|
+
cursor: 'auto',
|
|
55
|
+
pointerEvents: 'none',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
SELECTORS: {
|
|
59
|
+
SCROLLABLE_CONTENT: '#botonic-scrollable-content',
|
|
60
|
+
SIMPLEBAR_CONTENT: '.simplebar-content',
|
|
61
|
+
SIMPLEBAR_WRAPPER: '.simplebar-content-wrapper',
|
|
62
|
+
},
|
|
63
|
+
CUSTOM_PROPERTIES: {
|
|
64
|
+
// General
|
|
65
|
+
enableAnimations: 'animations.enable',
|
|
66
|
+
markdownStyle: 'markdownStyle',
|
|
67
|
+
scrollbar: 'scrollbar',
|
|
68
|
+
// Mobile
|
|
69
|
+
mobileBreakpoint: 'mobileBreakpoint',
|
|
70
|
+
mobileStyle: 'mobileStyle',
|
|
71
|
+
// Webviews
|
|
72
|
+
webviewHeaderStyle: 'webview.header.style',
|
|
73
|
+
webviewStyle: 'webview.style',
|
|
74
|
+
// Brand
|
|
75
|
+
brandColor: 'brand.color',
|
|
76
|
+
brandImage: 'brand.image',
|
|
77
|
+
// Header
|
|
78
|
+
customHeader: 'header.custom',
|
|
79
|
+
headerImage: 'header.image',
|
|
80
|
+
headerStyle: 'header.style',
|
|
81
|
+
headerSubtitle: 'header.subtitle',
|
|
82
|
+
headerTitle: 'header.title',
|
|
83
|
+
// Bot Message
|
|
84
|
+
botMessageBackground: 'message.bot.style.background',
|
|
85
|
+
botMessageBlobTick: 'message.bot.blobTick',
|
|
86
|
+
botMessageBlobTickStyle: 'message.bot.blobTickStyle',
|
|
87
|
+
botMessageBlobWidth: 'message.bot.blobWidth',
|
|
88
|
+
botMessageBorderColor: 'message.bot.style.borderColor',
|
|
89
|
+
botMessageImage: 'message.bot.image',
|
|
90
|
+
botMessageImageStyle: 'message.bot.imageStyle',
|
|
91
|
+
botMessageStyle: 'message.bot.style',
|
|
92
|
+
// User Message
|
|
93
|
+
customMessageTypes: 'message.customTypes',
|
|
94
|
+
messageStyle: 'message.style',
|
|
95
|
+
userMessageBackground: 'message.user.style.background',
|
|
96
|
+
userMessageBlobTick: 'message.user.blobTick',
|
|
97
|
+
userMessageBlobTickStyle: 'message.user.blobTickStyle',
|
|
98
|
+
userMessageBorderColor: 'message.user.style.borderColor',
|
|
99
|
+
userMessageStyle: 'message.user.style',
|
|
100
|
+
// Timestamps
|
|
101
|
+
enableMessageTimestamps: 'message.timestamps.enable',
|
|
102
|
+
messageTimestampsFormat: 'message.timestamps.format',
|
|
103
|
+
messageTimestampsStyle: 'message.timestamps.style',
|
|
104
|
+
// Intro
|
|
105
|
+
customIntro: 'intro.custom',
|
|
106
|
+
introImage: 'intro.image',
|
|
107
|
+
introStyle: 'intro.style',
|
|
108
|
+
// Buttons
|
|
109
|
+
buttonHoverBackground: 'button.hoverBackground',
|
|
110
|
+
buttonHoverTextColor: 'button.hoverTextColor',
|
|
111
|
+
buttonMessageType: 'button.messageType',
|
|
112
|
+
buttonStyle: 'button.style',
|
|
113
|
+
buttonDisabledStyle: 'button.disabledstyle',
|
|
114
|
+
buttonAutoDisable: 'button.autodisable',
|
|
115
|
+
buttonStyleBackground: 'button.style.background',
|
|
116
|
+
buttonStyleColor: 'button.style.color',
|
|
117
|
+
customButton: 'button.custom',
|
|
118
|
+
// Replies
|
|
119
|
+
alignReplies: 'replies.align',
|
|
120
|
+
customReply: 'reply.custom',
|
|
121
|
+
replyStyle: 'reply.style',
|
|
122
|
+
wrapReplies: 'replies.wrap',
|
|
123
|
+
// TriggerButton
|
|
124
|
+
customTrigger: 'triggerButton.custom',
|
|
125
|
+
triggerButtonImage: 'triggerButton.image',
|
|
126
|
+
triggerButtonStyle: 'triggerButton.style',
|
|
127
|
+
// User Input
|
|
128
|
+
blockInputs: 'userInput.blockInputs',
|
|
129
|
+
documentDownload: 'documentDownload',
|
|
130
|
+
customMenuButton: 'userInput.menuButton.custom',
|
|
131
|
+
customPersistentMenu: 'userInput.menu.custom',
|
|
132
|
+
customSendButton: 'userInput.sendButton.custom',
|
|
133
|
+
darkBackgroundMenu: 'userInput.menu.darkBackground',
|
|
134
|
+
enableAttachments: 'userInput.attachments.enable',
|
|
135
|
+
enableEmojiPicker: 'userInput.emojiPicker.enable',
|
|
136
|
+
enableSendButton: 'userInput.sendButton.enable',
|
|
137
|
+
enableUserInput: 'userInput.enable',
|
|
138
|
+
persistentMenu: 'userInput.persistentMenu',
|
|
139
|
+
textPlaceholder: 'userInput.box.placeholder',
|
|
140
|
+
userInputBoxStyle: 'userInput.box.style',
|
|
141
|
+
userInputStyle: 'userInput.style',
|
|
142
|
+
// Cover Component
|
|
143
|
+
coverComponent: 'coverComponent.component',
|
|
144
|
+
coverComponentProps: 'coverComponent.props',
|
|
145
|
+
// Carousel
|
|
146
|
+
customCarouselLeftArrow: 'carousel.arrow.left',
|
|
147
|
+
customCarouselRightArrow: 'carousel.arrow.right',
|
|
148
|
+
enableCarouselArrows: 'carousel.enableArrows',
|
|
149
|
+
},
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export const MIME_WHITELIST = {
|
|
153
|
+
audio: ['audio/mpeg', 'audio/mp3'],
|
|
154
|
+
document: ['application/pdf'],
|
|
155
|
+
image: ['image/jpeg', 'image/png'],
|
|
156
|
+
video: ['video/mp4', 'video/quicktime'],
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export const MAX_ALLOWED_SIZE_MB = 10
|
|
160
|
+
|
|
161
|
+
export const ROLES = {
|
|
162
|
+
ATTACHMENT_ICON: 'attachment-icon',
|
|
163
|
+
EMOJI_PICKER_ICON: 'emoji-picker-icon',
|
|
164
|
+
EMOJI_PICKER: 'emoji-picker',
|
|
165
|
+
HEADER: 'header',
|
|
166
|
+
MESSAGE_LIST: 'message-list',
|
|
167
|
+
PERSISTENT_MENU_ICON: 'persistent-menu-icon',
|
|
168
|
+
PERSISTENT_MENU: 'persistent-menu',
|
|
169
|
+
SEND_BUTTON_ICON: 'send-button-icon',
|
|
170
|
+
WEBCHAT: 'webchat',
|
|
171
|
+
TRIGGER_BUTTON: 'trigger-button',
|
|
172
|
+
TYPING_INDICATOR: 'typing-indicator',
|
|
173
|
+
TEXT_BOX: 'textbox',
|
|
174
|
+
WEBVIEW: 'webview',
|
|
175
|
+
WEBVIEW_HEADER: 'webview-header',
|
|
176
|
+
MESSAGE: 'message',
|
|
177
|
+
IMAGE_MESSAGE: 'image-message',
|
|
178
|
+
AUDIO_MESSAGE: 'audio-message',
|
|
179
|
+
VIDEO_MESSAGE: 'video-message',
|
|
180
|
+
DOCUMENT_MESSAGE: 'document-message',
|
|
181
|
+
RAW_MESSAGE: 'raw-message',
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export const COMPONENT_TYPE = {
|
|
185
|
+
TEXT: 'Text',
|
|
186
|
+
BUTTON: 'Button',
|
|
187
|
+
REPLY: 'Reply',
|
|
188
|
+
CAROUSEL: 'Carousel',
|
|
189
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import { webchatInitialState } from './webchat/hooks'
|
|
4
|
+
|
|
5
|
+
export const RequestContext = React.createContext({
|
|
6
|
+
getString: () => '',
|
|
7
|
+
setLocale: () => '',
|
|
8
|
+
session: {},
|
|
9
|
+
params: {},
|
|
10
|
+
input: {},
|
|
11
|
+
defaultDelay: 0,
|
|
12
|
+
defaultTyping: 0,
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
export const WebchatContext = React.createContext({
|
|
16
|
+
sendText: text => {},
|
|
17
|
+
sendAttachment: attachment => {},
|
|
18
|
+
sendPayload: payload => {},
|
|
19
|
+
sendInput: input => {},
|
|
20
|
+
setReplies: replies => {},
|
|
21
|
+
openWebview: webviewComponent => {},
|
|
22
|
+
addMessage: message => {},
|
|
23
|
+
updateMessage: message => {},
|
|
24
|
+
updateReplies: replies => {},
|
|
25
|
+
updateLatestInput: input => {},
|
|
26
|
+
closeWebview: () => {},
|
|
27
|
+
toggleWebchat: () => {},
|
|
28
|
+
getThemeProperty: property => undefined, // used to retrieve a specific property of the theme defined by the developer in his 'webchat/index.js'
|
|
29
|
+
resolveCase: () => {},
|
|
30
|
+
theme: {},
|
|
31
|
+
webchatState: webchatInitialState,
|
|
32
|
+
updateWebchatDevSettings: settings => {
|
|
33
|
+
return {}
|
|
34
|
+
},
|
|
35
|
+
updateUser: user => {},
|
|
36
|
+
})
|
|
@@ -2,9 +2,9 @@ import merge from 'lodash.merge'
|
|
|
2
2
|
import React from 'react'
|
|
3
3
|
import { render } from 'react-dom'
|
|
4
4
|
|
|
5
|
-
import { SENDERS } from '
|
|
6
|
-
import { onDOMLoaded } from '../util/dom'
|
|
5
|
+
import { SENDERS } from './constants'
|
|
7
6
|
import { ReactBot } from './react-bot'
|
|
7
|
+
import { onDOMLoaded } from './util/dom'
|
|
8
8
|
import { WebchatDev } from './webchat/webchat-dev'
|
|
9
9
|
import { WebchatApp } from './webchat-app'
|
|
10
10
|
|
|
@@ -51,7 +51,7 @@ export class DevApp extends WebchatApp {
|
|
|
51
51
|
})
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
getComponent(optionsAtRuntime = {}) {
|
|
54
|
+
getComponent(host, optionsAtRuntime = {}) {
|
|
55
55
|
let {
|
|
56
56
|
theme = {},
|
|
57
57
|
persistentMenu,
|
|
@@ -67,6 +67,7 @@ export class DevApp extends WebchatApp {
|
|
|
67
67
|
onOpen,
|
|
68
68
|
onClose,
|
|
69
69
|
onMessage,
|
|
70
|
+
hostId,
|
|
70
71
|
...webchatOptions
|
|
71
72
|
} = optionsAtRuntime
|
|
72
73
|
theme = merge(this.theme, theme)
|
|
@@ -83,6 +84,8 @@ export class DevApp extends WebchatApp {
|
|
|
83
84
|
this.onOpen = onOpen || this.onOpen
|
|
84
85
|
this.onClose = onClose || this.onClose
|
|
85
86
|
this.onMessage = onMessage || this.onMessage
|
|
87
|
+
this.hostId = hostId || this.hostId
|
|
88
|
+
this.createRootElement(host)
|
|
86
89
|
return (
|
|
87
90
|
<WebchatDev
|
|
88
91
|
{...webchatOptions}
|
|
@@ -99,8 +102,10 @@ export class DevApp extends WebchatApp {
|
|
|
99
102
|
enableAnimations={enableAnimations}
|
|
100
103
|
storage={storage}
|
|
101
104
|
storageKey={storageKey}
|
|
102
|
-
getString={(stringId,
|
|
103
|
-
|
|
105
|
+
getString={(stringId, botState) =>
|
|
106
|
+
this.bot.getString(stringId, botState)
|
|
107
|
+
}
|
|
108
|
+
setLocale={(locale, botState) => this.bot.setLocale(locale, botState)}
|
|
104
109
|
onInit={(...args) => this.onInitWebchat(...args)}
|
|
105
110
|
onOpen={(...args) => this.onOpenWebchat(...args)}
|
|
106
111
|
onClose={(...args) => this.onCloseWebchat(...args)}
|
|
@@ -111,8 +116,10 @@ export class DevApp extends WebchatApp {
|
|
|
111
116
|
|
|
112
117
|
render(dest, optionsAtRuntime = {}) {
|
|
113
118
|
onDOMLoaded(() => {
|
|
114
|
-
|
|
115
|
-
|
|
119
|
+
render(
|
|
120
|
+
this.getComponent(dest, optionsAtRuntime),
|
|
121
|
+
this.getReactMountNode(dest)
|
|
122
|
+
)
|
|
116
123
|
})
|
|
117
124
|
}
|
|
118
125
|
|
|
@@ -38,23 +38,29 @@ class WebsocketBackendService {
|
|
|
38
38
|
// On Event Received...
|
|
39
39
|
this.wsClient.addEventListener('message', event => {
|
|
40
40
|
console.log(event, this.onEvent)
|
|
41
|
-
const
|
|
41
|
+
const eventData = JSON.parse(decode(event.data))
|
|
42
42
|
if (this.onEvent && typeof this.onEvent === 'function')
|
|
43
|
-
this.onEvent(
|
|
43
|
+
this.onEvent(eventData)
|
|
44
44
|
})
|
|
45
45
|
}
|
|
46
46
|
async doAuthAndUpdateJwt() {
|
|
47
|
-
this.jwt = await this.doAuth({
|
|
47
|
+
this.jwt = await this.doAuth({
|
|
48
|
+
userId: this.user.id,
|
|
49
|
+
channel: this.user.channel,
|
|
50
|
+
idFromChannel: this.user.idFromChannel,
|
|
51
|
+
})
|
|
48
52
|
this.updateJwt(this.jwt)
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
async doAuth({ userId }) {
|
|
55
|
+
async doAuth({ userId, channel, idFromChannel }) {
|
|
52
56
|
try {
|
|
53
57
|
const {
|
|
54
58
|
data: { token },
|
|
55
59
|
// eslint-disable-next-line no-undef
|
|
56
60
|
} = await axios.post(`${REST_API_URL}auth/`, {
|
|
57
61
|
userId,
|
|
62
|
+
channel,
|
|
63
|
+
idFromChannel,
|
|
58
64
|
})
|
|
59
65
|
return token
|
|
60
66
|
} catch (e) {
|
|
@@ -72,7 +78,7 @@ class WebsocketBackendService {
|
|
|
72
78
|
`${REST_API_URL}events/`,
|
|
73
79
|
{
|
|
74
80
|
message,
|
|
75
|
-
sender: user,
|
|
81
|
+
sender: user, // TODO: Really needed or we should pass user information through JWT?
|
|
76
82
|
},
|
|
77
83
|
{ headers: { Authorization: 'Bearer ' + this.jwt } } // Note: Do not use string template as it will convert the token with commas, which will be invalid
|
|
78
84
|
)
|
|
@@ -85,22 +91,22 @@ class WebsocketBackendService {
|
|
|
85
91
|
if (hasErrors) {
|
|
86
92
|
// TODO: Handle rest of errors
|
|
87
93
|
await this.doAuthAndUpdateJwt()
|
|
88
|
-
await this.postMessage(user, message)
|
|
94
|
+
// await this.postMessage(user, message) // Temporary, avoid infinite events loop
|
|
89
95
|
}
|
|
90
96
|
}
|
|
91
97
|
}
|
|
92
98
|
|
|
93
99
|
export class FullstackProdApp extends WebchatApp {
|
|
94
|
-
async onUserInput({ user, input }) {
|
|
95
|
-
this.onMessage && this.onMessage(this, { from:
|
|
100
|
+
async onUserInput({ user, input, session, botState }) {
|
|
101
|
+
this.onMessage && this.onMessage(this, { from: input.from, message: input })
|
|
96
102
|
this.backendService.postMessage(user, input)
|
|
97
103
|
}
|
|
98
104
|
|
|
99
|
-
async doAuth(
|
|
100
|
-
return await this.backendService.doAuth(
|
|
105
|
+
async doAuth(user) {
|
|
106
|
+
return await this.backendService.doAuth(user)
|
|
101
107
|
}
|
|
102
108
|
|
|
103
|
-
onStateChange({
|
|
109
|
+
onStateChange({ user, messagesJSON, jwt, updateJwt }) {
|
|
104
110
|
if (!this.backendService && user) {
|
|
105
111
|
const lastMessage = messagesJSON[messagesJSON.length - 1]
|
|
106
112
|
this.backendService = new WebsocketBackendService({
|
|
@@ -121,12 +127,12 @@ export class FullstackDevApp extends DevApp {
|
|
|
121
127
|
console.log('FullstackDevApp ', args.playgroundCode)
|
|
122
128
|
}
|
|
123
129
|
|
|
124
|
-
async onUserInput({ user, input }) {
|
|
125
|
-
this.onMessage && this.onMessage(this, { from:
|
|
130
|
+
async onUserInput({ user, input, session, botState }) {
|
|
131
|
+
this.onMessage && this.onMessage(this, { from: input.from, message: input })
|
|
126
132
|
this.backendService && this.backendService.postMessage(user, input)
|
|
127
133
|
}
|
|
128
134
|
|
|
129
|
-
getComponent(optionsAtRuntime = {}) {
|
|
135
|
+
getComponent(host, optionsAtRuntime = {}) {
|
|
130
136
|
let {
|
|
131
137
|
theme = {},
|
|
132
138
|
persistentMenu,
|
|
@@ -142,6 +148,7 @@ export class FullstackDevApp extends DevApp {
|
|
|
142
148
|
onOpen,
|
|
143
149
|
onClose,
|
|
144
150
|
onMessage,
|
|
151
|
+
hostId,
|
|
145
152
|
...webchatOptions
|
|
146
153
|
} = optionsAtRuntime
|
|
147
154
|
theme = merge(this.theme, theme)
|
|
@@ -158,6 +165,8 @@ export class FullstackDevApp extends DevApp {
|
|
|
158
165
|
this.onOpen = onOpen || this.onOpen
|
|
159
166
|
this.onClose = onClose || this.onClose
|
|
160
167
|
this.onMessage = onMessage || this.onMessage
|
|
168
|
+
this.hostId = hostId || this.hostId
|
|
169
|
+
this.createRootElement(host)
|
|
161
170
|
return (
|
|
162
171
|
<WebchatDev
|
|
163
172
|
{...webchatOptions}
|
|
@@ -176,8 +185,10 @@ export class FullstackDevApp extends DevApp {
|
|
|
176
185
|
storageKey={storageKey}
|
|
177
186
|
playgroundCode={this.playgroundCode}
|
|
178
187
|
onStateChange={webchatState => this.onStateChange(webchatState)}
|
|
179
|
-
getString={(stringId,
|
|
180
|
-
|
|
188
|
+
getString={(stringId, botState) =>
|
|
189
|
+
this.bot.getString(stringId, botState)
|
|
190
|
+
}
|
|
191
|
+
setLocale={(locale, botState) => this.bot.setLocale(locale, botState)}
|
|
181
192
|
onInit={(...args) => this.onInitWebchat(...args)}
|
|
182
193
|
onOpen={(...args) => this.onOpenWebchat(...args)}
|
|
183
194
|
onClose={(...args) => this.onCloseWebchat(...args)}
|
|
@@ -187,11 +198,11 @@ export class FullstackDevApp extends DevApp {
|
|
|
187
198
|
)
|
|
188
199
|
}
|
|
189
200
|
|
|
190
|
-
async doAuth(
|
|
191
|
-
return await this.backendService.doAuth(
|
|
201
|
+
async doAuth(user) {
|
|
202
|
+
return await this.backendService.doAuth(user)
|
|
192
203
|
}
|
|
193
204
|
|
|
194
|
-
onStateChange({
|
|
205
|
+
onStateChange({ user, messagesJSON, jwt, updateJwt }) {
|
|
195
206
|
if (!this.backendService && user) {
|
|
196
207
|
const lastMessage = messagesJSON[messagesJSON.length - 1]
|
|
197
208
|
this.backendService = new WebsocketBackendService({
|
|
@@ -257,6 +268,7 @@ export class BrowserProdApp extends WebchatApp {
|
|
|
257
268
|
...botOptions,
|
|
258
269
|
})
|
|
259
270
|
}
|
|
271
|
+
// TODO: Review how this be done for only browser versions
|
|
260
272
|
async onUserInput({ input, session, lastRoutePath }) {
|
|
261
273
|
this.onMessage && this.onMessage(this, { from: 'user', message: input })
|
|
262
274
|
const resp = await this.bot.input({ input, session, lastRoutePath })
|
|
@@ -277,10 +289,10 @@ export { ShareButton } from '../components/share-button'
|
|
|
277
289
|
export { Subtitle } from '../components/subtitle'
|
|
278
290
|
export { Title } from '../components/title'
|
|
279
291
|
export { WebchatSettings } from '../components/webchat-settings'
|
|
280
|
-
export { RequestContext, WebchatContext } from '../contexts'
|
|
281
292
|
export { staticAsset } from '../util/environment'
|
|
282
293
|
export { getBotonicApp } from '../webchat'
|
|
283
294
|
export { WebviewApp } from '../webview'
|
|
295
|
+
export { RequestContext, WebchatContext } from './contexts'
|
|
284
296
|
// Experimental
|
|
285
297
|
export { Audio } from './components/audio'
|
|
286
298
|
export { Carousel } from './components/carousel'
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
|
|
3
|
+
import { Button } from '../components/button'
|
|
4
|
+
import { ButtonsDisabler } from '../components/buttons-disabler'
|
|
5
|
+
import { Element } from '../components/element'
|
|
6
|
+
import { Pic } from '../components/pic'
|
|
7
|
+
import { Reply } from '../components/reply'
|
|
8
|
+
import { Subtitle } from '../components/subtitle'
|
|
9
|
+
import { Title } from '../components/title'
|
|
3
10
|
import {
|
|
4
11
|
isAudio,
|
|
5
12
|
isCarousel,
|
|
@@ -9,14 +16,7 @@ import {
|
|
|
9
16
|
isLocation,
|
|
10
17
|
isText,
|
|
11
18
|
isVideo,
|
|
12
|
-
} from '
|
|
13
|
-
import { Button } from '../components/button'
|
|
14
|
-
import { ButtonsDisabler } from '../components/buttons-disabler'
|
|
15
|
-
import { Element } from '../components/element'
|
|
16
|
-
import { Pic } from '../components/pic'
|
|
17
|
-
import { Reply } from '../components/reply'
|
|
18
|
-
import { Subtitle } from '../components/subtitle'
|
|
19
|
-
import { Title } from '../components/title'
|
|
19
|
+
} from '../message-utils'
|
|
20
20
|
// Experimental
|
|
21
21
|
import { Audio } from './components/audio'
|
|
22
22
|
import { Carousel } from './components/carousel'
|
|
@@ -39,7 +39,7 @@ export function msgToBotonic(msg, customMessageTypes) {
|
|
|
39
39
|
if (isCustom(msg)) {
|
|
40
40
|
try {
|
|
41
41
|
return customMessageTypes
|
|
42
|
-
.find(mt => mt.customTypeName === msg.customTypeName)
|
|
42
|
+
.find(mt => mt.customTypeName === msg.json.customTypeName)
|
|
43
43
|
.deserialize(msg)
|
|
44
44
|
} catch (e) {
|
|
45
45
|
console.log(e)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { CoreBot } from '@botonic/core'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
|
|
4
|
-
import { RequestContext } from '../contexts'
|
|
5
4
|
import { Text } from './components/text'
|
|
5
|
+
import { RequestContext } from './contexts'
|
|
6
6
|
|
|
7
7
|
export class ReactBot extends CoreBot {
|
|
8
8
|
constructor(options) {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { WEBCHAT } from '../constants'
|
|
2
|
+
|
|
3
|
+
export const getScrollableArea = webchatElement => {
|
|
4
|
+
const getArea = area => {
|
|
5
|
+
const botonicScrollableContent = webchatElement.querySelector(
|
|
6
|
+
WEBCHAT.SELECTORS.SCROLLABLE_CONTENT
|
|
7
|
+
)
|
|
8
|
+
const scrollableArea =
|
|
9
|
+
botonicScrollableContent && botonicScrollableContent.querySelector(area)
|
|
10
|
+
return scrollableArea
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
full: getArea(WEBCHAT.SELECTORS.SIMPLEBAR_CONTENT),
|
|
14
|
+
visible: getArea(WEBCHAT.SELECTORS.SIMPLEBAR_WRAPPER),
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const scrollToBottom = ({
|
|
19
|
+
timeout = 200,
|
|
20
|
+
behavior = 'smooth',
|
|
21
|
+
host,
|
|
22
|
+
} = {}) => {
|
|
23
|
+
const webchatElement = getWebchatElement(host)
|
|
24
|
+
if (!webchatElement) return
|
|
25
|
+
const frame = getScrollableArea(webchatElement).visible
|
|
26
|
+
if (frame) {
|
|
27
|
+
setTimeout(
|
|
28
|
+
() => frame.scrollTo({ top: frame.scrollHeight, behavior: behavior }),
|
|
29
|
+
timeout
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const getWebchatElement = host =>
|
|
35
|
+
host && host.querySelector(`#${WEBCHAT.DEFAULTS.ID}`)
|
|
36
|
+
|
|
37
|
+
// https://stackoverflow.com/questions/9457891/how-to-detect-if-domcontentloaded-was-fired
|
|
38
|
+
export const onDOMLoaded = callback => {
|
|
39
|
+
if (/complete|interactive|loaded/.test(document.readyState)) {
|
|
40
|
+
// In case the document has finished parsing, document's readyState will
|
|
41
|
+
// be one of "complete", "interactive" or (non-standard) "loaded".
|
|
42
|
+
callback()
|
|
43
|
+
} else {
|
|
44
|
+
// The document is not ready yet, so wait for the DOMContentLoaded event
|
|
45
|
+
document.addEventListener('DOMContentLoaded', callback, false)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const isShadowDOMSupported = () => {
|
|
50
|
+
try {
|
|
51
|
+
return document.head.createShadowRoot || document.head.attachShadow
|
|
52
|
+
} catch (e) {
|
|
53
|
+
return false
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* given an object and a property, returns the property if exists (recursively), else undefined
|
|
3
|
+
* ex:
|
|
4
|
+
* let obj = { a: { b: { c: 5 } } }
|
|
5
|
+
* getProperty(obj, 'a.b.c'), returns 5
|
|
6
|
+
* getProperty(obj, 'a.b.z'), returns undefined
|
|
7
|
+
*/
|
|
8
|
+
export const getProperty = (obj, property) => {
|
|
9
|
+
if (!property) return undefined
|
|
10
|
+
const properties = property.split('.')
|
|
11
|
+
for (let i = 0; i < properties.length; i++) {
|
|
12
|
+
const prop = properties[i]
|
|
13
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
14
|
+
if (!obj || !obj.hasOwnProperty(prop)) {
|
|
15
|
+
return undefined
|
|
16
|
+
} else {
|
|
17
|
+
obj = obj[prop]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return obj
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function strToBool(string) {
|
|
24
|
+
const regex = /^\s*(true|1|on)\s*$/i
|
|
25
|
+
string = String(string)
|
|
26
|
+
return regex.test(string)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const mapObject = (obj, conversion = ([key, value]) => [key, value]) => {
|
|
30
|
+
return (
|
|
31
|
+
obj &&
|
|
32
|
+
Object.entries(obj)
|
|
33
|
+
.map(conversion)
|
|
34
|
+
.reduce(function (prev, curr) {
|
|
35
|
+
prev[curr[0]] = curr[1]
|
|
36
|
+
return prev
|
|
37
|
+
}, {})
|
|
38
|
+
)
|
|
39
|
+
}
|