@botpress/webchat 0.2.5 → 0.3.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/README.md +31 -0
- package/assets/fonts/roboto/roboto.woff2 +0 -0
- package/assets/fonts/roboto/roboto500.woff2 +0 -0
- package/assets/fonts/roboto.css +128 -0
- package/assets/notification.mp3 +0 -0
- package/dist/components/Composer.d.ts +4 -5
- package/dist/components/Composer.js +16 -25
- package/dist/components/Container.js +1 -4
- package/dist/components/ConversationList.d.ts +1 -1
- package/dist/components/ConversationList.js +5 -46
- package/dist/components/Header.d.ts +1 -3
- package/dist/components/Header.js +7 -37
- package/dist/components/common/BotInfo/index.d.ts +1 -1
- package/dist/components/common/BotInfo/index.js +4 -14
- package/dist/components/messages/InlineFeedback.d.ts +2 -1
- package/dist/components/messages/Message.js +3 -6
- package/dist/components/messages/MessageGroup.d.ts +1 -5
- package/dist/components/messages/MessageGroup.js +4 -7
- package/dist/components/messages/MessageList.d.ts +1 -1
- package/dist/components/messages/MessageList.js +7 -29
- package/dist/core/api.d.ts +2 -6
- package/dist/core/api.js +4 -32
- package/dist/core/constants.d.ts +4 -32
- package/dist/core/constants.js +18 -32
- package/dist/core/socket.d.ts +1 -7
- package/dist/core/socket.js +8 -30
- package/dist/index.d.ts +2 -8
- package/dist/index.js +6 -27
- package/dist/main.d.ts +2 -2
- package/dist/main.js +84 -135
- package/dist/store/composer.js +1 -1
- package/dist/store/index.d.ts +4 -8
- package/dist/store/index.js +25 -62
- package/dist/store/view.d.ts +3 -4
- package/dist/store/view.js +6 -13
- package/dist/translations/index.d.ts +2 -1
- package/dist/translations/index.js +36 -1
- package/dist/typings.d.ts +123 -55
- package/dist/utils/analytics.d.ts +5 -0
- package/dist/utils/analytics.js +37 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +27 -0
- package/package.json +6 -5
- package/dist/components/ContextMenu.d.ts +0 -2
- package/dist/components/ContextMenu.js +0 -24
- package/dist/components/OverridableComponent.d.ts +0 -24
- package/dist/components/OverridableComponent.js +0 -50
- package/dist/components/Stylesheet.d.ts +0 -5
- package/dist/components/Stylesheet.js +0 -7
- package/dist/components/common/MoreOptions/index.d.ts +0 -21
- package/dist/components/common/MoreOptions/index.js +0 -60
- package/dist/components/common/Overlay/index.d.ts +0 -7
- package/dist/components/common/Overlay/index.js +0 -36
- package/dist/icons/CloseChat.d.ts +0 -6
- package/dist/icons/CloseChat.js +0 -9
- package/dist/icons/Send.d.ts +0 -6
- package/dist/icons/Send.js +0 -8
- package/dist/utils.d.ts +0 -8
- package/dist/utils.js +0 -111
package/dist/main.js
CHANGED
|
@@ -41,19 +41,18 @@ const query_string_1 = __importDefault(require("query-string"));
|
|
|
41
41
|
const react_1 = __importDefault(require("react"));
|
|
42
42
|
const react_intl_1 = require("react-intl");
|
|
43
43
|
const Container_1 = __importDefault(require("./components/Container"));
|
|
44
|
-
const Stylesheet_1 = __importDefault(require("./components/Stylesheet"));
|
|
45
44
|
const constants_1 = __importDefault(require("./core/constants"));
|
|
46
45
|
const socket_1 = __importDefault(require("./core/socket"));
|
|
47
46
|
const Chat_1 = __importDefault(require("./icons/Chat"));
|
|
48
47
|
const utils_1 = require("./utils");
|
|
48
|
+
const analytics_1 = require("./utils/analytics");
|
|
49
49
|
exports.DEFAULT_TYPING_DELAY = 1000;
|
|
50
50
|
class Web extends react_1.default.Component {
|
|
51
51
|
constructor(props) {
|
|
52
52
|
super(props);
|
|
53
53
|
this.hasBeenInitialized = false;
|
|
54
54
|
this.isCurrentConversation = (event) => {
|
|
55
|
-
|
|
56
|
-
return !((_a = this.props.config) === null || _a === void 0 ? void 0 : _a.conversationId) || ((_b = this.props.config) === null || _b === void 0 ? void 0 : _b.conversationId) === event.conversationId;
|
|
55
|
+
return this.props.currentConversationId === event.conversationId;
|
|
57
56
|
};
|
|
58
57
|
this.handleKeyDown = (e) => __awaiter(this, void 0, void 0, function* () {
|
|
59
58
|
var _a;
|
|
@@ -64,52 +63,51 @@ class Web extends react_1.default.Component {
|
|
|
64
63
|
this.props.hideChat();
|
|
65
64
|
}
|
|
66
65
|
});
|
|
67
|
-
this.handleIframeApi = ({ data
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
66
|
+
this.handleIframeApi = ({ data }) => __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
switch (data.action) {
|
|
68
|
+
case 'configure':
|
|
69
|
+
return this.props.updateConfig(Object.assign({}, constants_1.default.DEFAULT_CONFIG, data.payload));
|
|
70
|
+
case 'mergeConfig':
|
|
71
|
+
return this.props.mergeConfig(data.payload);
|
|
72
|
+
case 'sendPayload':
|
|
73
|
+
return this.props.sendData(data.payload);
|
|
74
|
+
case 'event':
|
|
75
|
+
const { type, text, conversationId } = data.payload;
|
|
76
|
+
if (type === 'show') {
|
|
77
|
+
this.props.showChat();
|
|
78
|
+
(0, analytics_1.trackWebchatState)('show');
|
|
79
|
+
}
|
|
80
|
+
else if (type === 'hide') {
|
|
81
|
+
this.props.hideChat();
|
|
82
|
+
(0, analytics_1.trackWebchatState)('hide');
|
|
83
|
+
}
|
|
84
|
+
else if (type === 'toggle') {
|
|
85
|
+
this.props.displayWidgetView ? this.props.showChat() : this.props.hideChat();
|
|
86
|
+
(0, analytics_1.trackWebchatState)('toggle');
|
|
87
|
+
}
|
|
88
|
+
else if (type === 'message') {
|
|
89
|
+
(0, analytics_1.trackMessage)('sent');
|
|
90
|
+
yield this.props.sendMessage(text);
|
|
91
|
+
}
|
|
92
|
+
else if (type === 'loadConversation') {
|
|
93
|
+
yield this.props.fetchConversation(conversationId);
|
|
94
|
+
}
|
|
95
|
+
else if (type === 'toggleBotInfo') {
|
|
96
|
+
this.props.toggleBotInfo();
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
yield this.props.sendData({ type, payload: data.payload });
|
|
100
|
+
}
|
|
101
|
+
default:
|
|
102
|
+
break;
|
|
104
103
|
}
|
|
105
104
|
});
|
|
106
|
-
this.handleClearMessages = (event) => {
|
|
107
|
-
if (this.isCurrentConversation(event)) {
|
|
108
|
-
this.props.clearMessages();
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
105
|
this.handleNewMessage = (event) => __awaiter(this, void 0, void 0, function* () {
|
|
112
106
|
var _b;
|
|
107
|
+
if (!this.isCurrentConversation(event)) {
|
|
108
|
+
// don't do anything, it's a message from another conversation
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
113
111
|
if (event.authorId === undefined) {
|
|
114
112
|
const value = (event.payload.type === 'typing' ? event.payload.value : undefined) || exports.DEFAULT_TYPING_DELAY;
|
|
115
113
|
yield this.handleTyping(Object.assign(Object.assign({}, event), { timeInMs: value }));
|
|
@@ -118,11 +116,7 @@ class Web extends react_1.default.Component {
|
|
|
118
116
|
// don't do anything, it's the system message
|
|
119
117
|
return;
|
|
120
118
|
}
|
|
121
|
-
|
|
122
|
-
// don't do anything, it's a message from another conversation
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
(0, utils_1.trackMessage)('received');
|
|
119
|
+
(0, analytics_1.trackMessage)('received');
|
|
126
120
|
this.props.updateLastMessage(event.conversationId, event);
|
|
127
121
|
yield this.props.addEventToConversation(event);
|
|
128
122
|
// there's no focus on the actual conversation
|
|
@@ -133,27 +127,11 @@ class Web extends react_1.default.Component {
|
|
|
133
127
|
this.handleResetUnreadCount();
|
|
134
128
|
});
|
|
135
129
|
this.handleTyping = (event) => __awaiter(this, void 0, void 0, function* () {
|
|
136
|
-
if (!this.isCurrentConversation(event)) {
|
|
137
|
-
// don't do anything, it's a message from another conversation
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
130
|
yield this.props.updateTyping(event);
|
|
141
131
|
});
|
|
142
|
-
this.handleDataMessage = (event) => {
|
|
143
|
-
if (!event || !event.payload) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
const { language } = event.payload;
|
|
147
|
-
if (!language) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
this.props.updateBotUILanguage(language);
|
|
151
|
-
};
|
|
152
132
|
this.playSound = (0, debounce_1.default)(() => __awaiter(this, void 0, void 0, function* () {
|
|
153
|
-
|
|
154
|
-
const disableNotificationSound = this.config.disableNotificationSound ===
|
|
155
|
-
? this.props.config.disableNotificationSound
|
|
156
|
-
: this.config.disableNotificationSound;
|
|
133
|
+
var _c;
|
|
134
|
+
const disableNotificationSound = this.config.disableNotificationSound || ((_c = this.props.config) === null || _c === void 0 ? void 0 : _c.disableNotificationSound);
|
|
157
135
|
if (disableNotificationSound || this.audio.readyState < 2) {
|
|
158
136
|
return;
|
|
159
137
|
}
|
|
@@ -164,17 +142,16 @@ class Web extends react_1.default.Component {
|
|
|
164
142
|
this.props.resetUnread();
|
|
165
143
|
}
|
|
166
144
|
};
|
|
167
|
-
(0,
|
|
168
|
-
(0, utils_1.initializeAnalytics)();
|
|
145
|
+
(0, analytics_1.initializeAnalytics)();
|
|
169
146
|
}
|
|
170
147
|
componentDidMount() {
|
|
171
148
|
return __awaiter(this, void 0, void 0, function* () {
|
|
172
149
|
this.audio = new Audio(require('url:../assets/notification.mp3'));
|
|
173
|
-
this.props.
|
|
150
|
+
this.props.setIntlProvider(this.props.intl);
|
|
174
151
|
window.store = this.props.store;
|
|
175
152
|
window.addEventListener('message', this.handleIframeApi);
|
|
176
153
|
window.addEventListener('keydown', this.handleKeyDown);
|
|
177
|
-
yield this.
|
|
154
|
+
yield this.loadConfig();
|
|
178
155
|
yield this.initializeIfChatDisplayed();
|
|
179
156
|
this.props.setLoadingCompleted();
|
|
180
157
|
});
|
|
@@ -198,27 +175,24 @@ class Web extends react_1.default.Component {
|
|
|
198
175
|
if (this.isLazySocket() || !this.socket) {
|
|
199
176
|
yield this.initializeSocket();
|
|
200
177
|
}
|
|
201
|
-
yield this.socket.
|
|
202
|
-
this.props.
|
|
178
|
+
yield this.socket.connect();
|
|
179
|
+
this.props.setSocket(this.socket);
|
|
203
180
|
yield this.props.initializeChat();
|
|
204
181
|
}
|
|
205
182
|
});
|
|
206
183
|
}
|
|
207
|
-
|
|
184
|
+
loadConfig() {
|
|
208
185
|
return __awaiter(this, void 0, void 0, function* () {
|
|
209
186
|
this.config = this.extractConfig();
|
|
187
|
+
this.props.updateConfig(this.config);
|
|
210
188
|
if (this.config.exposeStore) {
|
|
211
189
|
const storePath = this.config.chatId ? `${this.config.chatId}.webchat_store` : 'webchat_store';
|
|
212
190
|
(0, set_1.default)(window.parent, storePath, this.props.store);
|
|
213
191
|
}
|
|
214
|
-
if (this.config.overrides) {
|
|
215
|
-
this.loadOverrides(this.config.overrides);
|
|
216
|
-
}
|
|
217
192
|
if (this.config.containerWidth) {
|
|
218
193
|
this.postMessageToParent('setWidth', this.config.containerWidth);
|
|
219
194
|
}
|
|
220
|
-
|
|
221
|
-
// await this.props.fetchBotInfo!()
|
|
195
|
+
yield this.props.fetchBotInfo();
|
|
222
196
|
if (!this.isLazySocket()) {
|
|
223
197
|
yield this.initializeSocket();
|
|
224
198
|
}
|
|
@@ -226,68 +200,38 @@ class Web extends react_1.default.Component {
|
|
|
226
200
|
});
|
|
227
201
|
}
|
|
228
202
|
postMessageToParent(type, value) {
|
|
229
|
-
var _a
|
|
230
|
-
(_a = window.parent) === null || _a === void 0 ? void 0 : _a.postMessage({ type, value, chatId:
|
|
203
|
+
var _a;
|
|
204
|
+
(_a = window.parent) === null || _a === void 0 ? void 0 : _a.postMessage({ type, value, chatId: this.config.chatId }, '*');
|
|
231
205
|
}
|
|
232
206
|
extractConfig() {
|
|
233
|
-
|
|
234
|
-
try {
|
|
235
|
-
return decodeURIComponent(options);
|
|
236
|
-
}
|
|
237
|
-
catch (_a) {
|
|
238
|
-
return options;
|
|
239
|
-
}
|
|
240
|
-
};
|
|
207
|
+
let userConfig = Object.assign({}, constants_1.default.DEFAULT_CONFIG, this.props.config);
|
|
241
208
|
const { options } = query_string_1.default.parse(location.search);
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
209
|
+
if (!options || typeof options !== 'string') {
|
|
210
|
+
console.warn(`Cannot decode option. Invalid format: ${typeof options}, expecting 'string'.`);
|
|
211
|
+
return userConfig;
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
const parsedOptions = JSON.parse(decodeURIComponent(options));
|
|
215
|
+
userConfig = Object.assign(userConfig, parsedOptions.config);
|
|
216
|
+
return userConfig;
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
// TODO: Handle those errors so they don't directly bubble up to the users
|
|
220
|
+
throw new Error(`An error occurred while extracting the configurations ${err}`);
|
|
221
|
+
}
|
|
246
222
|
}
|
|
247
223
|
initializeSocket() {
|
|
248
224
|
return __awaiter(this, void 0, void 0, function* () {
|
|
249
225
|
this.socket = new socket_1.default(this.config);
|
|
250
|
-
this.socket.onClear = this.handleClearMessages;
|
|
251
226
|
this.socket.onMessage = this.handleNewMessage;
|
|
252
|
-
this.socket.onTyping = this.handleTyping;
|
|
253
|
-
this.socket.onData = this.handleDataMessage;
|
|
254
|
-
this.socket.onUserIdChanged = this.props.setUserId;
|
|
255
|
-
// TODO: Can't do that
|
|
256
|
-
// this.config.userId && this.socket.changeUserId(this.config.userId)
|
|
257
227
|
this.socket.setup();
|
|
258
|
-
yield this.socket.
|
|
259
|
-
this.props.
|
|
228
|
+
yield this.socket.connect();
|
|
229
|
+
this.props.setSocket(this.socket);
|
|
260
230
|
});
|
|
261
231
|
}
|
|
262
|
-
loadOverrides(overrides) {
|
|
263
|
-
try {
|
|
264
|
-
for (const override of Object.values(overrides)) {
|
|
265
|
-
// TODO: load module view this can't work
|
|
266
|
-
// override.map(({ module }) => this.props.bp!.loadModuleView(module, true))
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
catch (err) {
|
|
270
|
-
console.error('Error while loading overrides', err.message);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
232
|
setupObserver() {
|
|
274
|
-
(0, mobx_1.observe)(this.props.config, 'userId', (data) => __awaiter(this, void 0, void 0, function* () {
|
|
275
|
-
if (!data.oldValue || data.oldValue === data.newValue) {
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
// TODO: Can't work right now
|
|
279
|
-
// this.socket.changeUserId(data.newValue)
|
|
280
|
-
this.socket.setup();
|
|
281
|
-
yield this.socket.waitForUserId();
|
|
282
|
-
yield this.props.initializeChat();
|
|
283
|
-
}));
|
|
284
|
-
(0, mobx_1.observe)(this.props.config, 'overrides', (data) => {
|
|
285
|
-
if (data.newValue && window.parent) {
|
|
286
|
-
this.loadOverrides(data.newValue);
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
233
|
(0, mobx_1.observe)(this.props.dimensions, 'container', (data) => {
|
|
290
|
-
if (data.newValue
|
|
234
|
+
if (data.newValue) {
|
|
291
235
|
this.postMessageToParent('setWidth', data.newValue);
|
|
292
236
|
}
|
|
293
237
|
});
|
|
@@ -310,20 +254,22 @@ class Web extends react_1.default.Component {
|
|
|
310
254
|
this.props.hasUnreadMessages && react_1.default.createElement("span", { className: 'bpw-floating-button-unread' }, this.props.unreadCount)));
|
|
311
255
|
}
|
|
312
256
|
applyAndRenderStyle() {
|
|
257
|
+
var _a, _b, _c;
|
|
313
258
|
const parentClass = (0, classnames_1.default)(`bp-widget-web bp-widget-${this.props.activeView}`, {
|
|
314
259
|
'bp-widget-hidden': !this.props.showWidgetButton && this.props.displayWidgetView,
|
|
315
|
-
[this.props.config.className]: !!this.props.config.className
|
|
260
|
+
[(_a = this.props.config) === null || _a === void 0 ? void 0 : _a.className]: !!((_b = this.props.config) === null || _b === void 0 ? void 0 : _b.className)
|
|
316
261
|
});
|
|
317
262
|
if (this.parentClass !== parentClass) {
|
|
318
263
|
this.postMessageToParent('setClass', parentClass);
|
|
319
264
|
this.parentClass = parentClass;
|
|
320
265
|
}
|
|
321
|
-
const
|
|
266
|
+
const stylesheet = this.props.config.stylesheet;
|
|
267
|
+
const extraStylesheet = (_c = this.props.botInfo) === null || _c === void 0 ? void 0 : _c.extraStylesheet;
|
|
322
268
|
const RobotoFont = react_1.default.lazy(() => Promise.resolve().then(() => __importStar(require('./fonts/roboto'))));
|
|
323
269
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
324
|
-
!!(stylesheet === null || stylesheet === void 0 ? void 0 : stylesheet.length) && react_1.default.createElement(
|
|
270
|
+
!!(stylesheet === null || stylesheet === void 0 ? void 0 : stylesheet.length) && react_1.default.createElement("link", { rel: "stylesheet", type: "text/css", href: stylesheet }),
|
|
325
271
|
react_1.default.createElement(react_1.default.Suspense, { fallback: react_1.default.createElement(react_1.default.Fragment, null) }, !utils_1.isIE && react_1.default.createElement(RobotoFont, null)),
|
|
326
|
-
!!(extraStylesheet === null || extraStylesheet === void 0 ? void 0 : extraStylesheet.length) && react_1.default.createElement(
|
|
272
|
+
!!(extraStylesheet === null || extraStylesheet === void 0 ? void 0 : extraStylesheet.length) && react_1.default.createElement("link", { rel: "stylesheet", type: "text/css", href: extraStylesheet })));
|
|
327
273
|
}
|
|
328
274
|
render() {
|
|
329
275
|
if (!this.props.isWebchatReady) {
|
|
@@ -349,7 +295,6 @@ exports.default = (0, mobx_react_1.inject)(({ store }) => ({
|
|
|
349
295
|
mergeConfig: store.mergeConfig,
|
|
350
296
|
addEventToConversation: store.addEventToConversation,
|
|
351
297
|
clearMessages: store.clearMessages,
|
|
352
|
-
setUserId: store.setUserId,
|
|
353
298
|
updateTyping: store.updateTyping,
|
|
354
299
|
sendMessage: store.sendMessage,
|
|
355
300
|
updateBotUILanguage: store.updateBotUILanguage,
|
|
@@ -369,5 +314,9 @@ exports.default = (0, mobx_react_1.inject)(({ store }) => ({
|
|
|
369
314
|
displayWidgetView: store.view.displayWidgetView,
|
|
370
315
|
setLoadingCompleted: store.view.setLoadingCompleted,
|
|
371
316
|
sendFeedback: store.sendFeedback,
|
|
372
|
-
updateLastMessage: store.updateLastMessage
|
|
317
|
+
updateLastMessage: store.updateLastMessage,
|
|
318
|
+
fetchConversation: store.fetchConversation,
|
|
319
|
+
setIntlProvider: store.setIntlProvider,
|
|
320
|
+
setSocket: store.setSocket,
|
|
321
|
+
currentConversationId: store.currentConversationId
|
|
373
322
|
}))((0, react_intl_1.injectIntl)((0, mobx_react_1.observer)(Web)));
|
package/dist/store/composer.js
CHANGED
package/dist/store/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { IntlShape } from 'react-intl';
|
|
3
3
|
import BpSocket from '../core/socket';
|
|
4
|
-
import { BotInfo, Config, CurrentConversation, EventFeedback, Message, QueuedMessage, RecentConversation,
|
|
4
|
+
import { BotInfo, Config, CurrentConversation, EventFeedback, Message, QueuedMessage, RecentConversation, uuid } from '../typings';
|
|
5
5
|
import ComposerStore from './composer';
|
|
6
6
|
import ViewStore from './view';
|
|
7
|
-
/** Includes the
|
|
7
|
+
/** Includes the definitions of all store classes */
|
|
8
8
|
export declare type StoreDef = Partial<RootStore> & Partial<ViewStore> & Partial<ComposerStore> & Partial<Config>;
|
|
9
9
|
declare class RootStore {
|
|
10
10
|
composer: ComposerStore;
|
|
@@ -57,22 +57,18 @@ declare class RootStore {
|
|
|
57
57
|
/** Creates a new conversation and switches to it */
|
|
58
58
|
createConversation(): Promise<uuid>;
|
|
59
59
|
resetConversation(): void;
|
|
60
|
-
resetSession(): Promise<void>;
|
|
61
60
|
extractFeedback(messages: Message[]): Promise<void>;
|
|
62
61
|
sendFeedback(feedback: number, messageId: string): Promise<void>;
|
|
63
62
|
downloadConversation(): Promise<void>;
|
|
64
63
|
/** Sends an event or a message, depending on how the backend manages those types */
|
|
65
64
|
sendData(data: any): Promise<void>;
|
|
66
|
-
uploadFile(title: string, payload: string, file: File): Promise<void>;
|
|
67
65
|
/** Sends a message of type voice */
|
|
68
66
|
sendVoiceMessage(voice: Buffer, ext: string): Promise<void>;
|
|
69
67
|
/** Use this method to replace a value or add a new config */
|
|
70
68
|
mergeConfig(config: Partial<Config>): void;
|
|
71
69
|
/** This replaces all the configurations by this object */
|
|
72
|
-
updateConfig(config: Config
|
|
70
|
+
updateConfig(config: Config): void;
|
|
73
71
|
private _applyConfig;
|
|
74
|
-
/** When this method is used, the user ID is changed in the configuration, then the socket is updated */
|
|
75
|
-
setUserId(userId: string): void;
|
|
76
72
|
publishConfigChanged(): void;
|
|
77
73
|
updatePreferredLanguage(lang: string): void;
|
|
78
74
|
/** Starts a timer to remove the typing animation when it's completed */
|
|
@@ -80,7 +76,7 @@ declare class RootStore {
|
|
|
80
76
|
private _expireTyping;
|
|
81
77
|
updateBotUILanguage(lang: string): void;
|
|
82
78
|
private emptyDelayedMessagesQueue;
|
|
83
|
-
/** Returns the current conversation ID, or the last one
|
|
79
|
+
/** Returns the current conversation ID, or the last one. */
|
|
84
80
|
private _getCurrentConvoId;
|
|
85
81
|
}
|
|
86
82
|
export { RootStore };
|
package/dist/store/index.js
CHANGED
|
@@ -19,6 +19,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
19
19
|
};
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
21
|
exports.RootStore = void 0;
|
|
22
|
+
const axios_1 = __importDefault(require("axios"));
|
|
22
23
|
const is_before_1 = __importDefault(require("date-fns/is_before"));
|
|
23
24
|
const is_valid_1 = __importDefault(require("date-fns/is_valid"));
|
|
24
25
|
const merge_1 = __importDefault(require("lodash/merge"));
|
|
@@ -28,6 +29,7 @@ const api_1 = __importDefault(require("../core/api"));
|
|
|
28
29
|
const main_1 = require("../main");
|
|
29
30
|
const translations_1 = require("../translations");
|
|
30
31
|
const utils_1 = require("../utils");
|
|
32
|
+
const analytics_1 = require("../utils/analytics");
|
|
31
33
|
const composer_1 = __importDefault(require("./composer"));
|
|
32
34
|
const view_1 = __importDefault(require("./view"));
|
|
33
35
|
class RootStore {
|
|
@@ -58,14 +60,14 @@ class RootStore {
|
|
|
58
60
|
}
|
|
59
61
|
get hasBotInfoDescription() {
|
|
60
62
|
var _a;
|
|
61
|
-
return !!((_a = this.config.
|
|
63
|
+
return !!((_a = this.config.botConversationDescription) === null || _a === void 0 ? void 0 : _a.length);
|
|
62
64
|
}
|
|
63
65
|
get botAvatarUrl() {
|
|
64
66
|
var _a, _b, _c;
|
|
65
67
|
return ((_b = (_a = this.botInfo) === null || _a === void 0 ? void 0 : _a.details) === null || _b === void 0 ? void 0 : _b.avatarUrl) || ((_c = this.config) === null || _c === void 0 ? void 0 : _c.avatarUrl) || undefined;
|
|
66
68
|
}
|
|
67
69
|
get rtl() {
|
|
68
|
-
return (0,
|
|
70
|
+
return (0, translations_1.isRTLLocale)(this.preferredLanguage);
|
|
69
71
|
}
|
|
70
72
|
get escapeHTML() {
|
|
71
73
|
var _a, _b;
|
|
@@ -155,7 +157,7 @@ class RootStore {
|
|
|
155
157
|
return __awaiter(this, void 0, void 0, function* () {
|
|
156
158
|
try {
|
|
157
159
|
yield this.fetchConversations();
|
|
158
|
-
yield this.fetchConversation(
|
|
160
|
+
yield this.fetchConversation();
|
|
159
161
|
(0, mobx_1.runInAction)('-> setInitialized', () => {
|
|
160
162
|
this.isInitialized = true;
|
|
161
163
|
this.postMessage('webchatReady');
|
|
@@ -173,17 +175,21 @@ class RootStore {
|
|
|
173
175
|
if (!this.config.mediaFileServiceUrl) {
|
|
174
176
|
return;
|
|
175
177
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
try {
|
|
179
|
+
const { data } = yield axios_1.default.get(this.config.mediaFileServiceUrl);
|
|
180
|
+
if (!data) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
(0, mobx_1.runInAction)('-> setBotInfo', () => {
|
|
184
|
+
this.botInfo = data;
|
|
185
|
+
});
|
|
186
|
+
this.mergeConfig({
|
|
187
|
+
disableNotificationSound: data.disableNotificationSound
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
console.error('Error while loading bot info', err);
|
|
179
192
|
}
|
|
180
|
-
(0, mobx_1.runInAction)('-> setBotInfo', () => {
|
|
181
|
-
this.botInfo = botInfo;
|
|
182
|
-
});
|
|
183
|
-
this.mergeConfig({
|
|
184
|
-
extraStylesheet: botInfo.extraStylesheet,
|
|
185
|
-
disableNotificationSound: botInfo.disableNotificationSound
|
|
186
|
-
});
|
|
187
193
|
});
|
|
188
194
|
}
|
|
189
195
|
fetchLanguage() {
|
|
@@ -235,7 +241,7 @@ class RootStore {
|
|
|
235
241
|
this.composer.updateMessage('');
|
|
236
242
|
try {
|
|
237
243
|
yield this.sendData({ type: 'text', text: userMessage });
|
|
238
|
-
(0,
|
|
244
|
+
(0, analytics_1.trackMessage)('sent');
|
|
239
245
|
this.composer.addMessageToHistory(userMessage);
|
|
240
246
|
}
|
|
241
247
|
catch (e) {
|
|
@@ -264,18 +270,9 @@ class RootStore {
|
|
|
264
270
|
resetConversation() {
|
|
265
271
|
this.currentConversation = undefined;
|
|
266
272
|
}
|
|
267
|
-
resetSession() {
|
|
268
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
269
|
-
if (this.currentConversationId) {
|
|
270
|
-
this.composer.setLocked(false);
|
|
271
|
-
return this.api.resetSession(this.currentConversationId);
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
273
|
extractFeedback(messages) {
|
|
276
274
|
return __awaiter(this, void 0, void 0, function* () {
|
|
277
275
|
const feedbackMessageIds = messages.filter((x) => x.payload && x.payload.collectFeedback).map((x) => x.id);
|
|
278
|
-
// TODO: store feedback somewhere
|
|
279
276
|
const feedbackInfo = feedbackMessageIds.map((x) => ({ messageId: x, feedback: 1 }));
|
|
280
277
|
(0, mobx_1.runInAction)('-> setFeedbackInfo', () => {
|
|
281
278
|
this.messageFeedbacks = feedbackInfo;
|
|
@@ -305,7 +302,7 @@ class RootStore {
|
|
|
305
302
|
if (payload.type === 'session_reset') {
|
|
306
303
|
continue;
|
|
307
304
|
}
|
|
308
|
-
info += `\n[${formatDate(message.sentOn)}] ${message.authorId ? 'User' : this.config.
|
|
305
|
+
info += `\n[${formatDate(message.sentOn)}] ${message.authorId ? 'User' : this.config.botName || 'Bot'}: Event (${payload.type}): ${payload.text ||
|
|
309
306
|
payload.audio ||
|
|
310
307
|
payload.image ||
|
|
311
308
|
payload.video ||
|
|
@@ -333,13 +330,6 @@ class RootStore {
|
|
|
333
330
|
this.updateLastMessage(this.currentConversationId, message);
|
|
334
331
|
});
|
|
335
332
|
}
|
|
336
|
-
uploadFile(title, payload, file) {
|
|
337
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
338
|
-
if (this.currentConversationId) {
|
|
339
|
-
yield this.api.uploadFile(file, payload, this.currentConversationId);
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
333
|
/** Sends a message of type voice */
|
|
344
334
|
sendVoiceMessage(voice, ext) {
|
|
345
335
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -354,7 +344,7 @@ class RootStore {
|
|
|
354
344
|
this._applyConfig();
|
|
355
345
|
}
|
|
356
346
|
/** This replaces all the configurations by this object */
|
|
357
|
-
updateConfig(config
|
|
347
|
+
updateConfig(config) {
|
|
358
348
|
this.config = config;
|
|
359
349
|
this._applyConfig();
|
|
360
350
|
}
|
|
@@ -362,13 +352,11 @@ class RootStore {
|
|
|
362
352
|
window.BP_STORAGE.config = this.config;
|
|
363
353
|
this.config.layoutWidth && this.view.setLayoutWidth(this.config.layoutWidth);
|
|
364
354
|
this.config.containerWidth && this.view.setContainerWidth(this.config.containerWidth);
|
|
365
|
-
this.view.disableAnimations = this.config.disableAnimations;
|
|
355
|
+
this.view.disableAnimations = !!this.config.disableAnimations;
|
|
366
356
|
this.config.showPoweredBy ? this.view.showPoweredBy() : this.view.hidePoweredBy();
|
|
367
357
|
document.title = this.config.botName || 'Botpress Webchat';
|
|
368
|
-
// TODO: can't work at the moment
|
|
369
|
-
// this.api.updateUserId(this.config.userId!)
|
|
370
358
|
if (!this.isInitialized) {
|
|
371
|
-
window.USE_SESSION_STORAGE = this.config.useSessionStorage;
|
|
359
|
+
window.USE_SESSION_STORAGE = !!this.config.useSessionStorage;
|
|
372
360
|
}
|
|
373
361
|
else if (window.USE_SESSION_STORAGE !== this.config.useSessionStorage) {
|
|
374
362
|
console.warn('[WebChat] "useSessionStorage" value cannot be altered once the webchat is initialized');
|
|
@@ -378,13 +366,6 @@ class RootStore {
|
|
|
378
366
|
document.documentElement.setAttribute('lang', locale);
|
|
379
367
|
this.publishConfigChanged();
|
|
380
368
|
}
|
|
381
|
-
/** When this method is used, the user ID is changed in the configuration, then the socket is updated */
|
|
382
|
-
setUserId(userId) {
|
|
383
|
-
this.config.userId = userId;
|
|
384
|
-
this.resetConversation();
|
|
385
|
-
// this.api.updateUserId(userId)
|
|
386
|
-
this.publishConfigChanged();
|
|
387
|
-
}
|
|
388
369
|
publishConfigChanged() {
|
|
389
370
|
this.postMessage('configChanged', JSON.stringify(this.config, undefined, 2));
|
|
390
371
|
}
|
|
@@ -441,7 +422,7 @@ class RootStore {
|
|
|
441
422
|
}
|
|
442
423
|
}
|
|
443
424
|
}
|
|
444
|
-
/** Returns the current conversation ID, or the last one
|
|
425
|
+
/** Returns the current conversation ID, or the last one. */
|
|
445
426
|
_getCurrentConvoId() {
|
|
446
427
|
if (this.currentConversationId) {
|
|
447
428
|
return this.currentConversationId;
|
|
@@ -449,15 +430,6 @@ class RootStore {
|
|
|
449
430
|
if (!this.conversations.length) {
|
|
450
431
|
return;
|
|
451
432
|
}
|
|
452
|
-
// TODO: these settings need to be set in the frontend
|
|
453
|
-
/*
|
|
454
|
-
const lifeTimeMargin = Date.now() - ms(this.config.recentConversationLifetime)
|
|
455
|
-
const isConversationExpired =
|
|
456
|
-
new Date(this.conversations[0].lastMessage?.sentOn || this.conversations[0].createdOn).getTime() < lifeTimeMargin
|
|
457
|
-
if (isConversationExpired && this.config.startNewConvoOnTimeout) {
|
|
458
|
-
return
|
|
459
|
-
}
|
|
460
|
-
*/
|
|
461
433
|
return this.conversations[0].id;
|
|
462
434
|
}
|
|
463
435
|
}
|
|
@@ -563,9 +535,6 @@ __decorate([
|
|
|
563
535
|
__decorate([
|
|
564
536
|
mobx_1.action.bound
|
|
565
537
|
], RootStore.prototype, "resetConversation", null);
|
|
566
|
-
__decorate([
|
|
567
|
-
mobx_1.action.bound
|
|
568
|
-
], RootStore.prototype, "resetSession", null);
|
|
569
538
|
__decorate([
|
|
570
539
|
mobx_1.action.bound
|
|
571
540
|
], RootStore.prototype, "extractFeedback", null);
|
|
@@ -578,9 +547,6 @@ __decorate([
|
|
|
578
547
|
__decorate([
|
|
579
548
|
mobx_1.action.bound
|
|
580
549
|
], RootStore.prototype, "sendData", null);
|
|
581
|
-
__decorate([
|
|
582
|
-
mobx_1.action.bound
|
|
583
|
-
], RootStore.prototype, "uploadFile", null);
|
|
584
550
|
__decorate([
|
|
585
551
|
mobx_1.action.bound
|
|
586
552
|
], RootStore.prototype, "sendVoiceMessage", null);
|
|
@@ -590,9 +556,6 @@ __decorate([
|
|
|
590
556
|
__decorate([
|
|
591
557
|
mobx_1.action.bound
|
|
592
558
|
], RootStore.prototype, "updateConfig", null);
|
|
593
|
-
__decorate([
|
|
594
|
-
mobx_1.action.bound
|
|
595
|
-
], RootStore.prototype, "setUserId", null);
|
|
596
559
|
__decorate([
|
|
597
560
|
mobx_1.action.bound
|
|
598
561
|
], RootStore.prototype, "publishConfigChanged", null);
|
package/dist/store/view.d.ts
CHANGED
|
@@ -18,11 +18,10 @@ declare class ViewStore {
|
|
|
18
18
|
customActions: CustomAction[];
|
|
19
19
|
disableAnimations: boolean;
|
|
20
20
|
constructor(rootStore: RootStore, fullscreen: boolean);
|
|
21
|
-
get showConversationsButton(): boolean;
|
|
21
|
+
get showConversationsButton(): boolean | undefined;
|
|
22
22
|
get showBotInfoButton(): boolean;
|
|
23
|
-
get showDownloadButton(): boolean;
|
|
24
|
-
get showDeleteConversationButton(): boolean;
|
|
25
|
-
get showResetButton(): boolean;
|
|
23
|
+
get showDownloadButton(): boolean | undefined;
|
|
24
|
+
get showDeleteConversationButton(): boolean | undefined;
|
|
26
25
|
get showCloseButton(): boolean;
|
|
27
26
|
get showWidgetButton(): boolean;
|
|
28
27
|
get hasUnreadMessages(): boolean;
|