@botpress/webchat 0.3.3 → 0.5.0
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/dist/components/messages/Message.d.ts +1 -1
- package/dist/components/messages/Message.js +20 -3
- package/dist/components/messages/MessageGroup.d.ts +1 -1
- package/dist/components/messages/MessageGroup.js +5 -2
- package/dist/core/socket.d.ts +3 -1
- package/dist/core/socket.js +18 -6
- package/dist/main.d.ts +1 -1
- package/dist/main.js +33 -19
- package/dist/store/index.d.ts +4 -4
- package/dist/store/index.js +23 -24
- package/dist/store/view.js +6 -5
- package/dist/typings.d.ts +22 -11
- package/dist/utils/webchatEvents.d.ts +2 -0
- package/dist/utils/webchatEvents.js +14 -0
- package/package.json +3 -3
|
@@ -8,4 +8,4 @@ declare const _default: React.ForwardRefExoticComponent<import("react-intl").Omi
|
|
|
8
8
|
WrappedComponent: React.ComponentType<MessageProps>;
|
|
9
9
|
} & import("mobx-react").IWrappedComponent<unknown>;
|
|
10
10
|
export default _default;
|
|
11
|
-
declare type MessageProps = Renderer.Message & WrappedComponentProps & Pick<StoreDef, 'intl'>;
|
|
11
|
+
declare type MessageProps = Renderer.Message & WrappedComponentProps & Pick<StoreDef, 'intl' | 'selectedMessageId' | 'config'>;
|
|
@@ -27,6 +27,7 @@ const classnames_1 = __importDefault(require("classnames"));
|
|
|
27
27
|
const mobx_react_1 = require("mobx-react");
|
|
28
28
|
const react_1 = __importStar(require("react"));
|
|
29
29
|
const react_intl_1 = require("react-intl");
|
|
30
|
+
const webchatEvents_1 = require("../../utils/webchatEvents");
|
|
30
31
|
class Message extends react_1.Component {
|
|
31
32
|
constructor() {
|
|
32
33
|
super(...arguments);
|
|
@@ -34,6 +35,17 @@ class Message extends react_1.Component {
|
|
|
34
35
|
hasError: false,
|
|
35
36
|
showMore: false
|
|
36
37
|
};
|
|
38
|
+
this.onMessageClick = () => {
|
|
39
|
+
var _a, _b;
|
|
40
|
+
(_a = this.props.store) === null || _a === void 0 ? void 0 : _a.setSelectedMessage(this.props.messageId);
|
|
41
|
+
(0, webchatEvents_1.postMessageToParent)('MESSAGE.SELECTED', {
|
|
42
|
+
id: this.props.messageId,
|
|
43
|
+
conversationId: (_b = this.props.store) === null || _b === void 0 ? void 0 : _b.currentConversationId,
|
|
44
|
+
sentOn: this.props.sentOn,
|
|
45
|
+
payload: this.props.payload,
|
|
46
|
+
from: this.props.isBotMessage ? 'bot' : 'user'
|
|
47
|
+
}, this.props.config.chatId);
|
|
48
|
+
};
|
|
37
49
|
}
|
|
38
50
|
static getDerivedStateFromError(_error) {
|
|
39
51
|
return { hasError: true };
|
|
@@ -70,11 +82,14 @@ class Message extends react_1.Component {
|
|
|
70
82
|
return null;
|
|
71
83
|
}
|
|
72
84
|
const additionalStyle = (this.props.payload && this.props.payload['web-style']) || {};
|
|
85
|
+
const messageSelectedClass = {
|
|
86
|
+
'bpw-message-selected': this.props.selectedMessageId === this.props.messageId
|
|
87
|
+
};
|
|
73
88
|
if (this.props.noBubble || ((_b = (_a = this.props.payload) === null || _a === void 0 ? void 0 : _a.wrapped) === null || _b === void 0 ? void 0 : _b.noBubble)) {
|
|
74
|
-
return (react_1.default.createElement("div", { className: (0, classnames_1.default)(this.props.className, wrappedClass), style: additionalStyle }, rendered));
|
|
89
|
+
return (react_1.default.createElement("div", { className: (0, classnames_1.default)(this.props.className, wrappedClass, messageSelectedClass), style: additionalStyle, onClick: this.onMessageClick }, rendered));
|
|
75
90
|
}
|
|
76
91
|
return (react_1.default.createElement("div", { className: (0, classnames_1.default)(this.props.className, wrappedClass, 'bpw-chat-bubble', `bpw-bubble-${type}`), "data-from": this.props.fromLabel, tabIndex: -1, style: additionalStyle },
|
|
77
|
-
react_1.default.createElement("div", { tabIndex: -1, className:
|
|
92
|
+
react_1.default.createElement("div", { tabIndex: -1, className: (0, classnames_1.default)('bpw-chat-bubble-content', messageSelectedClass), onClick: this.onMessageClick },
|
|
78
93
|
react_1.default.createElement("span", { className: "sr-only" }, this.props.store.intl.formatMessage({
|
|
79
94
|
id: this.props.isBotMessage ? 'message.botSaid' : 'message.iSaid',
|
|
80
95
|
defaultMessage: this.props.isBotMessage ? 'Virtual assistant said : ' : 'I said : '
|
|
@@ -85,5 +100,7 @@ class Message extends react_1.Component {
|
|
|
85
100
|
}
|
|
86
101
|
}
|
|
87
102
|
exports.default = (0, mobx_react_1.inject)(({ store }) => ({
|
|
88
|
-
intl: store.intl
|
|
103
|
+
intl: store.intl,
|
|
104
|
+
config: store.config,
|
|
105
|
+
selectedMessageId: store.selectedMessageId
|
|
89
106
|
}))((0, react_intl_1.injectIntl)((0, mobx_react_1.observer)(Message)));
|
|
@@ -43,7 +43,9 @@ class MessageGroup extends react_1.default.Component {
|
|
|
43
43
|
}) },
|
|
44
44
|
avatar,
|
|
45
45
|
react_1.default.createElement("div", { role: "region", className: 'bpw-message-container' },
|
|
46
|
-
react_1.default.createElement("div", { "aria-live": "assertive", role: "log", className: 'bpw-message-group'
|
|
46
|
+
react_1.default.createElement("div", { "aria-live": "assertive", role: "log", className: (0, classnames_1.default)('bpw-message-group', {
|
|
47
|
+
'bpw-message-group-selected': !!this.props.messages.find((m) => m.id === this.props.selectedMessageId)
|
|
48
|
+
}) },
|
|
47
49
|
react_1.default.createElement("span", { "data-from": fromLabel, className: "from hidden", "aria-hidden": "true" }, fromLabel),
|
|
48
50
|
(0, sortBy_1.default)(messages, ['sent_on', 'eventId']).map((message, i, messages) => {
|
|
49
51
|
const isLastMsg = i === messages.length - 1;
|
|
@@ -56,5 +58,6 @@ class MessageGroup extends react_1.default.Component {
|
|
|
56
58
|
exports.default = (0, mobx_react_1.inject)(({ store }) => ({
|
|
57
59
|
store,
|
|
58
60
|
sendFeedback: store.sendFeedback,
|
|
59
|
-
sendData: store.sendData
|
|
61
|
+
sendData: store.sendData,
|
|
62
|
+
selectedMessageId: store.selectedMessageId
|
|
60
63
|
}))(MessageGroup);
|
package/dist/core/socket.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { Message, MessagingSocket } from '@botpress/messaging-socket';
|
|
2
2
|
import { Config } from '../typings';
|
|
3
3
|
export default class BpSocket {
|
|
4
|
+
private config;
|
|
4
5
|
socket: MessagingSocket;
|
|
5
6
|
private chatId;
|
|
6
7
|
onMessage: (event: any) => void;
|
|
7
8
|
constructor(config: Config);
|
|
8
9
|
setup(): void;
|
|
9
10
|
sendPayload(payload: any): Promise<Message>;
|
|
10
|
-
postToParent: (_type: string, payload: any) => void;
|
|
11
11
|
connect(): Promise<void>;
|
|
12
|
+
reload(config: Config): Promise<void>;
|
|
13
|
+
private getCreds;
|
|
12
14
|
}
|
package/dist/core/socket.js
CHANGED
|
@@ -10,12 +10,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
const messaging_socket_1 = require("@botpress/messaging-socket");
|
|
13
|
+
const webchatEvents_1 = require("../utils/webchatEvents");
|
|
13
14
|
class BpSocket {
|
|
14
15
|
constructor(config) {
|
|
15
|
-
this.
|
|
16
|
-
var _a;
|
|
17
|
-
(_a = window.parent) === null || _a === void 0 ? void 0 : _a.postMessage(Object.assign(Object.assign({}, payload), { chatId: this.chatId }), '*');
|
|
18
|
-
};
|
|
16
|
+
this.config = config;
|
|
19
17
|
this.chatId = config.chatId;
|
|
20
18
|
this.socket = new messaging_socket_1.MessagingSocket({ url: config.messagingUrl, clientId: config.clientId });
|
|
21
19
|
window.websocket = this.socket;
|
|
@@ -32,14 +30,28 @@ class BpSocket {
|
|
|
32
30
|
}
|
|
33
31
|
connect() {
|
|
34
32
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
-
const creds =
|
|
33
|
+
const creds = this.getCreds();
|
|
36
34
|
yield this.socket.connect(creds);
|
|
37
35
|
if (this.socket.userId) {
|
|
38
36
|
const userId = this.socket.userId;
|
|
39
37
|
window.BP_STORAGE.set('creds', this.socket.creds);
|
|
40
|
-
|
|
38
|
+
(0, webchatEvents_1.postMessageToParent)('USER.CONNECTED', { userId }, this.chatId);
|
|
41
39
|
}
|
|
42
40
|
});
|
|
43
41
|
}
|
|
42
|
+
reload(config) {
|
|
43
|
+
var _a;
|
|
44
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
this.config = config;
|
|
46
|
+
const creds = this.getCreds();
|
|
47
|
+
if ((creds === null || creds === void 0 ? void 0 : creds.userId) !== this.socket.userId || (creds === null || creds === void 0 ? void 0 : creds.userToken) !== ((_a = this.socket.creds) === null || _a === void 0 ? void 0 : _a.userToken)) {
|
|
48
|
+
yield this.socket.disconnect();
|
|
49
|
+
yield this.connect();
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
getCreds() {
|
|
54
|
+
return this.config.customUser || window.BP_STORAGE.get('creds');
|
|
55
|
+
}
|
|
44
56
|
}
|
|
45
57
|
exports.default = BpSocket;
|
package/dist/main.d.ts
CHANGED
|
@@ -10,4 +10,4 @@ declare const _default: React.ForwardRefExoticComponent<import("react-intl").Omi
|
|
|
10
10
|
export default _default;
|
|
11
11
|
declare type MainProps = {
|
|
12
12
|
store?: RootStore;
|
|
13
|
-
} & WrappedComponentProps & Pick<StoreDef, 'config' | 'initializeChat' | 'botInfo' | 'fetchBotInfo' | 'sendMessage' | 'sendData' | 'intl' | 'updateTyping' | 'updateBotUILanguage' | 'hideChat' | 'showChat' | 'toggleBotInfo' | 'widgetTransition' | 'activeView' | 'isFullscreen' | 'unreadCount' | 'hasUnreadMessages' | 'showWidgetButton' | 'addEventToConversation' | 'clearMessages' | 'updateConfig' | 'mergeConfig' | 'isWebchatReady' | 'incrementUnread' | 'displayWidgetView' | 'resetUnread' | 'setLoadingCompleted' | 'dimensions' | 'updateLastMessage' | 'fetchConversation' | 'setIntlProvider' | 'setSocket' | 'currentConversationId'>;
|
|
13
|
+
} & WrappedComponentProps & Pick<StoreDef, 'config' | 'initializeChat' | 'botInfo' | 'fetchBotInfo' | 'sendMessage' | 'sendData' | 'intl' | 'updateTyping' | 'updateBotUILanguage' | 'hideChat' | 'showChat' | 'toggleBotInfo' | 'widgetTransition' | 'activeView' | 'isFullscreen' | 'unreadCount' | 'hasUnreadMessages' | 'showWidgetButton' | 'addEventToConversation' | 'clearMessages' | 'updateConfig' | 'mergeConfig' | 'isWebchatReady' | 'incrementUnread' | 'displayWidgetView' | 'resetUnread' | 'setLoadingCompleted' | 'dimensions' | 'updateLastMessage' | 'fetchConversation' | 'createConversation' | 'setIntlProvider' | 'setSocket' | 'currentConversationId' | 'currentConversation' | 'resetConversation'>;
|
package/dist/main.js
CHANGED
|
@@ -34,7 +34,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
34
34
|
exports.DEFAULT_TYPING_DELAY = void 0;
|
|
35
35
|
const classnames_1 = __importDefault(require("classnames"));
|
|
36
36
|
const debounce_1 = __importDefault(require("lodash/debounce"));
|
|
37
|
-
const set_1 = __importDefault(require("lodash/set"));
|
|
38
37
|
const mobx_1 = require("mobx");
|
|
39
38
|
const mobx_react_1 = require("mobx-react");
|
|
40
39
|
const query_string_1 = __importDefault(require("query-string"));
|
|
@@ -46,6 +45,7 @@ const socket_1 = __importDefault(require("./core/socket"));
|
|
|
46
45
|
const Chat_1 = __importDefault(require("./icons/Chat"));
|
|
47
46
|
const utils_1 = require("./utils");
|
|
48
47
|
const analytics_1 = require("./utils/analytics");
|
|
48
|
+
const webchatEvents_1 = require("./utils/webchatEvents");
|
|
49
49
|
exports.DEFAULT_TYPING_DELAY = 1000;
|
|
50
50
|
class Web extends react_1.default.Component {
|
|
51
51
|
constructor(props) {
|
|
@@ -68,7 +68,14 @@ class Web extends react_1.default.Component {
|
|
|
68
68
|
case 'configure':
|
|
69
69
|
return this.props.updateConfig(Object.assign({}, constants_1.default.DEFAULT_CONFIG, data.payload));
|
|
70
70
|
case 'mergeConfig':
|
|
71
|
-
|
|
71
|
+
this.props.mergeConfig(data.payload);
|
|
72
|
+
const oldUserId = this.socket.socket.userId;
|
|
73
|
+
yield this.socket.reload(data.payload);
|
|
74
|
+
if (this.socket.socket.userId !== oldUserId) {
|
|
75
|
+
this.props.resetConversation();
|
|
76
|
+
yield this.props.initializeChat();
|
|
77
|
+
}
|
|
78
|
+
return;
|
|
72
79
|
case 'sendPayload':
|
|
73
80
|
return this.props.sendData(data.payload);
|
|
74
81
|
case 'event':
|
|
@@ -86,12 +93,14 @@ class Web extends react_1.default.Component {
|
|
|
86
93
|
(0, analytics_1.trackWebchatState)('toggle');
|
|
87
94
|
}
|
|
88
95
|
else if (type === 'message') {
|
|
89
|
-
(0, analytics_1.trackMessage)('sent');
|
|
90
96
|
yield this.props.sendMessage(text);
|
|
91
97
|
}
|
|
92
98
|
else if (type === 'loadConversation') {
|
|
93
99
|
yield this.props.fetchConversation(conversationId);
|
|
94
100
|
}
|
|
101
|
+
else if (type === 'createConversation') {
|
|
102
|
+
yield this.props.createConversation();
|
|
103
|
+
}
|
|
95
104
|
else if (type === 'toggleBotInfo') {
|
|
96
105
|
this.props.toggleBotInfo();
|
|
97
106
|
}
|
|
@@ -103,7 +112,7 @@ class Web extends react_1.default.Component {
|
|
|
103
112
|
}
|
|
104
113
|
});
|
|
105
114
|
this.handleNewMessage = (event) => __awaiter(this, void 0, void 0, function* () {
|
|
106
|
-
var _b;
|
|
115
|
+
var _b, _c, _d;
|
|
107
116
|
if (!this.isCurrentConversation(event)) {
|
|
108
117
|
// don't do anything, it's a message from another conversation
|
|
109
118
|
return;
|
|
@@ -116,7 +125,15 @@ class Web extends react_1.default.Component {
|
|
|
116
125
|
// don't do anything, it's the system message
|
|
117
126
|
return;
|
|
118
127
|
}
|
|
119
|
-
(0
|
|
128
|
+
if (((_c = this.props.currentConversation) === null || _c === void 0 ? void 0 : _c.userId) !== event.authorId) {
|
|
129
|
+
(0, analytics_1.trackMessage)('received');
|
|
130
|
+
(0, webchatEvents_1.postMessageToParent)('MESSAGE.RECEIVED', event, this.props.config.chatId);
|
|
131
|
+
// This is to handle a special case for the emulator, setting the selected css class to the last message group
|
|
132
|
+
// This needs a rethinking
|
|
133
|
+
if (event.id) {
|
|
134
|
+
(_d = this.props.store) === null || _d === void 0 ? void 0 : _d.setSelectedMessage(event.id);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
120
137
|
this.props.updateLastMessage(event.conversationId, event);
|
|
121
138
|
yield this.props.addEventToConversation(event);
|
|
122
139
|
// there's no focus on the actual conversation
|
|
@@ -130,8 +147,8 @@ class Web extends react_1.default.Component {
|
|
|
130
147
|
yield this.props.updateTyping(event);
|
|
131
148
|
});
|
|
132
149
|
this.playSound = (0, debounce_1.default)(() => __awaiter(this, void 0, void 0, function* () {
|
|
133
|
-
var
|
|
134
|
-
const disableNotificationSound = this.config.disableNotificationSound || ((
|
|
150
|
+
var _e;
|
|
151
|
+
const disableNotificationSound = this.config.disableNotificationSound || ((_e = this.props.config) === null || _e === void 0 ? void 0 : _e.disableNotificationSound);
|
|
135
152
|
if (disableNotificationSound || this.audio.readyState < 2) {
|
|
136
153
|
return;
|
|
137
154
|
}
|
|
@@ -185,12 +202,9 @@ class Web extends react_1.default.Component {
|
|
|
185
202
|
return __awaiter(this, void 0, void 0, function* () {
|
|
186
203
|
this.config = this.extractConfig();
|
|
187
204
|
this.props.updateConfig(this.config);
|
|
188
|
-
|
|
189
|
-
const storePath = this.config.chatId ? `${this.config.chatId}.webchat_store` : 'webchat_store';
|
|
190
|
-
(0, set_1.default)(window.parent, storePath, this.props.store);
|
|
191
|
-
}
|
|
205
|
+
// is this necessary ?
|
|
192
206
|
if (this.config.containerWidth) {
|
|
193
|
-
|
|
207
|
+
(0, webchatEvents_1.postMessageToParent)('UI.RESIZE', this.config.containerWidth, this.config.chatId);
|
|
194
208
|
}
|
|
195
209
|
yield this.props.fetchBotInfo();
|
|
196
210
|
if (!this.isLazySocket()) {
|
|
@@ -199,10 +213,6 @@ class Web extends react_1.default.Component {
|
|
|
199
213
|
this.setupObserver();
|
|
200
214
|
});
|
|
201
215
|
}
|
|
202
|
-
postMessageToParent(type, value) {
|
|
203
|
-
var _a;
|
|
204
|
-
(_a = window.parent) === null || _a === void 0 ? void 0 : _a.postMessage({ type, value, chatId: this.config.chatId }, '*');
|
|
205
|
-
}
|
|
206
216
|
extractConfig() {
|
|
207
217
|
let userConfig = Object.assign({}, constants_1.default.DEFAULT_CONFIG, this.props.config);
|
|
208
218
|
const { options } = query_string_1.default.parse(location.search);
|
|
@@ -232,7 +242,8 @@ class Web extends react_1.default.Component {
|
|
|
232
242
|
setupObserver() {
|
|
233
243
|
(0, mobx_1.observe)(this.props.dimensions, 'container', (data) => {
|
|
234
244
|
if (data.newValue) {
|
|
235
|
-
this
|
|
245
|
+
// is this necessary ?
|
|
246
|
+
(0, webchatEvents_1.postMessageToParent)('UI.RESIZE', data.newValue, this.config.chatId);
|
|
236
247
|
}
|
|
237
248
|
});
|
|
238
249
|
}
|
|
@@ -260,8 +271,8 @@ class Web extends react_1.default.Component {
|
|
|
260
271
|
[(_a = this.props.config) === null || _a === void 0 ? void 0 : _a.className]: !!((_b = this.props.config) === null || _b === void 0 ? void 0 : _b.className)
|
|
261
272
|
});
|
|
262
273
|
if (this.parentClass !== parentClass) {
|
|
263
|
-
this.postMessageToParent('setClass', parentClass);
|
|
264
274
|
this.parentClass = parentClass;
|
|
275
|
+
(0, webchatEvents_1.postMessageToParent)('UI.SET-CLASS', parentClass, this.config.chatId);
|
|
265
276
|
}
|
|
266
277
|
const stylesheet = this.props.config.stylesheet;
|
|
267
278
|
const extraStylesheet = (_c = this.props.botInfo) === null || _c === void 0 ? void 0 : _c.extraStylesheet;
|
|
@@ -316,7 +327,10 @@ exports.default = (0, mobx_react_1.inject)(({ store }) => ({
|
|
|
316
327
|
sendFeedback: store.sendFeedback,
|
|
317
328
|
updateLastMessage: store.updateLastMessage,
|
|
318
329
|
fetchConversation: store.fetchConversation,
|
|
330
|
+
createConversation: store.createConversation,
|
|
319
331
|
setIntlProvider: store.setIntlProvider,
|
|
320
332
|
setSocket: store.setSocket,
|
|
321
|
-
|
|
333
|
+
currentConversation: store.currentConversation,
|
|
334
|
+
currentConversationId: store.currentConversationId,
|
|
335
|
+
resetConversation: store.resetConversation
|
|
322
336
|
}))((0, react_intl_1.injectIntl)((0, mobx_react_1.observer)(Web)));
|
package/dist/store/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ declare class RootStore {
|
|
|
13
13
|
private api;
|
|
14
14
|
conversations: RecentConversation[];
|
|
15
15
|
currentConversation?: CurrentConversation;
|
|
16
|
+
selectedMessageId?: string;
|
|
16
17
|
botInfo: BotInfo;
|
|
17
18
|
config: Config;
|
|
18
19
|
preferredLanguage: string;
|
|
@@ -27,6 +28,7 @@ declare class RootStore {
|
|
|
27
28
|
}, config?: Config);
|
|
28
29
|
setIntlProvider(provider: IntlShape): void;
|
|
29
30
|
setSocket(socket: BpSocket): void;
|
|
31
|
+
setSelectedMessage(messageId: string): void;
|
|
30
32
|
get isConversationStarted(): boolean;
|
|
31
33
|
get botName(): string;
|
|
32
34
|
get hasBotInfoDescription(): boolean;
|
|
@@ -35,7 +37,6 @@ declare class RootStore {
|
|
|
35
37
|
get escapeHTML(): boolean;
|
|
36
38
|
get currentMessages(): Message[];
|
|
37
39
|
get currentConversationId(): uuid | undefined;
|
|
38
|
-
postMessage(name: string, payload?: any): void;
|
|
39
40
|
updateMessages(messages: Message[]): void;
|
|
40
41
|
updateLastMessage(conversationId: string, message?: Message): void;
|
|
41
42
|
clearMessages(): void;
|
|
@@ -51,7 +52,7 @@ declare class RootStore {
|
|
|
51
52
|
/** Fetch the specified conversation ID, or try to fetch a valid one from the list */
|
|
52
53
|
fetchConversation(convoId?: uuid): Promise<uuid | undefined>;
|
|
53
54
|
/** Sends the specified message, or fetch the message in the composer */
|
|
54
|
-
sendMessage(
|
|
55
|
+
sendMessage(textMessage?: string): Promise<void>;
|
|
55
56
|
/** Sends an event to start conversation & hide the bot info page */
|
|
56
57
|
startConversation(): Promise<void>;
|
|
57
58
|
/** Creates a new conversation and switches to it */
|
|
@@ -61,7 +62,7 @@ declare class RootStore {
|
|
|
61
62
|
sendFeedback(feedback: number, messageId: string): Promise<void>;
|
|
62
63
|
downloadConversation(): Promise<void>;
|
|
63
64
|
/** Sends an event or a message, depending on how the backend manages those types */
|
|
64
|
-
sendData(data: any): Promise<void>;
|
|
65
|
+
sendData(data: any): Promise<Message | void>;
|
|
65
66
|
/** Sends a message of type voice */
|
|
66
67
|
sendVoiceMessage(voice: Buffer, ext: string): Promise<void>;
|
|
67
68
|
/** Use this method to replace a value or add a new config */
|
|
@@ -69,7 +70,6 @@ declare class RootStore {
|
|
|
69
70
|
/** This replaces all the configurations by this object */
|
|
70
71
|
updateConfig(config: Config): void;
|
|
71
72
|
private _applyConfig;
|
|
72
|
-
publishConfigChanged(): void;
|
|
73
73
|
updatePreferredLanguage(lang: string): void;
|
|
74
74
|
/** Starts a timer to remove the typing animation when it's completed */
|
|
75
75
|
private _startTypingTimer;
|
package/dist/store/index.js
CHANGED
|
@@ -30,6 +30,7 @@ const main_1 = require("../main");
|
|
|
30
30
|
const translations_1 = require("../translations");
|
|
31
31
|
const utils_1 = require("../utils");
|
|
32
32
|
const analytics_1 = require("../utils/analytics");
|
|
33
|
+
const webchatEvents_1 = require("../utils/webchatEvents");
|
|
33
34
|
const composer_1 = __importDefault(require("./composer"));
|
|
34
35
|
const view_1 = __importDefault(require("./view"));
|
|
35
36
|
class RootStore {
|
|
@@ -50,6 +51,9 @@ class RootStore {
|
|
|
50
51
|
setSocket(socket) {
|
|
51
52
|
this.api = new api_1.default(socket);
|
|
52
53
|
}
|
|
54
|
+
setSelectedMessage(messageId) {
|
|
55
|
+
this.selectedMessageId = messageId;
|
|
56
|
+
}
|
|
53
57
|
get isConversationStarted() {
|
|
54
58
|
var _a;
|
|
55
59
|
return !!((_a = this.currentConversation) === null || _a === void 0 ? void 0 : _a.messages.length);
|
|
@@ -81,10 +85,6 @@ class RootStore {
|
|
|
81
85
|
var _a;
|
|
82
86
|
return (_a = this.currentConversation) === null || _a === void 0 ? void 0 : _a.id;
|
|
83
87
|
}
|
|
84
|
-
postMessage(name, payload) {
|
|
85
|
-
const chatId = this.config.chatId;
|
|
86
|
-
window.parent.postMessage({ name, chatId, payload }, '*');
|
|
87
|
-
}
|
|
88
88
|
updateMessages(messages) {
|
|
89
89
|
if (this.currentConversation) {
|
|
90
90
|
this.currentConversation.messages = messages;
|
|
@@ -160,7 +160,7 @@ class RootStore {
|
|
|
160
160
|
yield this.fetchConversation();
|
|
161
161
|
(0, mobx_1.runInAction)('-> setInitialized', () => {
|
|
162
162
|
this.isInitialized = true;
|
|
163
|
-
|
|
163
|
+
(0, webchatEvents_1.postMessageToParent)('LIFECYCLE.READY', undefined, this.config.chatId);
|
|
164
164
|
});
|
|
165
165
|
}
|
|
166
166
|
catch (err) {
|
|
@@ -229,23 +229,24 @@ class RootStore {
|
|
|
229
229
|
});
|
|
230
230
|
}
|
|
231
231
|
/** Sends the specified message, or fetch the message in the composer */
|
|
232
|
-
sendMessage(
|
|
232
|
+
sendMessage(textMessage) {
|
|
233
233
|
return __awaiter(this, void 0, void 0, function* () {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
const userMessage = this.composer.message;
|
|
238
|
-
if (!userMessage || !userMessage.length) {
|
|
234
|
+
textMessage = textMessage || this.composer.message;
|
|
235
|
+
if (!textMessage) {
|
|
239
236
|
return;
|
|
240
237
|
}
|
|
241
238
|
this.composer.updateMessage('');
|
|
242
239
|
try {
|
|
243
|
-
yield this.sendData({ type: 'text', text:
|
|
240
|
+
const message = yield this.sendData({ type: 'text', text: textMessage });
|
|
244
241
|
(0, analytics_1.trackMessage)('sent');
|
|
245
|
-
|
|
242
|
+
if (message) {
|
|
243
|
+
(0, webchatEvents_1.postMessageToParent)('MESSAGE.SENT', message, this.config.chatId);
|
|
244
|
+
}
|
|
245
|
+
this.composer.addMessageToHistory(textMessage);
|
|
246
246
|
}
|
|
247
247
|
catch (e) {
|
|
248
|
-
this.composer.updateMessage(
|
|
248
|
+
this.composer.updateMessage(textMessage);
|
|
249
|
+
console.error('Webchat cloud not send message');
|
|
249
250
|
throw e;
|
|
250
251
|
}
|
|
251
252
|
});
|
|
@@ -328,6 +329,7 @@ class RootStore {
|
|
|
328
329
|
}
|
|
329
330
|
const message = yield this.api.sendMessage(data, this.currentConversationId);
|
|
330
331
|
this.updateLastMessage(this.currentConversationId, message);
|
|
332
|
+
return message;
|
|
331
333
|
});
|
|
332
334
|
}
|
|
333
335
|
/** Sends a message of type voice */
|
|
@@ -364,10 +366,7 @@ class RootStore {
|
|
|
364
366
|
const locale = (0, translations_1.getUserLocale)(this.config.locale);
|
|
365
367
|
this.updateBotUILanguage(locale);
|
|
366
368
|
document.documentElement.setAttribute('lang', locale);
|
|
367
|
-
this.
|
|
368
|
-
}
|
|
369
|
-
publishConfigChanged() {
|
|
370
|
-
this.postMessage('configChanged', JSON.stringify(this.config, undefined, 2));
|
|
369
|
+
(0, webchatEvents_1.postMessageToParent)('CONFIG.SET', Object.assign({}, this.config), this.config.chatId);
|
|
371
370
|
}
|
|
372
371
|
updatePreferredLanguage(lang) {
|
|
373
372
|
this.preferredLanguage = lang;
|
|
@@ -439,6 +438,9 @@ __decorate([
|
|
|
439
438
|
__decorate([
|
|
440
439
|
mobx_1.observable
|
|
441
440
|
], RootStore.prototype, "currentConversation", void 0);
|
|
441
|
+
__decorate([
|
|
442
|
+
mobx_1.observable
|
|
443
|
+
], RootStore.prototype, "selectedMessageId", void 0);
|
|
442
444
|
__decorate([
|
|
443
445
|
mobx_1.observable
|
|
444
446
|
], RootStore.prototype, "botInfo", void 0);
|
|
@@ -463,6 +465,9 @@ __decorate([
|
|
|
463
465
|
__decorate([
|
|
464
466
|
mobx_1.action.bound
|
|
465
467
|
], RootStore.prototype, "setSocket", null);
|
|
468
|
+
__decorate([
|
|
469
|
+
mobx_1.action.bound
|
|
470
|
+
], RootStore.prototype, "setSelectedMessage", null);
|
|
466
471
|
__decorate([
|
|
467
472
|
mobx_1.computed
|
|
468
473
|
], RootStore.prototype, "isConversationStarted", null);
|
|
@@ -487,9 +492,6 @@ __decorate([
|
|
|
487
492
|
__decorate([
|
|
488
493
|
mobx_1.computed
|
|
489
494
|
], RootStore.prototype, "currentConversationId", null);
|
|
490
|
-
__decorate([
|
|
491
|
-
mobx_1.action.bound
|
|
492
|
-
], RootStore.prototype, "postMessage", null);
|
|
493
495
|
__decorate([
|
|
494
496
|
mobx_1.action.bound
|
|
495
497
|
], RootStore.prototype, "updateMessages", null);
|
|
@@ -556,9 +558,6 @@ __decorate([
|
|
|
556
558
|
__decorate([
|
|
557
559
|
mobx_1.action.bound
|
|
558
560
|
], RootStore.prototype, "updateConfig", null);
|
|
559
|
-
__decorate([
|
|
560
|
-
mobx_1.action.bound
|
|
561
|
-
], RootStore.prototype, "publishConfigChanged", null);
|
|
562
561
|
__decorate([
|
|
563
562
|
mobx_1.action.bound
|
|
564
563
|
], RootStore.prototype, "updatePreferredLanguage", null);
|
package/dist/store/view.js
CHANGED
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
const merge_1 = __importDefault(require("lodash/merge"));
|
|
13
13
|
const mobx_1 = require("mobx");
|
|
14
14
|
const constants_1 = __importDefault(require("../core/constants"));
|
|
15
|
+
const webchatEvents_1 = require("../utils/webchatEvents");
|
|
15
16
|
class ViewStore {
|
|
16
17
|
constructor(rootStore, fullscreen) {
|
|
17
18
|
/** If false, probably embedded on a website or on the studio */
|
|
@@ -111,7 +112,7 @@ class ViewStore {
|
|
|
111
112
|
}
|
|
112
113
|
setLoadingCompleted() {
|
|
113
114
|
this._isLoading = false;
|
|
114
|
-
this.rootStore.
|
|
115
|
+
(0, webchatEvents_1.postMessageToParent)('LIFECYCLE.LOADED', undefined, this.rootStore.config.chatId);
|
|
115
116
|
}
|
|
116
117
|
showPoweredBy() {
|
|
117
118
|
this.isPoweredByDisplayed = true;
|
|
@@ -157,7 +158,7 @@ class ViewStore {
|
|
|
157
158
|
showChat() {
|
|
158
159
|
if (this.disableAnimations) {
|
|
159
160
|
this.activeView = 'side';
|
|
160
|
-
this.rootStore.
|
|
161
|
+
(0, webchatEvents_1.postMessageToParent)('UI.OPENED', undefined, this.rootStore.config.chatId);
|
|
161
162
|
return this._updateTransitions({ widgetTransition: undefined, sideTransition: 'none' });
|
|
162
163
|
}
|
|
163
164
|
this._updateTransitions({ widgetTransition: 'fadeOut' });
|
|
@@ -165,7 +166,7 @@ class ViewStore {
|
|
|
165
166
|
this._updateTransitions({ sideTransition: 'fadeIn' });
|
|
166
167
|
}, constants_1.default.ANIMATION_DURATION + 10);
|
|
167
168
|
this._endAnimation('side');
|
|
168
|
-
this.rootStore.
|
|
169
|
+
(0, webchatEvents_1.postMessageToParent)('UI.OPENED', undefined, this.rootStore.config.chatId);
|
|
169
170
|
}
|
|
170
171
|
hideChat() {
|
|
171
172
|
if (this.isFullscreen) {
|
|
@@ -173,7 +174,7 @@ class ViewStore {
|
|
|
173
174
|
}
|
|
174
175
|
if (this.disableAnimations) {
|
|
175
176
|
this.activeView = 'widget';
|
|
176
|
-
this.rootStore.
|
|
177
|
+
(0, webchatEvents_1.postMessageToParent)('UI.CLOSED', undefined, this.rootStore.config.chatId);
|
|
177
178
|
return this._updateTransitions({ widgetTransition: undefined, sideTransition: undefined });
|
|
178
179
|
}
|
|
179
180
|
this._updateTransitions({ sideTransition: 'fadeOut' });
|
|
@@ -183,7 +184,7 @@ class ViewStore {
|
|
|
183
184
|
}, constants_1.default.ANIMATION_DURATION + 10);
|
|
184
185
|
}
|
|
185
186
|
this._endAnimation('widget');
|
|
186
|
-
this.rootStore.
|
|
187
|
+
(0, webchatEvents_1.postMessageToParent)('UI.CLOSED', undefined, this.rootStore.config.chatId);
|
|
187
188
|
}
|
|
188
189
|
_endAnimation(finalView) {
|
|
189
190
|
setTimeout(() => {
|
package/dist/typings.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
+
import { UserCredentials } from '@botpress/messaging-socket';
|
|
2
3
|
import { RootStore } from './store';
|
|
3
4
|
import { BPStorage } from './utils/storage';
|
|
4
5
|
declare global {
|
|
@@ -35,7 +36,7 @@ export declare namespace Renderer {
|
|
|
35
36
|
isLastMessage?: boolean;
|
|
36
37
|
sentOn?: Date;
|
|
37
38
|
inlineFeedback?: any;
|
|
38
|
-
onSendData?: (data: any) => Promise<void>;
|
|
39
|
+
onSendData?: (data: any) => Promise<Message | void>;
|
|
39
40
|
onFileUpload?: (label: string, payload: any, file: File) => Promise<void>;
|
|
40
41
|
/** Allows to autoplay voice messages coming from the bot */
|
|
41
42
|
onAudioEnded?: () => void;
|
|
@@ -135,11 +136,27 @@ export interface StudioConnector {
|
|
|
135
136
|
getModuleInjector: any;
|
|
136
137
|
loadModuleView: any;
|
|
137
138
|
}
|
|
139
|
+
export declare type WebchatEventType = 'LIFECYCLE.LOADED' | 'LIFECYCLE.READY' | 'UI.OPENED' | 'UI.CLOSED' | 'UI.RESIZE' | 'UI.SET-CLASS' | 'CONFIG.SET' | 'MESSAGE.SENT' | 'MESSAGE.RECEIVED' | 'MESSAGE.SELECTED' | 'USER.CONNECTED';
|
|
140
|
+
export interface WebchatEvent {
|
|
141
|
+
type: WebchatEventType;
|
|
142
|
+
value: any;
|
|
143
|
+
chatId: string;
|
|
144
|
+
}
|
|
138
145
|
export interface Config {
|
|
139
146
|
/** Url of the messaging server */
|
|
140
147
|
messagingUrl: string;
|
|
141
148
|
/** Id of your messaging client */
|
|
142
149
|
clientId: string;
|
|
150
|
+
/**
|
|
151
|
+
* Refers to a specific webchat reference in parent window. Useful when using multiple chat window
|
|
152
|
+
* @default 'bp-web-widget'
|
|
153
|
+
*/
|
|
154
|
+
chatId: string;
|
|
155
|
+
/**
|
|
156
|
+
* Url where the webchat bundle is hosted
|
|
157
|
+
* @default: '/'
|
|
158
|
+
*/
|
|
159
|
+
hostUrl?: string;
|
|
143
160
|
/**
|
|
144
161
|
* Url of the Media File Service where we fetch the bot info
|
|
145
162
|
* @default ''
|
|
@@ -250,22 +267,12 @@ export interface Config {
|
|
|
250
267
|
* Experimental: expose the store to the parent frame for more control on the webchat's behavior
|
|
251
268
|
* @default false
|
|
252
269
|
*/
|
|
253
|
-
exposeStore?: boolean;
|
|
254
|
-
/**
|
|
255
|
-
* If true, Websocket is created when the Webchat is opened. Bot cannot be proactive.
|
|
256
|
-
* @default false
|
|
257
|
-
*/
|
|
258
270
|
lazySocket?: boolean;
|
|
259
271
|
/**
|
|
260
272
|
* If true, chat will no longer play the notification sound for new messages.
|
|
261
273
|
* @default false
|
|
262
274
|
*/
|
|
263
275
|
disableNotificationSound?: boolean;
|
|
264
|
-
/**
|
|
265
|
-
* Refers to a specific webchat reference in parent window. Useful when using multiple chat window
|
|
266
|
-
* @default ''
|
|
267
|
-
*/
|
|
268
|
-
chatId?: string;
|
|
269
276
|
/**
|
|
270
277
|
* CSS class to be applied to iframe
|
|
271
278
|
* @default ''
|
|
@@ -277,6 +284,10 @@ export interface Config {
|
|
|
277
284
|
* @default ''
|
|
278
285
|
*/
|
|
279
286
|
googleMapsAPIKey?: string;
|
|
287
|
+
/**
|
|
288
|
+
* Allows setting a custom user id
|
|
289
|
+
*/
|
|
290
|
+
customUser?: UserCredentials;
|
|
280
291
|
}
|
|
281
292
|
export interface BotDetails {
|
|
282
293
|
website?: string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.postMessageToParent = void 0;
|
|
7
|
+
const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
|
|
8
|
+
const postMessageToParent = (type, value, chatId) => {
|
|
9
|
+
var _a;
|
|
10
|
+
//cloneDeep necessary because of potentially nested mobx proxy object isn't serializable
|
|
11
|
+
const evt = { type, value: (0, cloneDeep_1.default)(value), chatId };
|
|
12
|
+
(_a = window.parent) === null || _a === void 0 ? void 0 : _a.postMessage(evt, '*');
|
|
13
|
+
};
|
|
14
|
+
exports.postMessageToParent = postMessageToParent;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botpress/webchat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"source": "src/index.tsx",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@blueprintjs/core": "^3.23.1",
|
|
32
|
-
"@botpress/messaging-components": "0.
|
|
33
|
-
"@botpress/messaging-socket": "1.
|
|
32
|
+
"@botpress/messaging-components": "0.4.2",
|
|
33
|
+
"@botpress/messaging-socket": "1.2.0",
|
|
34
34
|
"@formatjs/intl-pluralrules": "^4.1.6",
|
|
35
35
|
"@formatjs/intl-utils": "^3.8.4",
|
|
36
36
|
"@juggle/resize-observer": "^3.0.2",
|